import {
  CheckCircleFilled,
  CloseCircleFilled,
  LoadingOutlined,
} from '@ant-design/icons';
import type { ChatConversationRequest } from './types';

export type ActivityChecklistState = 'complete' | 'current' | 'pending' | 'error';

export type ActivityChecklistEntry = {
  key: string;
  label: string;
  state: ActivityChecklistState;
};

type ActivityChecklistSourceEntry = {
  key: string;
  label: string;
  checked: boolean;
};

function getEntryStateLabel(entry: ActivityChecklistEntry) {
  if (entry.state === 'complete') {
    return '완료';
  }

  if (entry.state === 'current') {
    return '진행중';
  }

  if (entry.state === 'error') {
    return '확인필요';
  }

  return '대기';
}

function normalizeLines(lines: string[]) {
  return lines.map((line) => String(line ?? '').trim()).filter(Boolean);
}

function parseDirectiveChecklistEntries(lines: string[]) {
  const entriesByLabel = new Map<string, ActivityChecklistSourceEntry>();
  const labelOrder: string[] = [];

  lines.forEach((line, index) => {
    const match = line.match(/^(☐|☑)\s+(.+)$/u);

    if (!match) {
      return;
    }

    const [, marker, rawLabel] = match;
    const label = rawLabel.trim();

    if (!label) {
      return;
    }

    if (!entriesByLabel.has(label)) {
      labelOrder.push(label);
    }

    entriesByLabel.set(label, {
      key: `directive-${index}`,
      label,
      checked: marker === '☑',
    });
  });

  return labelOrder
    .map((label) => entriesByLabel.get(label))
    .filter((entry): entry is ActivityChecklistSourceEntry => entry != null);
}

function extractProgressLabel(line: string) {
  if (!line.startsWith('# 진행:')) {
    return '';
  }

  const rawLabel = line.slice('# 진행:'.length).trim();
  const commandSeparatorIndex = rawLabel.indexOf(' $ ');
  if (commandSeparatorIndex < 0) {
    return '';
  }

  return rawLabel.slice(0, commandSeparatorIndex).trim();
}

function parseProgressChecklistEntries(lines: string[]) {
  const entriesByLabel = new Map<string, ActivityChecklistSourceEntry>();
  const labelOrder: string[] = [];

  lines.forEach((line, index) => {
    const label = extractProgressLabel(line);

    if (!label) {
      return;
    }

    if (!entriesByLabel.has(label)) {
      labelOrder.push(label);
    }

    entriesByLabel.set(label, {
      key: `progress-${index}`,
      label,
      checked: false,
    });
  });

  return labelOrder
    .map((label) => entriesByLabel.get(label))
    .filter((entry): entry is ActivityChecklistSourceEntry => entry != null);
}

function buildChecklistSourceEntries(lines: string[]) {
  const directiveEntries = parseDirectiveChecklistEntries(lines);

  if (directiveEntries.length > 0) {
    return {
      entries: directiveEntries,
      hasExplicitCheckedState: true,
    };
  }

  return {
    entries: parseProgressChecklistEntries(lines),
    hasExplicitCheckedState: false,
  };
}

