import { useState } from 'react';
import { FileText, Terminal, Pencil, Search, Globe, Wrench, ChevronRight } from 'lucide-react';
import type { ChatMessage } from '../types';
import { CopyButton } from './CopyButton';

type ToolMessage = Extract<ChatMessage, { role: 'tool' }>;

type ToolActivityProps = {
  message: ToolMessage;
};

const toolIcons: Record<string, typeof FileText> = {
  Read: FileText,
  Edit: Pencil,
  Write: Pencil,
  Bash: Terminal,
  Grep: Search,
  Glob: Search,
  WebFetch: Globe,
  WebSearch: Globe,
};

function getToolSummary(toolName: string, toolInput: Record<string, unknown>): string {
  switch (toolName) {
    case 'Read':
    case 'Edit':
    case 'Write':
      return (toolInput.file_path as string) ?? '';
    case 'Bash':
      return truncate((toolInput.command as string) ?? '', 80);
    case 'Grep':
    case 'Glob':
      return (toolInput.pattern as string) ?? '';
    case 'WebFetch':
      return (toolInput.url as string) ?? '';
    case 'WebSearch':
      return (toolInput.query as string) ?? '';
    default:
      return (
        Object.values(toolInput)
          .find((v) => typeof v === 'string')
          ?.toString() ?? ''
      );
  }
}

function truncate(str: string, max: number): string {
  return str.length > max ? str.slice(0, max) + '...' : str;
}

export const ToolActivity = ({ message }: ToolActivityProps) => {
  const [open, setOpen] = useState(false);

  const Icon = toolIcons[message.toolName] ?? Wrench;
  const summary = getToolSummary(message.toolName, message.toolInput);
  const pending = message.output === undefined;
  const isError = message.isError === true;

  return (
    <div className="my-1">
      <button
        onClick={() => setOpen(!open)}
        className="flex items-center gap-2 w-full text-left px-3 py-1.5 rounded-md hover:bg-duck-dark/5 transition-colors cursor-pointer text-sm"
      >
        <ChevronRight className={`h-3 w-3 shrink-0 transition-transform ${open ? 'rotate-90' : ''}`} />
        <Icon className="h-4 w-4 shrink-0 text-duck-teal" />
        <span className="font-medium text-duck-dark/80">{message.toolName}</span>
        <span className="text-duck-dark/50 truncate flex-1 font-mono text-xs">{summary}</span>
        <span className="shrink-0">
          {pending && <span className="inline-block h-2 w-2 rounded-full bg-amber-400 animate-pulse" />}
          {!pending && !isError && <span className="text-green-600 text-xs">done</span>}
          {!pending && isError && <span className="text-red-600 text-xs">error</span>}
        </span>
      </button>

      {open && (
        <div className="ml-7 mt-1 space-y-2 text-xs">
          <div className="rounded-md bg-duck-dark/5 p-2 overflow-x-auto group/input">
            <div className="flex items-center justify-between mb-1">
              <div className="text-duck-dark/50 text-[10px] uppercase tracking-wider">Input</div>
              <CopyButton
                text={message.toolName === 'Bash'
                  ? (message.toolInput.command as string) ?? JSON.stringify(message.toolInput, null, 2)
                  : Object.entries(message.toolInput).map(([k, v]) => `${k}: ${typeof v === 'string' ? v : JSON.stringify(v)}`).join('\n')}
                className="!opacity-0 group-hover/input:!opacity-60 hover:!opacity-100"
              />
            </div>
            {message.toolName === 'Bash' ? (
              <pre className="bg-gray-900 text-green-400 p-2 rounded font-mono whitespace-pre-wrap break-all">
                {(message.toolInput.command as string) ?? JSON.stringify(message.toolInput, null, 2)}
              </pre>
            ) : (
              <pre className="font-mono whitespace-pre-wrap break-all text-duck-dark/70">
                {Object.entries(message.toolInput)
                  .map(([k, v]) => `${k}: ${typeof v === 'string' ? v : JSON.stringify(v)}`)
                  .join('\n')}
              </pre>
            )}
          </div>

          {message.output !== undefined && (
            <div className="rounded-md bg-duck-dark/5 p-2 overflow-x-auto group/output">
              <div className="flex items-center justify-between mb-1">
                <div className="text-duck-dark/50 text-[10px] uppercase tracking-wider">Output</div>
                <CopyButton text={message.output} className="!opacity-0 group-hover/output:!opacity-60 hover:!opacity-100" />
              </div>
              <ToolOutput toolName={message.toolName} output={message.output} isError={isError} />
            </div>
          )}
        </div>
      )}
    </div>
  );
};

type ToolOutputProps = {
  toolName: string;
  output: string;
  isError: boolean;
};

const ToolOutput = ({ toolName, output, isError }: ToolOutputProps) => {
  const [expanded, setExpanded] = useState(false);
  const maxLines = 20;
  const lines = output.split('\n');
  const needsTruncation = lines.length > maxLines;
  const displayText = expanded ? output : lines.slice(0, maxLines).join('\n');

  const isBash = toolName === 'Bash';

  return (
    <>
      <pre
        className={`font-mono whitespace-pre-wrap break-all p-2 rounded ${
          isBash ? 'bg-gray-900 text-green-400' : isError ? 'bg-red-50 dark:bg-red-950/50 text-red-700 dark:text-red-300' : 'text-duck-dark/70'
        }`}
      >
        {displayText}
      </pre>
      {needsTruncation && (
        <button
          onClick={() => setExpanded(!expanded)}
          className="text-duck-teal hover:underline text-[11px] mt-1 cursor-pointer"
        >
          {expanded ? 'Show less' : `Show more (${lines.length - maxLines} more lines)`}
        </button>
      )}
    </>
  );
};
