import { useQuery } from "@tanstack/react-query";
import { Braces, Code2, Info, Link2 } from "lucide-react";
import { useState, type ReactNode } from "react";
import { Navigate, useParams } from "react-router-dom";
import { useTranslation } from "react-i18next";

import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { listModels } from "@/entities/model/model-api";
import type { ModelRouteDTO } from "@/entities/model/types";
import { getSystemInfo } from "@/entities/system/system-api";
import { runtimeConfig } from "@/shared/config/runtime-config";
import { CopyButton } from "@/shared/components/copy-button";
import { cn } from "@/shared/lib/cn";

type ExampleLanguage = "curl" | "python" | "javascript";
type ExampleView = "request" | "response";
type Method = "GET" | "POST";
type Capability = ModelRouteDTO["capability"];

type FieldDefinition = {
  name: string;
  required?: boolean;
  descriptionKey: string;
};

type EndpointDefinition = {
  key: string;
  category: string;
  title: string;
  method: Method;
  path: string;
  descriptionKey: string;
  capabilities: Capability[];
  fields: FieldDefinition[];
  noteKeys: string[];
  request: (model: string) => Record<string, unknown> | undefined;
  response: Record<string, unknown>;
};

const exampleLanguages: ExampleLanguage[] = ["curl", "python", "javascript"];