export function buildChatActivityChecklistEntries(lines: string[], request?: ChatConversationRequest) {
  const { entries: sourceEntries, hasExplicitCheckedState } = buildChecklistSourceEntries(lines);

  if (sourceEntries.length === 0) {
    return [];
  }

  const lastUncheckedIndex = sourceEntries.findIndex((entry) => !entry.checked);
  const currentEntryIndex =
    request?.status === 'failed' || request?.status === 'cancelled' || request?.status === 'removed'
      ? Math.max(lastUncheckedIndex, 0)
      : lastUncheckedIndex;
  const isTerminalComplete = request?.status === 'completed';
  const isTerminalError = request?.status === 'failed' || request?.status === 'cancelled' || request?.status === 'removed';

  return sourceEntries.map<ActivityChecklistEntry>((entry, index) => {
    let state: ActivityChecklistState = 'pending';

    if ((hasExplicitCheckedState && entry.checked) || isTerminalComplete) {
      state = 'complete';
    } else if (!hasExplicitCheckedState && currentEntryIndex > 0 && index < currentEntryIndex) {
      state = 'complete';
    } else if (isTerminalError && index === currentEntryIndex) {
      state = 'error';
    } else if (index === currentEntryIndex) {
      state = 'current';
    }

    return {
      key: entry.key,
      label: entry.label,
      state,
    };
  });
}
function resolveResultNote(request?: ChatConversationRequest) {
  const normalizedStatusMessage = String(request?.statusMessage ?? '').trim();

  if (request?.status === 'completed') {
    return normalizedStatusMessage || '응답과 결과 정리가 완료되었습니다.';
  }

  if (request?.status === 'failed') {
    return normalizedStatusMessage || '오류로 종료되었습니다.';
  }

  if (request?.status === 'cancelled') {
    return normalizedStatusMessage || '사용자 요청으로 중단되었습니다.';
  }

  if (request?.status === 'removed') {
    return normalizedStatusMessage || '요청 기록이 제거되었습니다.';
  }

  return normalizedStatusMessage || '최종 결과를 정리하는 단계입니다.';
}

function renderStateIcon(state: ActivityChecklistState) {
  if (state === 'complete') {
    return <CheckCircleFilled aria-hidden="true" />;
  }

  if (state === 'current') {
    return <LoadingOutlined aria-hidden="true" />;
  }

  if (state === 'error') {
    return <CloseCircleFilled aria-hidden="true" />;
  }
  return <LoadingOutlined aria-hidden="true" />;
}

function buildSummaryLabel(entries: ActivityChecklistEntry[]) {
  const completedCount = entries.filter((entry) => entry.state === 'complete').length;
  const currentEntry = entries.find((entry) => entry.state === 'current');
  const errorEntry = entries.find((entry) => entry.state === 'error');

  if (errorEntry) {
    return `${errorEntry.label} 단계에서 확인 필요`;
  }

  if (currentEntry) {
    return `${completedCount}/${entries.length} 완료 · ${currentEntry.label} 진행 중`;
  }

  if (completedCount === entries.length) {
    return '체크리스트 완료';
  }

  return `${completedCount}/${entries.length} 완료`;
}

function buildChecklistStatusLabel(request?: ChatConversationRequest) {
  if (request?.status === 'failed' || request?.status === 'cancelled' || request?.status === 'removed') {
    return resolveResultNote(request);
  }

  return '최초 작업지시 기준';
}

export function ChatActivityChecklist({
  lines,
  request,
  title,
  statusLabel,
}: {
  lines: string[];
  request?: ChatConversationRequest;
  title?: string;
  statusLabel?: string;
}) {
  if (lines.length === 0 && !request) {
    return null;
  }

  const normalizedLines = normalizeLines(lines);
  const entries = buildChatActivityChecklistEntries(normalizedLines, request);

  if (entries.length === 0) {
    return null;
  }

  return (
    <section className="app-chat-activity-checklist" aria-label="Plan 체크리스트">
      <div className="app-chat-activity-checklist__header">
        <div className="app-chat-activity-checklist__title-group">
          <span className="app-chat-activity-checklist__title">{title?.trim() || '최초 작업 계획 체크리스트'}</span>
          <span className="app-chat-activity-checklist__summary">{buildSummaryLabel(entries)}</span>
        </div>
        <span className="app-chat-activity-checklist__legend">
          <span>{statusLabel?.trim() || buildChecklistStatusLabel(request)}</span>
        </span>
      </div>
      <ol className="app-chat-activity-checklist__list">
        {entries.map((entry) => (
          <li
            key={entry.key}
            className={`app-chat-activity-checklist__item app-chat-activity-checklist__item--${entry.state}`}
            aria-current={entry.state === 'current' ? 'step' : undefined}
          >
            <span className="app-chat-activity-checklist__icon">{renderStateIcon(entry.state)}</span>
            <div className="app-chat-activity-checklist__content">
              <div className="app-chat-activity-checklist__row">
                <span className="app-chat-activity-checklist__label">{entry.label}</span>
                <span className="app-chat-activity-checklist__state">{getEntryStateLabel(entry)}</span>
              </div>
            </div>
          </li>
        ))}
      </ol>
    </section>
  );
}
