import type { LogicNode } from './strategyTypes';
import { generateNodeId } from './strategyTypes';
import { subtreeToFlatOrphans } from './strategyFlowLayout';
import {
  DEFAULT_START_CANDLE,
  DEFAULT_START_COMBINE_OP,
  START_NODE_ID,
  createStartNodeId,
  defaultStartMeta,
  normalizeStartCandleType,
  type StartCombineOp,
  type StartNodeMeta,
} from './strategyStartNodes';

export type EditorConditionState = {
  root: LogicNode | null;
  startMeta: Record<string, StartNodeMeta>;
  extraStartIds: string[];
  extraRoots: Record<string, LogicNode | null>;
  /** START 2개 이상일 때 분기 결합 (기본 AND) */
  startCombineOp?: StartCombineOp;
};

export type { StartCombineOp };

export type ConditionBranch = {
  candleType: string;
  root: LogicNode | null;
};

export type StartSection = {
  startId: string;
  candleType: string;
  root: LogicNode | null;
  canDelete: boolean;
};

export function collectStartSections(state: EditorConditionState): StartSection[] {
  const sections: StartSection[] = [{
    startId: START_NODE_ID,
    candleType: normalizeStartCandleType(state.startMeta[START_NODE_ID]?.candleType),
    root: state.root,
    canDelete: false,
  }];
  for (const startId of state.extraStartIds) {
    sections.push({
      startId,
      candleType: normalizeStartCandleType(state.startMeta[startId]?.candleType),
      root: state.extraRoots[startId] ?? null,
      canDelete: true,
    });
  }
  return sections;
}

export function hasMultipleStartSections(state: EditorConditionState): boolean {
  return state.extraStartIds.length >= 1;
}

export function normalizeStartCombineOp(value: string | undefined | null): StartCombineOp {
  return value === 'OR' ? 'OR' : DEFAULT_START_COMBINE_OP;
}

export function updateStartCombineOp(
  state: EditorConditionState,
  op: StartCombineOp,
): EditorConditionState {
  return { ...state, startCombineOp: op };
}

export function updateBranchRoot(
  state: EditorConditionState,
  startId: string,
  root: LogicNode | null,
): EditorConditionState {
  if (startId === START_NODE_ID) {
    return { ...state, root };
  }
  return {
    ...state,
    extraRoots: { ...state.extraRoots, [startId]: root },
  };
}

export function updateStartCandleType(
  state: EditorConditionState,
  startId: string,
  candleType: string,
): EditorConditionState {
  return {
    ...state,
    startMeta: {
      ...state.startMeta,
      [startId]: { candleType: normalizeStartCandleType(candleType) },
    },
  };
}

export function addExtraStartSection(state: EditorConditionState): EditorConditionState {
  const startId = createStartNodeId();
  return {
    ...state,
    extraStartIds: [...state.extraStartIds, startId],
    startMeta: {
      ...state.startMeta,
      [startId]: { candleType: DEFAULT_START_CANDLE },
    },
    extraRoots: { ...state.extraRoots, [startId]: null },
  };
}

export function removeStartSection(
  state: EditorConditionState,
  startId: string,
): { state: EditorConditionState; orphanedNodes: LogicNode[] } {
  if (startId === START_NODE_ID) {
    return { state, orphanedNodes: [] };
  }
  const branch = state.extraRoots[startId];
  const nextMeta = { ...state.startMeta };
  delete nextMeta[startId];
  const nextRoots = { ...state.extraRoots };
  delete nextRoots[startId];
  return {
    state: {
      ...state,
      startMeta: nextMeta,
      extraStartIds: state.extraStartIds.filter(id => id !== startId),
      extraRoots: nextRoots,
    },
    orphanedNodes: branch ? subtreeToFlatOrphans(branch) : [],
  };
}

export function emptyEditorConditionState(): EditorConditionState {
  return {
    root: null,
    startMeta: defaultStartMeta(),
    extraStartIds: [],
    extraRoots: {},
    startCombineOp: DEFAULT_START_COMBINE_OP,
  };
}