const endpoints: Record<string, EndpointDefinition> = {
  "chat/completions": {
    key: "chat/completions", category: "Chat", title: "Chat completions", method: "POST", path: "/chat/completions",
    descriptionKey: "docs.endpointChat", capabilities: ["chat", "responses"],
    fields: [
      { name: "model", required: true, descriptionKey: "docs.reference.fieldModel" },
      { name: "messages", required: true, descriptionKey: "docs.reference.fieldChatMessages" },
      { name: "stream", descriptionKey: "docs.reference.fieldStream" },
      { name: "max_completion_tokens", descriptionKey: "docs.reference.fieldMaxCompletionTokens" },
      { name: "tools", descriptionKey: "docs.reference.fieldTools" },
      { name: "tool_choice", descriptionKey: "docs.reference.fieldToolChoice" },
    ],
    noteKeys: ["docs.reference.noteChatImages", "docs.reference.noteChatTools"],
    request: (model) => ({ model, messages: [{ role: "system", content: "You are a concise assistant." }, { role: "user", content: "Explain HTTP streaming." }], stream: false }),
    response: { id: "chatcmpl_example", object: "chat.completion", model: "grok-chat-fast", choices: [{ index: 0, message: { role: "assistant", content: "HTTP streaming sends response data incrementally." }, finish_reason: "stop" }], usage: { prompt_tokens: 24, completion_tokens: 12, total_tokens: 36 } },
  },
  "chat/responses": {
    key: "chat/responses", category: "Chat", title: "Responses", method: "POST", path: "/responses",
    descriptionKey: "docs.endpointResponses", capabilities: ["chat", "responses"],
    fields: [
      { name: "model", required: true, descriptionKey: "docs.reference.fieldModel" },
      { name: "input", required: true, descriptionKey: "docs.reference.fieldInput" },
      { name: "instructions", descriptionKey: "docs.reference.fieldInstructions" },
      { name: "stream", descriptionKey: "docs.reference.fieldStream" },
      { name: "store", descriptionKey: "docs.reference.fieldStore" },
      { name: "previous_response_id", descriptionKey: "docs.reference.fieldPreviousResponse" },
      { name: "tools", descriptionKey: "docs.reference.fieldTools" },
    ],
    noteKeys: ["docs.reference.noteResponsesState", "docs.reference.noteResponsesCompact"],
    request: (model) => ({ model, input: "Explain HTTP streaming.", store: false, stream: false }),
    response: { id: "resp_example", object: "response", status: "completed", model: "grok-chat-fast", output: [{ type: "message", role: "assistant", status: "completed", content: [{ type: "output_text", text: "HTTP streaming sends response data incrementally." }] }], usage: { input_tokens: 18, output_tokens: 12, total_tokens: 30 } },
  },
  "chat/messages": {
    key: "chat/messages", category: "Chat", title: "Messages", method: "POST", path: "/messages",
    descriptionKey: "docs.endpointMessages", capabilities: ["chat", "responses"],
    fields: [
      { name: "model", required: true, descriptionKey: "docs.reference.fieldModel" },
      { name: "max_tokens", required: true, descriptionKey: "docs.reference.fieldMaxTokens" },
      { name: "messages", required: true, descriptionKey: "docs.reference.fieldMessages" },
      { name: "system", descriptionKey: "docs.reference.fieldSystem" },
      { name: "stream", descriptionKey: "docs.reference.fieldStream" },
      { name: "tools", descriptionKey: "docs.reference.fieldAnthropicTools" },
      { name: "tool_choice", descriptionKey: "docs.reference.fieldToolChoice" },
    ],
    noteKeys: ["docs.reference.noteMessagesEvents", "docs.reference.noteMessagesLimits"],
    request: (model) => ({ model, max_tokens: 1024, system: "You are a concise assistant.", messages: [{ role: "user", content: "Explain HTTP streaming." }], stream: false }),
    response: { id: "msg_example", type: "message", role: "assistant", model: "grok-chat-fast", content: [{ type: "text", text: "HTTP streaming sends response data incrementally." }], stop_reason: "end_turn", stop_sequence: null, usage: { input_tokens: 18, output_tokens: 12 } },
  },
  "image/generations": {
    key: "image/generations", category: "Image", title: "Image generations", method: "POST", path: "/images/generations",
    descriptionKey: "docs.endpointImageGeneration", capabilities: ["image"],
    fields: [
      { name: "model", required: true, descriptionKey: "docs.reference.fieldModel" },
      { name: "prompt", required: true, descriptionKey: "docs.reference.fieldPrompt" },
      { name: "n", descriptionKey: "docs.reference.fieldImageCount" },
      { name: "aspect_ratio", descriptionKey: "docs.reference.fieldAspectRatio" },
      { name: "resolution", descriptionKey: "docs.reference.fieldResolution" },
      { name: "response_format", descriptionKey: "docs.reference.fieldResponseFormat" },
      { name: "stream", descriptionKey: "docs.reference.fieldImageStream" },
    ],
    noteKeys: ["docs.reference.noteImageCount", "docs.reference.noteImageStorage"],
    request: (model) => ({ model, prompt: "A minimal red chair in a bright studio", n: 1, response_format: "url" }),
    response: { created: 1783860000, data: [{ url: "http://127.0.0.1:8000/v1/media/images/example" }] },
  },
  "image/edits": {
    key: "image/edits", category: "Image", title: "Image edits", method: "POST", path: "/images/edits",
    descriptionKey: "docs.endpointImageEdit", capabilities: ["image_edit"],
    fields: [
      { name: "model", required: true, descriptionKey: "docs.reference.fieldModel" },
      { name: "prompt", required: true, descriptionKey: "docs.reference.fieldPrompt" },
      { name: "image / images", required: true, descriptionKey: "docs.reference.fieldEditImages" },
      { name: "n", descriptionKey: "docs.reference.fieldImageCount" },
      { name: "response_format", descriptionKey: "docs.reference.fieldResponseFormat" },
    ],
    noteKeys: ["docs.reference.noteEditJSON", "docs.reference.noteEditSources", "docs.reference.noteImageStorage"],
    request: (model) => ({ model, prompt: "Change the chair to black", image: { url: "https://example.com/chair.png" }, n: 1, response_format: "url" }),
    response: { created: 1783860000, data: [{ url: "http://127.0.0.1:8000/v1/media/images/example" }] },
  },
  "video/generations": {
    key: "video/generations", category: "Video", title: "Video generations", method: "POST", path: "/videos/generations",
    descriptionKey: "docs.endpointVideoCreate", capabilities: ["video"],
    fields: [
      { name: "model", required: true, descriptionKey: "docs.reference.fieldModel" },
      { name: "prompt", descriptionKey: "docs.reference.fieldVideoPrompt" },
      { name: "duration", descriptionKey: "docs.reference.fieldDuration" },
      { name: "aspect_ratio", descriptionKey: "docs.reference.fieldAspectRatio" },
      { name: "resolution", descriptionKey: "docs.reference.fieldResolution" },
      { name: "image", descriptionKey: "docs.reference.fieldVideoImage" },
      { name: "reference_images", descriptionKey: "docs.reference.fieldReferenceImages" },
    ],
    noteKeys: ["docs.reference.noteVideoAsync", "docs.reference.noteVideoStrict"],
    request: (model) => ({ model, prompt: "A paper airplane flying over a city", duration: 8, aspect_ratio: "16:9", resolution: "720p" }),
    response: { request_id: "video_example" },
  },
  "video/get": {
    key: "video/get", category: "Video", title: "Get video", method: "GET", path: "/videos/{request_id}",
    descriptionKey: "docs.endpointVideoGet", capabilities: ["video"],
    fields: [{ name: "request_id", required: true, descriptionKey: "docs.reference.fieldRequestId" }],
    noteKeys: ["docs.reference.noteVideoPolling", "docs.reference.noteVideoStatus"],
    request: () => undefined,
    response: { status: "done", model: "grok-imagine-video", progress: 100, video: { url: "https://example.com/generated.mp4", duration: 8, respect_moderation: true } },
  },
};

