import { useState, useMemo, useCallback } from "preact/hooks";
import { useT } from "../../../shared/i18n/context";
import { CopyButton } from "./CopyButton";

type Protocol = "openai" | "anthropic" | "gemini";
type CodeLang = "python" | "node" | "curl";

const protocols: { id: Protocol; label: string }[] = [
  { id: "openai", label: "OpenAI" },
  { id: "anthropic", label: "Anthropic" },
  { id: "gemini", label: "Gemini" },
];

const langs: { id: CodeLang; label: string }[] = [
  { id: "python", label: "Python" },
  { id: "node", label: "Node.js" },
  { id: "curl", label: "cURL" },
];

function buildExamples(
  baseUrl: string,
  apiKey: string,
  model: string,
  origin: string,
  reasoningEffort: string
): Record<string, string> {
  const effortLine = reasoningEffort && reasoningEffort !== "medium"
    ? `\n    reasoning_effort="${reasoningEffort}",`
    : "";
  const effortJson = reasoningEffort && reasoningEffort !== "medium"
    ? `,\n    "reasoning_effort": "${reasoningEffort}"`
    : "";
  const effortJs = reasoningEffort && reasoningEffort !== "medium"
    ? `\n    reasoning_effort: "${reasoningEffort}",`
    : "";
  return {
    "openai-python": `from openai import OpenAI

client = OpenAI(
    base_url="${baseUrl}",
    api_key="${apiKey}",
)

response = client.chat.completions.create(
    model="${model}",
    messages=[{"role": "user", "content": "Hello"}],${effortLine}
)
print(response.choices[0].message.content)`,

    "openai-curl": `curl ${baseUrl}/chat/completions \\
  -H "Content-Type: application/json" \\
  -H "Authorization: Bearer ${apiKey}" \\
  -d '{
    "model": "${model}",
    "messages": [{"role": "user", "content": "Hello"}]${effortJson}
  }'`,

    "openai-node": `import OpenAI from "openai";

const client = new OpenAI({
    baseURL: "${baseUrl}",
    apiKey: "${apiKey}",
});

const stream = await client.chat.completions.create({
    model: "${model}",
    messages: [{ role: "user", content: "Hello" }],${effortJs}
    stream: true,
});
for await (const chunk of stream) {
    process.stdout.write(chunk.choices[0]?.delta?.content || "");
}`,

    "anthropic-python": `import anthropic

client = anthropic.Anthropic(
    base_url="${origin}/v1",
    api_key="${apiKey}",
)

message = client.messages.create(
    model="${model}",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello"}],
)
print(message.content[0].text)`,

    "anthropic-curl": `curl ${origin}/v1/messages \\
  -H "Content-Type: application/json" \\
  -H "x-api-key: ${apiKey}" \\
  -H "anthropic-version: 2023-06-01" \\
  -d '{
    "model": "${model}",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Hello"}]
  }'`,

    "anthropic-node": `import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
    baseURL: "${origin}/v1",
    apiKey: "${apiKey}",
});

const message = await client.messages.create({
    model: "${model}",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Hello" }],
});
console.log(message.content[0].text);`,

    "gemini-python": `from google import genai

client = genai.Client(
    api_key="${apiKey}",
    http_options={"base_url": "${origin}/v1beta"},
)

response = client.models.generate_content(
    model="${model}",
    contents="Hello",
)
print(response.text)`,

    "gemini-curl": `curl "${origin}/v1beta/models/${model}:generateContent?key=${apiKey}" \\
  -H "Content-Type: application/json" \\
  -d '{
    "contents": [{"role": "user", "parts": [{"text": "Hello"}]}]
  }'`,

    "gemini-node": `import { GoogleGenAI } from "@google/genai";

const ai = new GoogleGenAI({
    apiKey: "${apiKey}",
    httpOptions: { baseUrl: "${origin}/v1beta" },
});

const response = await ai.models.generateContent({
    model: "${model}",
    contents: "Hello",
});
console.log(response.text);`,
  };
}