function wrapTimeframe(candleType: string, root: LogicNode): LogicNode {
  return {
    id: generateNodeId(),
    type: 'TIMEFRAME',
    candleType: normalizeStartCandleType(candleType),
    children: [root],
  };
}

/** 편집기 상태 → 저장/평가용 DSL (TIMEFRAME 래핑) */
export function encodeConditionForSave(state: EditorConditionState): LogicNode | null {
  const branches = collectEditorBranches(state).filter(b => b.root != null) as Array<{
    candleType: string;
    root: LogicNode;
  }>;

  if (branches.length === 0) return null;
  if (branches.length === 1) {
    const { candleType, root } = branches[0];
    if (normalizeStartCandleType(candleType) === DEFAULT_START_CANDLE) return root;
    return wrapTimeframe(candleType, root);
  }

  const combineOp = normalizeStartCombineOp(state.startCombineOp);
  return {
    id: generateNodeId(),
    type: combineOp,
    children: branches.map(b => wrapTimeframe(b.candleType, b.root)),
  };
}

function parseMultiStartWrapper(dsl: LogicNode): EditorConditionState | null {
  if (dsl.type !== 'AND' && dsl.type !== 'OR') return null;
  const children = dsl.children ?? [];
  const allTimeframe = children.length > 0 && children.every(c => c.type === 'TIMEFRAME');
  if (!allTimeframe) return null;

  const startMeta: Record<string, StartNodeMeta> = {};
  const extraStartIds: string[] = [];
  const extraRoots: Record<string, LogicNode | null> = {};
  let primaryRoot: LogicNode | null = null;

  children.forEach((tf, index) => {
    const candleType = normalizeStartCandleType(tf.candleType);
    const branchRoot = tf.children?.[0] ?? null;
    if (index === 0) {
      startMeta[START_NODE_ID] = { candleType };
      primaryRoot = branchRoot;
      return;
    }
    const startId = createStartNodeId();
    startMeta[startId] = { candleType };
    extraStartIds.push(startId);
    extraRoots[startId] = branchRoot;
  });

  return {
    root: primaryRoot,
    startMeta,
    extraStartIds,
    extraRoots,
    startCombineOp: dsl.type as StartCombineOp,
  };
}

/** DSL → 편집기 상태 (TIMEFRAME / AND|OR+TIMEFRAME 분해) */
export function decodeConditionForEditor(dsl: LogicNode | null): EditorConditionState {
  if (!dsl) return emptyEditorConditionState();

  const multiStart = parseMultiStartWrapper(dsl);
  if (multiStart) return multiStart;

  if (dsl.type === 'TIMEFRAME') {
    return {
      root: dsl.children?.[0] ?? null,
      startMeta: {
        [START_NODE_ID]: { candleType: normalizeStartCandleType(dsl.candleType) },
      },
      extraStartIds: [],
      extraRoots: {},
      startCombineOp: DEFAULT_START_COMBINE_OP,
    };
  }

  return {
    root: dsl,
    startMeta: defaultStartMeta(),
    extraStartIds: [],
    extraRoots: {},
    startCombineOp: DEFAULT_START_COMBINE_OP,
  };
}

/** Logic Expression / 미리보기용 — START별 평가 분봉과 서브트리 */
export function collectEditorBranches(state: EditorConditionState): ConditionBranch[] {
  const branches: ConditionBranch[] = [];
  const primaryCt = state.startMeta[START_NODE_ID]?.candleType ?? DEFAULT_START_CANDLE;
  if (state.root) branches.push({ candleType: primaryCt, root: state.root });

  for (const startId of state.extraStartIds) {
    const root = state.extraRoots[startId] ?? null;
    if (root) {
      branches.push({
        candleType: state.startMeta[startId]?.candleType ?? DEFAULT_START_CANDLE,
        root,
      });
    }
  }
  return branches;
}

/** 저장된 DSL에서 Logic Expression용 분기 목록 */
export function collectDslBranches(dsl: LogicNode | null): ConditionBranch[] {
  return collectEditorBranches(decodeConditionForEditor(dsl));
}