export function ApiDocsPage() {
  const { t } = useTranslation();
  const { category, endpoint } = useParams();
  const definition = endpoints[`${category ?? ""}/${endpoint ?? ""}`];
  const [language, setLanguage] = useState<ExampleLanguage>("curl");
  const [exampleView, setExampleView] = useState<ExampleView>("request");
  const [selectedModel, setSelectedModel] = useState("");

  const systemQuery = useQuery({ queryKey: ["system-info"], queryFn: getSystemInfo, staleTime: Number.POSITIVE_INFINITY, retry: 1 });
  const modelsQuery = useQuery({ queryKey: ["docs", "available-models"], queryFn: () => listModels({ page: 1, pageSize: 100 }), staleTime: 30_000 });

  if (!definition) return <Navigate to="/docs/chat/completions" replace />;

  const publicApiBaseUrl = systemQuery.data?.publicApiBaseURL || runtimeConfig.publicApiBaseUrl;
  const baseUrl = `${publicApiBaseUrl.replace(/\/$/, "")}/v1`;
  const availableModels = (modelsQuery.data?.items ?? []).filter((model) => model.enabled && model.available && definition.capabilities.includes(model.capability));
  const selectedModelAvailable = availableModels.some((model) => model.publicId === selectedModel);
  const exampleModel = (selectedModelAvailable ? selectedModel : availableModels[0]?.publicId) || fallbackModel(definition.key);
  const examples = createExamples(definition, baseUrl, exampleModel);
  const responseExample = JSON.stringify(withExampleModel(definition.response, exampleModel), null, 2);

  return (
    <div className="w-full space-y-10">
      <header className="space-y-4">
        <div className="min-w-0">
          <h1 className="text-2xl font-medium text-foreground">{definition.title}</h1>
          <p className="mt-2 max-w-2xl text-sm leading-6 text-muted-foreground">{t(definition.descriptionKey)}</p>
        </div>
        <EndpointSignature method={definition.method} path={`/v1${definition.path}`} />
      </header>

      <div className="space-y-10">
        <DocsSection icon={<Link2 />} title={t("docs.reference.connection")}>
          <div className="grid gap-4 sm:grid-cols-2">
            <ConnectionItem label={t("docs.baseUrl")} value={baseUrl} />
            <ConnectionItem label={t("docs.authentication")} value={definition.key === "chat/messages" ? "x-api-key: g2a_..." : "Authorization: Bearer g2a_..."} />
            {definition.key === "chat/messages" ? <ConnectionItem label="anthropic-version" value="2023-06-01" /> : null}
          </div>
        </DocsSection>

        <DocsSection icon={<Braces />} title={definition.method === "GET" ? t("docs.reference.pathParameters") : t("docs.reference.requestBody")}>
          <div className="overflow-hidden rounded-md bg-card">
            <div className="hidden grid-cols-[minmax(120px,180px)_minmax(0,1fr)] gap-5 bg-secondary/35 px-4 py-2 text-xs text-muted-foreground sm:grid">
              <span>{t("docs.reference.parameter")}</span>
              <span>{t("docs.reference.description")}</span>
            </div>
            <div>{definition.fields.map((field, index) => <ParameterItem key={field.name} field={field} muted={index % 2 === 1} />)}</div>
          </div>
        </DocsSection>

        <DocsSection icon={<Code2 />} title={t("docs.reference.example")}>
          <ExamplePanel
            view={exampleView}
            onViewChange={setExampleView}
            language={language}
            onLanguageChange={setLanguage}
            code={exampleView === "request" ? examples[language] : responseExample}
            models={availableModels}
            selectedModel={exampleModel}
            onModelChange={setSelectedModel}
          />
        </DocsSection>

        {definition.noteKeys.length > 0 ? (
          <DocsSection icon={<Info />} title={t("docs.reference.notes")}>
            <ul className="space-y-2 rounded-md bg-secondary/35 px-4 py-3 text-xs leading-5 text-muted-foreground">
              {definition.noteKeys.map((key) => <li key={key} className="relative pl-3 before:absolute before:left-0 before:top-[0.55rem] before:size-1 before:rounded-full before:bg-muted-foreground/55">{t(key)}</li>)}
            </ul>
          </DocsSection>
        ) : null}
      </div>
    </div>
  );
}

