import { useMemo, type FormEvent } from 'react';
import type { GatewayTask } from '@easyai-ai-gateway/contracts';
import { BookOpen, Play, Search, Send } from 'lucide-react';
import { Badge, Button, Select, Textarea } from '../components/ui';
import type { ApiDocSection, LoadState, TaskForm } from '../types';

const docs: Array<{ key: ApiDocSection; group: string; method: string; path: string; title: string }> = [
  { key: 'chat', group: '聊天(Chat)', method: 'POST', path: '/v1/chat/completions', title: 'Chat(聊天)' },
  { key: 'imageGeneration', group: '图片', method: 'POST', path: '/v1/images/generations', title: '创建图片' },
  { key: 'imageEdit', group: '图片', method: 'POST', path: '/v1/images/edits', title: '编辑图片' },
  { key: 'pricing', group: '计费', method: 'POST', path: '/api/v1/pricing/estimate', title: '价格预估' },
  { key: 'files', group: '文件', method: 'POST', path: '/v1/files/upload', title: '上传文件' },
];

const guideItems = ['获取 Base URL 和 API Key', '通知设置-WebHook 参数介绍', '错误码', '测试模式'];

const taskKindOptions = [
  ['chat.completions', 'Chat'],
  ['images.generations', '生图'],
  ['images.edits', '图像编辑'],
] as const;

export function ApiDocsPage(props: {
  activeDocSection: ApiDocSection;
  apiKeySecret: string;
  canRun: boolean;
  coreMessage: string;
  coreState: LoadState;
  taskForm: TaskForm;
  taskResult: GatewayTask | null;
  onLogin: () => void;
  onDocSectionChange: (value: ApiDocSection) => void;
  onSubmitTask: (event: FormEvent<HTMLFormElement>) => void;
  onTaskFormChange: (value: TaskForm) => void;
}) {
  const current = docs.find((item) => item.key === props.activeDocSection) ?? docs[0];
  const bodyExample = useMemo(() => requestBodyExample(props.taskForm), [props.taskForm]);

  function handleSubmit(event: FormEvent<HTMLFormElement>) {
    if (!props.canRun) {
      event.preventDefault();
      props.onLogin();
      return;
    }
    props.onSubmitTask(event);
  }

  return (
    <div className="apiDocsShell">
      <aside className="docsSidebar">
        <div className="docsBrand">
          <BookOpen size={19} />
          <strong>API Docs</strong>
        </div>
        <label className="docsSearch">
          <Search size={15} />
          <input placeholder="搜索" />
        </label>
        <DocsGroup title="指南" items={guideItems.map((title) => ({ title }))} />
        {groupDocs(docs).map((group) => (
          <DocsGroup
            key={group.title}
            title={group.title}
            items={group.items.map((item) => ({
              active: item.key === props.activeDocSection,
              method: item.method,
              title: item.title,
              onClick: () => props.onDocSectionChange(item.key),
            }))}
          />
        ))}
      </aside>

      <main className="docsArticle">
        <p className="eyebrow">{current.group}</p>
        <h1>{current.title}</h1>
        <div className="endpointBar">
          <Badge variant="warning">{current.method}</Badge>
          <code>{current.path}</code>
        </div>
        <p className="docsLead">
          保持与原 integration-platform / OpenAI 兼容接口一致，支持本地 API Key 和 server-main 接入 token。
        </p>

        <section className="paramCard">
          <header>
            <h2>Header 参数</h2>
            <Button type="button" variant="secondary" size="sm">生成代码</Button>
          </header>
          <ParamRow name="Content-Type" type="string" required value="application/json" />
          <ParamRow name="Accept" type="string" required value="application/json" />
          <ParamRow name="Authorization" type="string" value="Bearer {{YOUR_API_KEY}}" />
        </section>

        <section className="paramCard">
          <header>
            <h2>Body 参数</h2>
            <Badge variant="outline">application/json</Badge>
          </header>
          <ParamRow name="model" type="string" required value="模型 ID 或别名" />
          <ParamRow name="messages / prompt" type="array|string" required value="对话消息或图片提示词" />
          <ParamRow name="simulation" type="boolean" value="测试模式开关" />
          <ParamRow name="stream" type="boolean" value="对话进度流式返回" />
        </section>
      </main>

      <aside className="docsRunner">
        <form onSubmit={handleSubmit}>
          <header>
            <strong>在线运行</strong>
            <Button type="submit" size="sm" disabled={props.canRun && props.coreState === 'loading'}>
              <Send size={14} />
              {props.canRun ? '发送' : '登录'}
            </Button>
          </header>
          <div className="runnerEndpoint">
            <Badge variant="warning">POST</Badge>
            <span>{current.path}</span>
          </div>
          <label className="shLabel">
            能力
            <Select value={props.taskForm.kind} onChange={(event) => props.onTaskFormChange(defaultTaskForKind(event.target.value as TaskForm['kind'], props.taskForm))}>
              {taskKindOptions.map(([value, label]) => (
                <option value={value} key={value}>{label}</option>
              ))}
            </Select>
          </label>
          <label className="shLabel">
            请求 Body
            <Textarea value={bodyExample} onChange={(event) => props.onTaskFormChange(parseBody(event.target.value, props.taskForm))} />
          </label>
          <Button type="submit" disabled={props.canRun && props.coreState === 'loading'}>
            <Play size={15} />
            {!props.canRun ? '登录后运行' : props.coreState === 'loading' ? '运行中' : '运行测试'}
          </Button>
        </form>
        <section className="runnerResult">
          <strong>返回结果</strong>
          {props.taskResult ? (
            <pre>{JSON.stringify(props.taskResult.result ?? props.taskResult, null, 2)}</pre>
          ) : (
            <div className="emptyState">
              <span>点击发送获取返回结果</span>
            </div>
          )}
          {props.coreMessage && <p>{props.coreMessage}</p>}
        </section>
      </aside>
    </div>
  );
}

