import { CheckCircleFilled, CloseCircleFilled, LoadingOutlined } from "@ant-design/icons";
import { Collapse, Flex, Typography } from "antd";

import { HighlightBlock } from "./HighlightBlock";
import type { PartProps } from "./types";

interface ToolPartData {
  errorText?: string;
  input?: unknown;
  output?: unknown;
  toolCallId?: string;
  toolMetadata?: Record<string, unknown>;
  toolName?: string;
  type?: string;
}

function getToolState(part: ToolPartData) {
  if ("errorText" in part && part.errorText) return "output-error" as const;
  if ("output" in part) return "output-available" as const;
  if ("input" in part) return "input-available" as const;
  return "input-streaming" as const;
}

function getInputLang(value: unknown): string {
  return typeof value === "object" && value !== null ? "json" : "text";
}

function getOutputLang(value: unknown): string {
  return typeof value === "object" && value !== null ? "json" : "text";
}

function formatContent(value: unknown): string {
  if (typeof value === "object" && value !== null) return JSON.stringify(value, null, 2);
  if (typeof value === "string") return value;
  return String(value);
}

export function ToolPart({ part }: PartProps) {
  const toolPart = part as unknown as ToolPartData;
  const state = getToolState(toolPart);
  const rawToolName = toolPart.toolName ?? (toolPart.type ?? "unknown").replace(/^tool-/, "");
  const toolName =
    typeof toolPart.toolMetadata?.["displayName"] === "string" ? toolPart.toolMetadata["displayName"] : rawToolName;

  const isStreaming = state === "input-streaming" || state === "input-available";

  const formattedInput = toolPart.input != null ? formatContent(toolPart.input) : "";
  const inputLang = toolPart.input != null ? getInputLang(toolPart.input) : "text";

  const hasOutput = "output" in toolPart && toolPart.output != null;
  const formattedOutput = hasOutput ? formatContent(toolPart.output) : "";
  const outputLang = hasOutput ? getOutputLang(toolPart.output) : "text";

  if (state === "output-error") {
    return (
      <Collapse
        ghost
        items={[
          {
            children: (
              <div className="tool-call-section">
                <Typography.Text type="danger">错误</Typography.Text>
                <HighlightBlock code={toolPart.errorText!} isStreaming={false} lang="text" />
              </div>
            ),
            key: toolPart.toolCallId ?? toolName,
            label: (
              <Flex align="center" component="span" gap={4}>
                <CloseCircleFilled className="icon-error" />
                <Typography.Text type="danger">{toolName} 失败</Typography.Text>
              </Flex>
            ),
          },
        ]}
        size="small"
      />
    );
  }

  return (
    <Collapse
      defaultActiveKey={isStreaming ? [toolPart.toolCallId ?? toolName] : undefined}
      ghost
      items={[
        {
          children: (
            <Flex gap={8} vertical>
              {toolPart.input != null && (
                <div className="tool-call-section">
                  <Typography.Text type="secondary">入参</Typography.Text>
                  <HighlightBlock code={formattedInput} isStreaming={isStreaming} lang={inputLang} />
                </div>
              )}
              {hasOutput && (
                <div className="tool-call-section">
                  <Typography.Text type="secondary">出参</Typography.Text>
                  <HighlightBlock code={formattedOutput} isStreaming={isStreaming} lang={outputLang} />
                </div>
              )}
              {!toolPart.input && !("output" in toolPart) && (
                <Typography.Text type="secondary">生成中...</Typography.Text>
              )}
            </Flex>
          ),
          key: toolPart.toolCallId ?? toolName,
          label: isStreaming ? (
            <Flex align="center" component="span" gap={4}>
              <LoadingOutlined className="icon-primary" />
              <Typography.Text type="secondary">
                {state === "input-streaming" ? "生成参数" : `调用 ${toolName}`}
              </Typography.Text>
            </Flex>
          ) : (
            <Flex align="center" component="span" gap={4}>
              <CheckCircleFilled className="icon-success" />
              <Typography.Text type="secondary">{toolName}</Typography.Text>
            </Flex>
          ),
        },
      ]}
      size="small"
    />
  );
}