function withExampleModel(response: Record<string, unknown>, model: string): Record<string, unknown> {
  return "model" in response ? { ...response, model } : response;
}

function fallbackModel(key: string): string {
  if (key.startsWith("image/")) return key === "image/edits" ? "grok-imagine-image-edit" : "grok-imagine-image";
  if (key.startsWith("video/")) return "grok-imagine-video";
  return "your-enabled-model";
}

function createExamples(definition: EndpointDefinition, baseUrl: string, model: string): Record<ExampleLanguage, string> {
  const request = definition.request(model);
  const url = `${baseUrl}${definition.path.replace("{request_id}", "video_example")}`;
  const messageHeaders = definition.key === "chat/messages";
  const curlHeaders = messageHeaders
    ? [
        '  -H "x-api-key: $GROK2API_API_KEY"',
        '  -H "anthropic-version: 2023-06-01"',
        '  -H "Content-Type: application/json"',
      ].join(" \\\n")
    : [
        '  -H "Authorization: Bearer $GROK2API_API_KEY"',
        '  -H "Content-Type: application/json"',
      ].join(" \\\n");
  const curlBody = request ? ` \\\n  -d '${JSON.stringify(request, null, 2)}'` : "";
  const headers = messageHeaders
    ? { "x-api-key": "g2a_your_api_key", "anthropic-version": "2023-06-01", "Content-Type": "application/json" }
    : { Authorization: "Bearer g2a_your_api_key", "Content-Type": "application/json" };
  const pythonImports = request ? "import json\nimport requests" : "import requests";
  const pythonPayload = request ? `\n\npayload = json.loads(r'''${JSON.stringify(request, null, 2)}''')` : "";
  const pythonBody = request ? ",\n    json=payload" : "";
  const javascriptBody = request ? `,\n  body: JSON.stringify(${JSON.stringify(request, null, 2)})` : "";
  return {
    curl: `export GROK2API_API_KEY="g2a_your_api_key"\n\ncurl -X ${definition.method} "${url}" \\\n${curlHeaders}${curlBody}`,
    python: `${pythonImports}${pythonPayload}\n\nresponse = requests.${definition.method.toLowerCase()}(\n    "${url}",\n    headers=${JSON.stringify(headers, null, 2)}${pythonBody}\n)\nresponse.raise_for_status()\nprint(response.json())`,
    javascript: `const response = await fetch("${url}", {\n  method: "${definition.method}",\n  headers: ${JSON.stringify(headers, null, 2)}${javascriptBody}\n});\n\nif (!response.ok) throw new Error(await response.text());\nconsole.log(await response.json());`,
  };
}

function MethodLabel({ method }: { method: Method }) {
  return <span className={cn("font-mono text-xs font-semibold", method === "GET" ? "text-emerald-600 dark:text-emerald-400" : "text-sky-600 dark:text-sky-400")}>{method}</span>;
}