function DocsGroup(props: {
  items: Array<{ active?: boolean; method?: string; onClick?: () => void; title: string }>;
  title: string;
}) {
  return (
    <section className="docsGroup">
      <h3>{props.title}</h3>
      {props.items.map((item) => (
        <button type="button" data-active={item.active} key={item.title} onClick={item.onClick}>
          <span>{item.title}</span>
          {item.method && <Badge variant="warning">{item.method}</Badge>}
        </button>
      ))}
    </section>
  );
}

function ParamRow(props: { name: string; required?: boolean; type: string; value: string }) {
  return (
    <div className="paramRow">
      <code>{props.name}</code>
      <span>{props.type}</span>
      <p>{props.value}</p>
      <em>{props.required ? '必需' : '可选'}</em>
    </div>
  );
}

function groupDocs(items: typeof docs) {
  const groups = new Map<string, typeof docs>();
  for (const item of items) {
    groups.set(item.group, [...(groups.get(item.group) ?? []), item]);
  }
  return Array.from(groups, ([title, groupItems]) => ({ title, items: groupItems }));
}

function defaultTaskForKind(kind: TaskForm['kind'], current: TaskForm): TaskForm {
  if (kind === 'chat.completions') return { ...current, kind, model: 'gpt-4o-mini' };
  if (kind === 'images.edits') return { ...current, kind, image: current.image ?? 'https://example.com/source.png', mask: current.mask ?? 'https://example.com/mask.png', model: 'gpt-image-1' };
  return { ...current, kind, model: 'gpt-image-1' };
}

function requestBodyExample(task: TaskForm) {
  const body = task.kind === 'chat.completions'
    ? { model: task.model, messages: [{ role: 'user', content: task.prompt }], simulation: true, stream: true }
    : task.kind === 'images.edits'
      ? { model: task.model, prompt: task.prompt, image: task.image, mask: task.mask, simulation: true }
      : { model: task.model, prompt: task.prompt, quality: 'medium', simulation: true, size: '1024x1024' };
  return JSON.stringify(body, null, 2);
}

function parseBody(value: string, current: TaskForm): TaskForm {
  try {
    const body = JSON.parse(value) as {
      image?: string;
      mask?: string;
      messages?: Array<{ content?: string }>;
      model?: string;
      prompt?: string;
    };
    return {
      ...current,
      image: body.image ?? current.image,
      mask: body.mask ?? current.mask,
      model: body.model ?? current.model,
      prompt: body.prompt ?? body.messages?.[0]?.content ?? current.prompt,
    };
  } catch {
    return current;
  }
}