interface CodeExamplesProps {
  baseUrl: string;
  apiKey: string;
  model: string;
  reasoningEffort: string;
  serviceTier: string | null;
}

export function CodeExamples({ baseUrl, apiKey, model, reasoningEffort, serviceTier }: CodeExamplesProps) {
  const t = useT();
  const [protocol, setProtocol] = useState<Protocol>("openai");
  const [codeLang, setCodeLang] = useState<CodeLang>("python");

  const origin = typeof window !== "undefined" ? window.location.origin : "";

  // Build compound model name with suffixes for CLI users
  const displayModel = useMemo(() => {
    let name = model;
    if (reasoningEffort && reasoningEffort !== "medium") name += `-${reasoningEffort}`;
    if (serviceTier === "fast") name += "-fast";
    return name;
  }, [model, reasoningEffort, serviceTier]);

  // When effort/speed are embedded as suffixes, don't also show separate reasoning_effort param
  const explicitEffort = displayModel === model ? reasoningEffort : "medium";
  const examples = useMemo(
    () => buildExamples(baseUrl, apiKey, displayModel, origin, explicitEffort),
    [baseUrl, apiKey, displayModel, origin, explicitEffort]
  );

  const currentCode = examples[`${protocol}-${codeLang}`] || "Loading...";
  const getCode = useCallback(() => currentCode, [currentCode]);

  const protoActive =
    "px-6 py-3 text-[0.82rem] font-semibold text-primary border-b-2 border-primary bg-white dark:bg-card-dark transition-colors";
  const protoInactive =
    "px-6 py-3 text-[0.82rem] font-medium text-slate-500 dark:text-text-dim hover:text-slate-700 dark:hover:text-text-main hover:bg-slate-50 dark:hover:bg-[#21262d] border-b-2 border-transparent transition-colors";
  const langActive =
    "px-3 py-1.5 text-xs font-semibold rounded bg-white dark:bg-[#21262d] text-slate-800 dark:text-text-main shadow-sm border border-transparent dark:border-border-dark transition-all";
  const langInactive =
    "px-3 py-1.5 text-xs font-medium rounded text-slate-500 dark:text-text-dim hover:text-slate-700 dark:hover:text-text-main hover:bg-white/50 dark:hover:bg-[#21262d] border border-transparent transition-all";

  return (
    <section class="flex flex-col gap-4">
      <h2 class="text-[0.95rem] font-bold">{t("integrationExamples")}</h2>
      <div class="bg-white dark:bg-card-dark border border-gray-200 dark:border-border-dark rounded-xl overflow-hidden shadow-sm transition-colors">
        {/* Protocol Tabs */}
        <div class="flex border-b border-gray-200 dark:border-border-dark bg-slate-50/50 dark:bg-[#0d1117]">
          {protocols.map((p) => (
            <button
              key={p.id}
              onClick={() => setProtocol(p.id)}
              class={protocol === p.id ? protoActive : protoInactive}
            >
              {p.label}
            </button>
          ))}
        </div>
        {/* Language Tabs & Code */}
        <div class="p-5">
          <div class="flex items-center justify-between mb-4">
            <div class="flex gap-2 p-1 bg-slate-100 dark:bg-bg-dark dark:border dark:border-border-dark rounded-lg">
              {langs.map((l) => (
                <button
                  key={l.id}
                  onClick={() => setCodeLang(l.id)}
                  class={codeLang === l.id ? langActive : langInactive}
                >
                  {l.label}
                </button>
              ))}
            </div>
          </div>
          {/* Code Block */}
          <div class="relative group rounded-lg overflow-hidden bg-[#0d1117] text-slate-300 font-mono text-xs border border-slate-800 dark:border-border-dark">
            <div class="absolute right-2 top-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity">
              <CopyButton getText={getCode} variant="label" />
            </div>
            <div class="p-4 overflow-x-auto">
              <pre class="m-0"><code>{currentCode}</code></pre>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}