function EndpointSignature({ method, path }: { method: Method; path: string }) {
  return (
    <div className="flex h-8 w-fit max-w-full items-center gap-2 rounded-md bg-card px-3">
      <MethodLabel method={method} />
      <code className="min-w-0 truncate text-xs" title={path}>{path}</code>
      <CopyButton value={path} />
    </div>
  );
}

function DocsSection({ icon, title, children }: { icon: ReactNode; title: string; children: ReactNode }) {
  return (
    <section className="space-y-3.5">
      <div className="flex items-center gap-2 text-sm font-medium [&_svg]:size-4 [&_svg]:text-muted-foreground">{icon}{title}</div>
      <div className="min-w-0">{children}</div>
    </section>
  );
}

function ConnectionItem({ label, value }: { label: string; value: string }) {
  return (
    <div className="min-w-0">
      <div className="mb-1.5 text-xs text-muted-foreground">{label}</div>
      <div className="flex h-8 min-w-0 items-center rounded-md bg-secondary/55 pl-3 pr-0.5">
        <code className="min-w-0 flex-1 truncate text-xs text-muted-foreground" title={value}>{value}</code>
        <CopyButton value={value} />
      </div>
    </div>
  );
}

function ParameterItem({ field, muted }: { field: FieldDefinition; muted: boolean }) {
  const { t } = useTranslation();
  return (
    <div className={cn("grid grid-cols-1 gap-1.5 px-4 py-3 sm:grid-cols-[minmax(120px,180px)_minmax(0,1fr)] sm:gap-5", muted && "bg-secondary/20")}>
      <div className="min-w-0">
        <code className="break-all text-xs font-medium text-foreground">
        {field.name}
        {field.required ? <span className="ml-1 text-destructive" title={t("docs.reference.required")}>*</span> : null}
        </code>
      </div>
      <div className="min-w-0 text-xs leading-5 text-muted-foreground">{t(field.descriptionKey)}</div>
    </div>
  );
}

function ExamplePanel({
  view,
  onViewChange,
  language,
  onLanguageChange,
  code,
  models,
  selectedModel,
  onModelChange,
}: {
  view: ExampleView;
  onViewChange: (view: ExampleView) => void;
  language: ExampleLanguage;
  onLanguageChange: (language: ExampleLanguage) => void;
  code: string;
  models: ModelRouteDTO[];
  selectedModel: string;
  onModelChange: (model: string) => void;
}) {
  const { t } = useTranslation();
  return (
    <div className="overflow-hidden rounded-lg bg-card">
      <div className="flex min-h-12 flex-wrap items-center gap-2 px-3 py-2">
        <Tabs value={view} onValueChange={(value) => onViewChange(value as ExampleView)}>
          <TabsList>
            <TabsTrigger value="request">{t("docs.reference.request")}</TabsTrigger>
            <TabsTrigger value="response">{t("docs.reference.response")}</TabsTrigger>
          </TabsList>
        </Tabs>

        <div className="flex min-w-0 flex-1 flex-wrap items-center justify-end gap-2">
          {view === "request" ? (
            <Select value={language} onValueChange={(value) => onLanguageChange(value as ExampleLanguage)}>
              <SelectTrigger className="h-8 w-28 bg-background text-xs" aria-label={t("docs.exampleLanguage")}><SelectValue /></SelectTrigger>
              <SelectContent>
                {exampleLanguages.map((item) => <SelectItem key={item} value={item}>{item === "javascript" ? "JavaScript" : item === "python" ? "Python" : "cURL"}</SelectItem>)}
              </SelectContent>
            </Select>
          ) : null}
          {models.length > 0 ? (
            <Select value={selectedModel} onValueChange={onModelChange}>
              <SelectTrigger className="h-8 w-[190px] max-w-full bg-background text-xs" aria-label={t("docs.reference.exampleModel")}><SelectValue /></SelectTrigger>
              <SelectContent>{models.map((model) => <SelectItem key={model.id} value={model.publicId}>{model.publicId}</SelectItem>)}</SelectContent>
            </Select>
          ) : null}
          <CopyButton value={code} />
        </div>
      </div>

      <pre className="max-h-[480px] overflow-auto bg-secondary/45 p-4 text-xs leading-5 text-foreground"><code>{code}</code></pre>
    </div>
  );
}
