import React from 'react';
import type { LogicNode } from '../../utils/strategyTypes';
import { nodeToText, type DefType } from '../../utils/strategyEditorShared';
import { getIndicatorPaletteCategory } from './paletteCategories';
import {
  collectEditorBranches,
  normalizeStartCombineOp,
  type EditorConditionState,
} from '../../utils/strategyConditionSerde';
import { formatStartCandleLabel } from '../../utils/strategyStartNodes';

interface Props {
  buyCondition: LogicNode | null;
  sellCondition: LogicNode | null;
  buyEditorState?: EditorConditionState;
  sellEditorState?: EditorConditionState;
  orphanCount: number;
  def: DefType;
}

function renderCondition(node: LogicNode, def: DefType): React.ReactNode {
  const full = nodeToText(node, def);
  const ind = node.condition?.indicatorType ?? '';
  const tail = ind && full.startsWith(`${ind} -`) ? full.slice(ind.length) : full;
  const cat = getIndicatorPaletteCategory(ind);

  return (
    <>
      <span className="se-formula-punc">(</span>
      {ind ? (
        <>
          <span className={`se-formula-ind se-formula-ind--${cat}`}>{ind}</span>
          {tail ? <span className="se-formula-detail">{tail}</span> : null}
        </>
      ) : (
        <span className="se-formula-detail">{full || '?'}</span>
      )}
      <span className="se-formula-punc">)</span>
    </>
  );
}

function renderNode(node: LogicNode, def: DefType): React.ReactNode {
  if (node.type === 'CONDITION') return renderCondition(node, def);

  if (node.type === 'AND') {
    const children = node.children ?? [];
    if (children.length === 0) return <span className="se-formula-empty">(빈 AND)</span>;
    return (
      <>
        <span className="se-formula-punc">(</span>
        {children.map((child, i) => (
          <React.Fragment key={child.id}>
            {i > 0 ? <span className="se-formula-logic se-formula-logic--and"> AND </span> : null}
            {renderNode(child, def)}
          </React.Fragment>
        ))}
        <span className="se-formula-punc">)</span>
      </>
    );
  }

  if (node.type === 'OR') {
    const children = node.children ?? [];
    if (children.length === 0) return <span className="se-formula-empty">(빈 OR)</span>;
    return (
      <>
        <span className="se-formula-punc">(</span>
        {children.map((child, i) => (
          <React.Fragment key={child.id}>
            {i > 0 ? <span className="se-formula-logic se-formula-logic--or"> OR </span> : null}
            {renderNode(child, def)}
          </React.Fragment>
        ))}
        <span className="se-formula-punc">)</span>
      </>
    );
  }

  if (node.type === 'NOT') {
    const child = node.children?.[0];
    return child ? (
      <>
        <span className="se-formula-logic se-formula-logic--not">NOT </span>
        {renderNode(child, def)}
      </>
    ) : (
      <span className="se-formula-empty">(빈 NOT)</span>
    );
  }

  if (node.type === 'TIMEFRAME') {
    const inner = node.children?.[0];
    const tf = formatStartCandleLabel(node.candleType ?? '1m');
    return inner ? (
      <>
        <span className="se-formula-tf">[{tf}]</span>
        {' '}
        {renderNode(inner, def)}
      </>
    ) : (
      <span className="se-formula-empty">[{tf} 빈 조건]</span>
    );
  }

  return null;
}

function renderSignalBranches(
  editorState: EditorConditionState | undefined,
  fallbackRoot: LogicNode | null,
  def: DefType,
): React.ReactNode {
  const branches = editorState
    ? collectEditorBranches(editorState)
    : fallbackRoot
      ? [{ candleType: '1m', root: fallbackRoot }]
      : [];

  if (branches.length === 0) {
    return <span className="se-formula-empty">(연결된 조건 없음)</span>;
  }

  if (branches.length === 1) {
    const { candleType, root } = branches[0];
    if (!root) return <span className="se-formula-empty">(연결된 조건 없음)</span>;
    return (
      <>
        <span className="se-formula-tf">[{formatStartCandleLabel(candleType)}]</span>
        {' '}
        {renderNode(root, def)}
      </>
    );
  }

  const combineOp = normalizeStartCombineOp(editorState?.startCombineOp);
  const combineClass = combineOp === 'AND' ? 'se-formula-logic--and' : 'se-formula-logic--or';

  return (
    <>
      <span className="se-formula-punc">(</span>
      {branches.map((branch, i) => (
        <React.Fragment key={`${branch.candleType}-${i}`}>
          {i > 0 ? (
            <span className={`se-formula-logic ${combineClass}`}> {combineOp} </span>
          ) : null}
          {branch.root ? (
            <>
              <span className="se-formula-tf">[{formatStartCandleLabel(branch.candleType)}]</span>
              {' '}
              {renderNode(branch.root, def)}
            </>
          ) : (
            <span className="se-formula-empty">[{formatStartCandleLabel(branch.candleType)} 빈 조건]</span>
          )}
        </React.Fragment>
      ))}
      <span className="se-formula-punc">)</span>
    </>
  );
}

export default function LogicExpressionPreview({
  buyCondition,
  sellCondition,
  buyEditorState,
  sellEditorState,
  orphanCount,
  def,
}: Props) {
  const hasBody = buyCondition || sellCondition
    || (buyEditorState && collectEditorBranches(buyEditorState).some(b => b.root))
    || (sellEditorState && collectEditorBranches(sellEditorState).some(b => b.root));

  return (
    <div className="se-terminal-text se-terminal-text--rich">
      {!hasBody && (
        <span className="se-formula-empty">(연결된 조건을 구성하세요)</span>
      )}
      {(buyCondition || buyEditorState) && (
        <div className="se-formula-line">
          <span className="se-formula-signal se-formula-signal--buy">[매수]</span>
          {' '}
          {renderSignalBranches(buyEditorState, buyCondition, def)}
        </div>
      )}
      {(sellCondition || sellEditorState) && (
        <div className="se-formula-line">
          <span className="se-formula-signal se-formula-signal--sell">[매도]</span>
          {' '}
          {renderSignalBranches(sellEditorState, sellCondition, def)}
        </div>
      )}
      {orphanCount > 0 && (
        <div className="se-formula-line se-formula-comment">
          {'// 미연결 요소 '}{orphanCount}{'개 — 전략 코드 미포함'}
        </div>
      )}
    </div>
  );
}
