import { useEffect, useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import {
  getAISettings,
  updateAISettings,
  testAIConnection,
  getSystemPrompts,
  updateSystemPrompt,
  type SystemPromptsData,
} from "../api/client";

type Provider = "anthropic" | "ollama" | "lmstudio";
type Tab = "general" | "system-prompts";

// ── Static per-service documentation ──────────────────────────────────────────

interface ServiceDoc {
  description: string;
  placeholders: { name: string; required: boolean; description: string }[];
  requiredResponseKeys: string[];
  notes: string[];
}

const SERVICE_DOCS: Record<string, ServiceDoc> = {
  doc_service: {
    description:
      "Extracts structured data from uploaded PDF documents. The system prompt instructs the model to return ONLY a JSON object. The user template is sent once per document with the extracted text injected at {text}.",
    placeholders: [
      {
        name: "{text}",
        required: true,
        description:
          "The first 50 000 characters of text extracted from the PDF. Must be present in the user template.",
      },
    ],
    requiredResponseKeys: [
      "title",
      "document_type",
      "total_amount",
      "currency",
      "vendor_name",
      "customer_name",
      "billing_address",
      "customer_address",
      "invoice_number",
      "invoice_date",
      "due_date",
      "tags",
      "line_items",
      "suggested_categories",
    ],
    notes: [
      'The system prompt should instruct the model to return ONLY a JSON object — no markdown, no code fences, no explanation.',
      'document_type must be one of: invoice, bill, receipt, order, expense, revenue, unknown.',
      'tags and suggested_categories must be JSON arrays of strings.',
      'line_items must be a JSON array of objects, each with keys description and amount.',
      'Missing keys will be stored as null — the service will not error on absent optional fields.',
    ],
  },
};

// ── Shared layout helpers ──────────────────────────────────────────────────────

function Section({ title, children }: { title: string; children: React.ReactNode }) {
  return (
    <section style={{ marginBottom: 36 }}>
      <h2 style={{ fontSize: 18, marginBottom: 16 }}>{title}</h2>
      {children}
    </section>
  );
}

function Field({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <div style={{ marginBottom: 12 }}>
      <label style={{ display: "block", fontSize: 13, marginBottom: 4, color: "#555" }}>
        {label}
      </label>
      {children}
    </div>
  );
}

const inputStyle: React.CSSProperties = {
  width: "100%",
  padding: "7px 10px",
  fontSize: 14,
  border: "1px solid #ccc",
  borderRadius: 4,
  boxSizing: "border-box",
};

const textareaStyle: React.CSSProperties = {
  ...inputStyle,
  fontFamily: "monospace",
  fontSize: 13,
  resize: "vertical",
  minHeight: 120,
};

// ── Service documentation panel ────────────────────────────────────────────────

function ServiceDocsPanel({ serviceId }: { serviceId: string }) {
  const [open, setOpen] = useState(false);
  const doc = SERVICE_DOCS[serviceId];
  if (!doc) return null;

  return (
    <div style={{ marginBottom: 16 }}>
      <button
        onClick={() => setOpen((v) => !v)}
        style={{
          background: "none",
          border: "none",
          cursor: "pointer",
          fontSize: 13,
          color: "#555",
          padding: 0,
          display: "flex",
          alignItems: "center",
          gap: 6,
        }}
      >
        <span style={{ fontSize: 11 }}>{open ? "▼" : "▶"}</span>
        How-to &amp; required keys
      </button>

      {open && (
        <div
          style={{
            marginTop: 10,
            padding: "14px 16px",
            background: "#f8f9fa",
            border: "1px solid #e0e0e0",
            borderRadius: 5,
            fontSize: 13,
            lineHeight: 1.6,
          }}
        >
          <p style={{ marginBottom: 10 }}>{doc.description}</p>

          {doc.placeholders.length > 0 && (
            <>
              <p style={{ fontWeight: 600, marginBottom: 6 }}>Template placeholders</p>
              <table style={{ width: "100%", borderCollapse: "collapse", marginBottom: 12 }}>
                <thead>
                  <tr style={{ background: "#eee" }}>
                    <th style={thStyle}>Placeholder</th>
                    <th style={thStyle}>Required</th>
                    <th style={thStyle}>Description</th>
                  </tr>
                </thead>
                <tbody>
                  {doc.placeholders.map((p) => (
                    <tr key={p.name}>
                      <td style={tdStyle}>
                        <code style={codeStyle}>{p.name}</code>
                      </td>
                      <td style={{ ...tdStyle, textAlign: "center" }}>
                        {p.required ? (
                          <span style={{ color: "#c00", fontWeight: 600 }}>Yes</span>
                        ) : (
                          "No"
                        )}
                      </td>
                      <td style={tdStyle}>{p.description}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </>
          )}

          {doc.requiredResponseKeys.length > 0 && (
            <>
              <p style={{ fontWeight: 600, marginBottom: 6 }}>Expected JSON response keys</p>
              <div style={{ display: "flex", flexWrap: "wrap", gap: 6, marginBottom: 12 }}>
                {doc.requiredResponseKeys.map((k) => (
                  <code key={k} style={codeStyle}>
                    {k}
                  </code>
                ))}
              </div>
            </>
          )}

          {doc.notes.length > 0 && (
            <>
              <p style={{ fontWeight: 600, marginBottom: 6 }}>Notes</p>
              <ul style={{ paddingLeft: 18, margin: 0 }}>
                {doc.notes.map((n, i) => (
                  <li key={i} style={{ marginBottom: 4 }}>
                    {n}
                  </li>
                ))}
              </ul>
            </>
          )}
        </div>
      )}
    </div>
  );
}

const thStyle: React.CSSProperties = {
  padding: "5px 10px",
  textAlign: "left",
  fontWeight: 600,
  fontSize: 12,
  borderBottom: "1px solid #ddd",
};
const tdStyle: React.CSSProperties = {
  padding: "5px 10px",
  verticalAlign: "top",
  borderBottom: "1px solid #eee",
};
const codeStyle: React.CSSProperties = {
  background: "#ececec",
  padding: "1px 5px",
  borderRadius: 3,
  fontFamily: "monospace",
  fontSize: 12,
};

// ── General tab ────────────────────────────────────────────────────────────────

function GeneralTab() {
  const { data: rawSettings, isLoading } = useQuery({
    queryKey: ["aiSettings"],
    queryFn: getAISettings,
  });

  const [provider, setProvider] = useState<Provider>("lmstudio");
  const [anthropicKey, setAnthropicKey] = useState("");
  const [anthropicModel, setAnthropicModel] = useState("");
  const [ollamaUrl, setOllamaUrl] = useState("");
  const [ollamaModel, setOllamaModel] = useState("");
  const [ollamaKey, setOllamaKey] = useState("");
  const [lmstudioUrl, setLmstudioUrl] = useState("");
  const [lmstudioModel, setLmstudioModel] = useState("");
  const [lmstudioKey, setLmstudioKey] = useState("");
  const [testResult, setTestResult] = useState<{
    ok: boolean;
    response?: string;
    error?: string;
  } | null>(null);

  useEffect(() => {
    if (!rawSettings) return;
    const s = rawSettings as Record<string, unknown>;
    if (s.provider) setProvider(s.provider as Provider);
    const ant = s.anthropic as Record<string, string> | undefined;
    if (ant?.api_key) setAnthropicKey(ant.api_key);
    if (ant?.model) setAnthropicModel(ant.model);
    const oll = s.ollama as Record<string, string> | undefined;
    if (oll?.base_url) setOllamaUrl(oll.base_url);
    if (oll?.model) setOllamaModel(oll.model);
    if (oll?.api_key) setOllamaKey(oll.api_key);
    const lms = s.lmstudio as Record<string, string> | undefined;
    if (lms?.base_url) setLmstudioUrl(lms.base_url);
    if (lms?.model) setLmstudioModel(lms.model);
    if (lms?.api_key) setLmstudioKey(lms.api_key);
  }, [rawSettings]);

  const aiMut = useMutation({ mutationFn: updateAISettings });
  const testMut = useMutation({
    mutationFn: testAIConnection,
    onSuccess: (data) => setTestResult(data),
  });

  const save = () => {
    aiMut.mutate({
      provider,
      anthropic_api_key: anthropicKey,
      anthropic_model: anthropicModel,
      ollama_base_url: ollamaUrl,
      ollama_model: ollamaModel,
      ollama_api_key: ollamaKey,
      lmstudio_base_url: lmstudioUrl,
      lmstudio_model: lmstudioModel,
      lmstudio_api_key: lmstudioKey,
    });
  };

  if (isLoading) return <div style={{ padding: 16 }}>Loading…</div>;

  return (
    <Section title="AI Provider">
      <Field label="Provider">
        <select
          value={provider}
          onChange={(e) => setProvider(e.target.value as Provider)}
          style={inputStyle}
        >
          <option value="anthropic">Anthropic (cloud)</option>
          <option value="ollama">Ollama (local)</option>
          <option value="lmstudio">LM Studio (local)</option>
        </select>
      </Field>

      {provider === "anthropic" && (
        <>
          <Field label="API Key">
            <input
              type="password"
              value={anthropicKey}
              onChange={(e) => setAnthropicKey(e.target.value)}
              placeholder="sk-ant-… (leave blank to keep current)"
              style={inputStyle}
            />
          </Field>
          <Field label="Model">
            <input
              value={anthropicModel}
              onChange={(e) => setAnthropicModel(e.target.value)}
              placeholder="claude-haiku-4-5-20251001"
              style={inputStyle}
            />
          </Field>
        </>
      )}

      {provider === "ollama" && (
        <>
          <Field label="Base URL">
            <input
              value={ollamaUrl}
              onChange={(e) => setOllamaUrl(e.target.value)}
              placeholder="http://192.168.1.x:11434/v1"
              style={inputStyle}
            />
          </Field>
          <Field label="Model">
            <input
              value={ollamaModel}
              onChange={(e) => setOllamaModel(e.target.value)}
              placeholder="llama3.2"
              style={inputStyle}
            />
          </Field>
          <Field label="API Key (usually 'ollama')">
            <input
              value={ollamaKey}
              onChange={(e) => setOllamaKey(e.target.value)}
              placeholder="ollama"
              style={inputStyle}
            />
          </Field>
        </>
      )}

      {provider === "lmstudio" && (
        <>
          <Field label="Base URL">
            <input
              value={lmstudioUrl}
              onChange={(e) => setLmstudioUrl(e.target.value)}
              placeholder="http://192.168.1.x:1234/v1"
              style={inputStyle}
            />
          </Field>
          <Field label="Model">
            <input
              value={lmstudioModel}
              onChange={(e) => setLmstudioModel(e.target.value)}
              placeholder="local-model"
              style={inputStyle}
            />
          </Field>
          <Field label="API Key (can be empty)">
            <input
              value={lmstudioKey}
              onChange={(e) => setLmstudioKey(e.target.value)}
              placeholder=""
              style={inputStyle}
            />
          </Field>
        </>
      )}

      <div style={{ display: "flex", gap: 10, marginTop: 16 }}>
        <button
          onClick={save}
          disabled={aiMut.isPending}
          style={{
            padding: "8px 16px",
            cursor: "pointer",
            background: "#222",
            color: "#fff",
            borderRadius: 4,
            border: "none",
          }}
        >
          {aiMut.isPending ? "Saving…" : "Save"}
        </button>
        <button
          onClick={() => testMut.mutate()}
          disabled={testMut.isPending}
          style={{ padding: "8px 16px", cursor: "pointer", borderRadius: 4, border: "1px solid #ccc" }}
        >
          {testMut.isPending ? "Testing…" : "Test Connection"}
        </button>
      </div>

      {aiMut.isSuccess && (
        <p style={{ marginTop: 8, fontSize: 13, color: "#2a9d8f" }}>Settings saved.</p>
      )}
      {aiMut.isError && (
        <p style={{ marginTop: 8, fontSize: 13, color: "#c00" }}>Failed to save settings.</p>
      )}

      {testResult && (
        <div
          style={{
            marginTop: 10,
            padding: 10,
            borderRadius: 4,
            background: testResult.ok ? "#e8f5e9" : "#fdecea",
            fontSize: 13,
          }}
        >
          {testResult.ok ? (
            <>Connected. Response: <em>{testResult.response}</em></>
          ) : (
            <>Connection failed: {testResult.error}</>
          )}
        </div>
      )}
    </Section>
  );
}

// ── System Prompts tab ─────────────────────────────────────────────────────────

function ServicePromptCard({
  serviceId,
  label,
  initialSystem,
  initialUserTemplate,
  defaultSystem,
  defaultUserTemplate,
}: {
  serviceId: string;
  label: string;
  initialSystem: string;
  initialUserTemplate: string;
  defaultSystem: string;
  defaultUserTemplate: string;
}) {
  const queryClient = useQueryClient();
  const [system, setSystem] = useState(initialSystem);
  const [userTemplate, setUserTemplate] = useState(initialUserTemplate);
  const [showResetConfirm, setShowResetConfirm] = useState(false);

  const isAtDefault =
    system === defaultSystem && userTemplate === defaultUserTemplate;

  const handleReset = () => {
    setSystem(defaultSystem);
    setUserTemplate(defaultUserTemplate);
    setShowResetConfirm(false);
  };

  const mut = useMutation({
    mutationFn: () => updateSystemPrompt(serviceId, { system, user_template: userTemplate }),
    onSuccess: (data) => queryClient.setQueryData(["systemPrompts"], data),
  });

  return (
    <div
      style={{
        border: "1px solid #e0e0e0",
        borderRadius: 6,
        padding: 20,
        marginBottom: 24,
      }}
    >
      <h3 style={{ fontSize: 16, marginBottom: 14 }}>{label}</h3>

      <ServiceDocsPanel serviceId={serviceId} />

      <Field label="System Prompt">
        <textarea
          value={system}
          onChange={(e) => setSystem(e.target.value)}
          style={{ ...textareaStyle, minHeight: 80 }}
        />
      </Field>

      <Field label="User Prompt Template">
        <textarea
          value={userTemplate}
          onChange={(e) => setUserTemplate(e.target.value)}
          style={{ ...textareaStyle, minHeight: 220 }}
        />
      </Field>

      <div style={{ display: "flex", alignItems: "center", gap: 10, marginTop: 12, flexWrap: "wrap" }}>
        <button
          onClick={() => mut.mutate()}
          disabled={mut.isPending}
          style={{
            padding: "8px 16px",
            cursor: "pointer",
            background: "#222",
            color: "#fff",
            borderRadius: 4,
            border: "none",
          }}
        >
          {mut.isPending ? "Saving…" : "Save"}
        </button>

        {!isAtDefault && !showResetConfirm && (
          <button
            onClick={() => setShowResetConfirm(true)}
            style={{
              padding: "8px 16px",
              cursor: "pointer",
              borderRadius: 4,
              border: "1px solid #ccc",
              background: "transparent",
              fontSize: 14,
            }}
          >
            Reset to Default
          </button>
        )}

        {showResetConfirm && (
          <span style={{ fontSize: 13, display: "flex", alignItems: "center", gap: 8 }}>
            <span style={{ color: "#555" }}>Discard changes and restore the built-in default?</span>
            <button
              onClick={handleReset}
              style={{
                padding: "4px 12px",
                cursor: "pointer",
                borderRadius: 4,
                border: "1px solid #c00",
                color: "#c00",
                background: "transparent",
                fontSize: 13,
              }}
            >
              Yes, reset
            </button>
            <button
              onClick={() => setShowResetConfirm(false)}
              style={{
                padding: "4px 12px",
                cursor: "pointer",
                borderRadius: 4,
                border: "1px solid #ccc",
                background: "transparent",
                fontSize: 13,
              }}
            >
              Cancel
            </button>
          </span>
        )}

        {mut.isSuccess && (
          <span style={{ fontSize: 13, color: "#2a9d8f" }}>Saved.</span>
        )}
        {mut.isError && (
          <span style={{ fontSize: 13, color: "#c00" }}>Failed to save.</span>
        )}
      </div>

      {isAtDefault && (
        <p style={{ marginTop: 8, fontSize: 12, color: "#aaa" }}>
          Using the built-in default prompt.
        </p>
      )}
    </div>
  );
}

function SystemPromptsTab() {
  const { data, isLoading, isError } = useQuery<SystemPromptsData>({
    queryKey: ["systemPrompts"],
    queryFn: getSystemPrompts,
  });

  if (isLoading) return <div style={{ padding: 16 }}>Loading…</div>;
  if (isError || !data)
    return <div style={{ padding: 16, color: "#c00" }}>Failed to load system prompts.</div>;

  return (
    <Section title="Service System Prompts">
      <p style={{ fontSize: 13, color: "#666", marginBottom: 20 }}>
        Each service sends its own system prompt to the AI model. Changes take effect within 30 seconds (config cache TTL).
      </p>
      {Object.entries(data).map(
        ([serviceId, { label, system, user_template, default_system, default_user_template }]) => (
          <ServicePromptCard
            key={serviceId}
            serviceId={serviceId}
            label={label}
            initialSystem={system}
            initialUserTemplate={user_template}
            defaultSystem={default_system}
            defaultUserTemplate={default_user_template}
          />
        )
      )}
    </Section>
  );
}

// ── Page root ──────────────────────────────────────────────────────────────────

const tabBarStyle: React.CSSProperties = {
  display: "flex",
  gap: 0,
  borderBottom: "1px solid #e0e0e0",
  marginBottom: 32,
};

function TabButton({
  active,
  onClick,
  children,
}: {
  active: boolean;
  onClick: () => void;
  children: React.ReactNode;
}) {
  return (
    <button
      onClick={onClick}
      style={{
        padding: "10px 20px",
        fontSize: 14,
        cursor: "pointer",
        border: "none",
        borderBottom: active ? "2px solid #222" : "2px solid transparent",
        background: "transparent",
        fontWeight: active ? 600 : 400,
        color: active ? "#111" : "#666",
        marginBottom: -1,
      }}
    >
      {children}
    </button>
  );
}

export default function AIAdminSettingsPage() {
  const [tab, setTab] = useState<Tab>("general");

  return (
    <div style={{ padding: 32, maxWidth: 700, margin: "0 auto" }}>
      <h1 style={{ fontSize: 24, marginBottom: 28 }}>AI Service — Settings</h1>

      <div style={tabBarStyle}>
        <TabButton active={tab === "general"} onClick={() => setTab("general")}>
          General
        </TabButton>
        <TabButton active={tab === "system-prompts"} onClick={() => setTab("system-prompts")}>
          System Prompts
        </TabButton>
      </div>

      {tab === "general" && <GeneralTab />}
      {tab === "system-prompts" && <SystemPromptsTab />}
    </div>
  );
}
