import { useState } from 'react';
import { LocalTaskComment } from '../../api';
import { ChatMessage } from './ChatMessage';
import { isThinkingComment } from './thinkingUtils';
import { MarkdownText } from '../../lib/markdown-text';
import { ToolCallsSection, parseToolCallComment, type ToolCallData } from './ToolCallsSection';

interface ProgressData {
  movement: string;
  tools: Record<string, number>;
  durationMs: number;
  summary?: string;
}

function tryParseMovementComplete(body: string): ProgressData | null {
  try {
    const data = JSON.parse(body);
    if (data && typeof data.movement === 'string' && typeof data.durationMs === 'number' && typeof data.tools === 'object') {
      return data as ProgressData;
    }
  } catch { /* not movement JSON */ }
  return null;
}

function isMovementCompleteComment(c: LocalTaskComment): boolean {
  return c.kind === 'progress' && tryParseMovementComplete(c.body) !== null;
}

function isToolCallComment(c: LocalTaskComment): boolean {
  return c.kind === 'progress' && parseToolCallComment(c.body) !== null;
}

function getThinkingText(c: LocalTaskComment): string | null {
  try {
    const data = JSON.parse(c.body);
    if (data && data.type === 'thinking' && typeof data.text === 'string') {
      return data.text;
    }
  } catch { /* not thinking */ }
  return null;
}

export type ChatItem =
  | { type: 'comment'; comment: LocalTaskComment }
  | { type: 'movement'; movementName: string; summary: ProgressData; inner: LocalTaskComment[]; completionComment: LocalTaskComment };

export function groupCommentsByMovement(comments: LocalTaskComment[]): ChatItem[] {
  const items: ChatItem[] = [];
  let pendingInner: LocalTaskComment[] = [];

  const isUserComment = (c: LocalTaskComment) =>
    c.kind === 'request' || c.kind === 'comment' || c.kind === 'interjection';

  for (const c of comments) {
    if (isMovementCompleteComment(c)) {
      const summary = tryParseMovementComplete(c.body)!;
      items.push({
        type: 'movement',
        movementName: summary.movement,
        summary,
        inner: pendingInner,
        completionComment: c,
      });
      pendingInner = [];
    } else if (isUserComment(c)) {
      if (pendingInner.length > 0) {
        for (const p of pendingInner) {
          items.push({ type: 'comment', comment: p });
        }
        pendingInner = [];
      }
      items.push({ type: 'comment', comment: c });
    } else {
      pendingInner.push(c);
    }
  }
  for (const p of pendingInner) {
    items.push({ type: 'comment', comment: p });
  }
  return items;
}

function formatDuration(ms: number): string {
  if (ms < 1000) return `${ms}ms`;
  const sec = Math.round(ms / 1000);
  if (sec < 60) return `${sec}s`;
  const min = Math.floor(sec / 60);
  return `${min}m ${sec % 60}s`;
}

function getPreviewText(item: ChatItem & { type: 'movement' }): string | null {
  if (item.summary.summary) return item.summary.summary;
  for (let i = item.inner.length - 1; i >= 0; i--) {
    const text = getThinkingText(item.inner[i]!);
    if (text) return text;
  }
  return null;
}

interface MovementGroupExpandedProps {
  item: ChatItem & { type: 'movement' };
  taskId: number;
  isLast: boolean;
  isRunning: boolean;
  animatingIdx: number;
  startIdx: number;
}

export function MovementGroupExpanded({ item, taskId, animatingIdx, startIdx }: MovementGroupExpandedProps) {
  const [expanded, setExpanded] = useState(false);
  const { movementName, summary, inner } = item;
  const previewText = getPreviewText(item);

  return (
    <div className="flex flex-col">
      {/* Header — always visible */}
      <button
        onClick={() => setExpanded(!expanded)}
        className="flex items-start gap-2 text-left py-1.5 hover:bg-surface/50 rounded -mx-1 px-1 transition-colors group"
      >
        <svg
          className={`w-3.5 h-3.5 mt-0.5 flex-shrink-0 text-slate-400 transition-transform ${expanded ? 'rotate-90' : ''}`}
          viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"
        >
          <path d="M6 4l4 4-4 4" />
        </svg>
        <div className="min-w-0 flex-1">
          <div className="flex items-center gap-2">
            <span className="text-xs font-semibold text-slate-700">{movementName}</span>
            <span className="text-[10px] text-slate-400 font-mono tabular-nums">{formatDuration(summary.durationMs)}</span>
          </div>
        </div>
      </button>

      {/* Collapsed: summary full text */}
      {!expanded && previewText && (
        <div className="ml-5 mt-0.5 mb-1">
          <div className="text-xs text-slate-600 leading-relaxed">
            <MarkdownText text={previewText} />
          </div>
        </div>
      )}

      {/* Expanded: render inner comments in chronological order. Consecutive
          tool_call comments are merged into one ToolCallsSection so the
          expanded view matches what users saw while the movement was running. */}
      {expanded && (() => {
        type Block =
          | { kind: 'comment'; comment: LocalTaskComment; origIdx: number }
          | { kind: 'tools'; toolCalls: ToolCallData[]; firstId: number };
        const blocks: Block[] = [];
        let toolBuf: ToolCallData[] = [];
        let toolFirstId = 0;
        const flushTools = () => {
          if (toolBuf.length > 0) {
            blocks.push({ kind: 'tools', toolCalls: toolBuf, firstId: toolFirstId });
            toolBuf = [];
          }
        };
        for (let i = 0; i < inner.length; i++) {
          const c = inner[i]!;
          const tc = isToolCallComment(c) ? parseToolCallComment(c.body) : null;
          if (tc) {
            if (toolBuf.length === 0) toolFirstId = c.id;
            toolBuf.push(tc);
          } else {
            flushTools();
            blocks.push({ kind: 'comment', comment: c, origIdx: i });
          }
        }
        flushTools();

        if (blocks.length === 0) {
          return (
            <div className="ml-5 mt-1 mb-1 border-l-2 border-slate-100 pl-3">
              <div className="text-[10px] text-slate-400 py-1">中間出力なし</div>
            </div>
          );
        }
        return (
          <div className="ml-5 mt-1 mb-1 flex flex-col gap-3 border-l-2 border-slate-100 pl-3">
            {blocks.map((b) =>
              b.kind === 'comment' ? (
                <ChatMessage
                  key={`c-${b.comment.id}`}
                  comment={b.comment}
                  taskId={taskId}
                  isStaleThinking={isThinkingComment(b.comment) && (startIdx + b.origIdx) !== animatingIdx}
                />
              ) : (
                <ToolCallsSection key={`t-${b.firstId}`} toolCalls={b.toolCalls} />
              ),
            )}
          </div>
        );
      })()}
    </div>
  );
}
