import { useCallback, useEffect, useMemo, useRef, useState } from "react";

import "./admin-models.css";

interface AdminSession { csrf_token: string }
interface RuntimeAvailability {
  available_for_new_jobs: boolean;
  checked_at: string;
  reason: string;
}
interface ModelConfig {
  config_version: number;
  contract_evidence_ref: string | null;
  contract_validation_status: "blocked" | "unverified" | "verified";
  credit_cost: number;
  display_name: string;
  enabled: boolean;
  error_mapping_profile: Record<string, string>;
  gateway_account_ref: string;
  is_default: boolean;
  model_id: string;
  prompt_max_length: number;
  recommendation_priority: number;
  reference_limits: { max_file_bytes: number; max_files: number; max_total_bytes: number };
  route_profile: Record<string, unknown>;
  runtime_availability: RuntimeAvailability;
  safety_source: string;
  supported_ratios: string[];
}
interface ModelConfiguration {
  config_set_version: number;
  configured_default_model_id: string;
  models: ModelConfig[];
  recommended_model_id: string | null;
}

async function responseJson<T>(url: string, init?: RequestInit) {
  const response = await fetch(url, { credentials: "same-origin", ...init });
  const body = await response.json() as T;
  return { body, response };
}

function idempotencyKey() {
  return crypto.randomUUID().replaceAll("-", "") + crypto.randomUUID().replaceAll("-", "");
}

function editableModel(model: ModelConfig) {
  const { config_version: _configVersion, contract_evidence_ref: _evidence, contract_validation_status: _status, runtime_availability: _runtime, ...editable } = model;
  return editable;
}

function runtimeLabel(runtime: RuntimeAvailability) {
  return runtime.available_for_new_jobs ? "可用于新任务" : `不可用 · ${runtime.reason}`;
}

export function AdminModelsPage() {
  const [session, setSession] = useState<AdminSession>();
  const [configuration, setConfiguration] = useState<ModelConfiguration>();
  const [draft, setDraft] = useState<ModelConfig[]>();
  const [loadingFailed, setLoadingFailed] = useState(false);
  const [saving, setSaving] = useState(false);
  const [notice, setNotice] = useState("");
  const [conflicted, setConflicted] = useState(false);
  const priorityRefs = useRef<Record<string, HTMLInputElement | null>>({});
  const defaultRefs = useRef<Record<string, HTMLInputElement | null>>({});

  const load = useCallback(async () => {
    setLoadingFailed(false);
    setConflicted(false);
    try {
      const [sessionResult, modelResult] = await Promise.all([
        responseJson<AdminSession>("/api/v1/admin-auth/session"),
        responseJson<ModelConfiguration>("/api/v1/models"),
      ]);
      if (!sessionResult.response.ok || !modelResult.response.ok) throw new Error("load_failed");
      setSession(sessionResult.body);
      setConfiguration(modelResult.body);
      setDraft(structuredClone(modelResult.body.models));
      setNotice("");
    } catch {
      setLoadingFailed(true);
    }
  }, []);

  useEffect(() => { void load(); }, [load]);

  useEffect(() => {
    if (typeof EventSource === "undefined") return undefined;
    const source = new EventSource("/api/v1/events");
    source.onmessage = () => { void load(); };
    return () => source.close();
  }, [load]);

  const validation = useMemo(() => {
    if (!draft) return { valid: false, message: "" };
    const invalidPriority = draft.find((model) => !Number.isSafeInteger(model.recommendation_priority) || model.recommendation_priority <= 0);
    if (invalidPriority) return { field: invalidPriority.model_id, kind: "priority" as const, message: "推荐优先级必须是正整数。", valid: false };
    const duplicatePriority = draft.find((model, index) => draft.findIndex((item) => item.recommendation_priority === model.recommendation_priority) !== index);
    if (duplicatePriority) return { field: duplicatePriority.model_id, kind: "priority" as const, message: "推荐优先级不能重复。", valid: false };
    const defaults = draft.filter((model) => model.enabled && model.is_default);
    if (defaults.length !== 1) return { field: draft.find((model) => model.is_default)?.model_id ?? draft[0]?.model_id, kind: "default" as const, message: "必须指定一个已启用的默认模型。", valid: false };
    return { message: "", valid: true };
  }, [draft]);

  function updateModel(modelId: string, change: Partial<ModelConfig>) {
    setDraft((current) => current?.map((model) => model.model_id === modelId ? { ...model, ...change } : model));
    setNotice("");
  }

  function chooseDefault(modelId: string) {
    setDraft((current) => current?.map((model) => ({ ...model, is_default: model.model_id === modelId })));
    setNotice("");
  }

  async function save() {
    if (!configuration || !draft || !session || !validation.valid || saving || conflicted) return;
    setSaving(true);
    setNotice("");
    try {
      const { body, response } = await responseJson<ModelConfiguration & { error?: { code?: string } }>("/api/v1/admin/models/configuration", {
        body: JSON.stringify({ expected_config_set_version: configuration.config_set_version, models: draft.map(editableModel) }),
        headers: {
          "Content-Type": "application/json",
          "Idempotency-Key": idempotencyKey(),
          "X-CSRF-Token": session.csrf_token,
        },
        method: "PUT",
      });
      if (!response.ok) {
        const code = body.error?.code;
        if (code === "MODEL_CONFIG_VERSION_CONFLICT") {
          setConflicted(true);
          setNotice("配置已被其他管理员更新，请刷新最新配置后重新编辑。");
        } else if (code === "MODEL_RECOMMENDATION_PRIORITY_INVALID" || code === "MODEL_RECOMMENDATION_PRIORITY_CONFLICT") {
          const modelId = validation.field ?? draft[0]?.model_id;
          if (modelId) priorityRefs.current[modelId]?.focus();
          setNotice("请修正推荐优先级后再保存。");
        } else if (code === "MODEL_DEFAULT_REPLACEMENT_REQUIRED" || code === "MODEL_DEFAULT_REPLACEMENT_INVALID") {
          const modelId = validation.field ?? draft[0]?.model_id;
          if (modelId) defaultRefs.current[modelId]?.focus();
          setNotice("请指定一个已启用的替代默认模型。");
        } else setNotice("操作未完成。");
        return;
      }
      setConfiguration(body);
      setDraft(structuredClone(body.models));
      setNotice("模型配置已原子保存并记录审计。");
    } catch {
      setNotice("操作未完成。");
    } finally {
      setSaving(false);
    }
  }

  return (
    <div className="admin-models-page">
      <main id="admin-main">
        <header className="admin-models-heading">
          <div><p>MODEL OPERATIONS</p><h1>模型配置</h1></div>
          {configuration ? <strong>配置集合 v{configuration.config_set_version}</strong> : null}
        </header>
        {!configuration && !loadingFailed ? <div aria-label="模型配置加载中" className="admin-models-loading"><span /><span /><span /></div> : null}
        {loadingFailed ? <p className="admin-models-alert" role="alert">模型配置暂时无法读取。<button onClick={() => void load()} type="button">重试</button></p> : null}
        {configuration && draft ? (
          <>
            <div className="admin-models-summary" aria-label="模型配置摘要">
              <span>配置默认 <strong>{configuration.configured_default_model_id}</strong></span>
              <span>当前推荐 <strong>{configuration.recommended_model_id ?? "无"}</strong></span>
              <span>运行时可用 <strong>{configuration.models.filter((model) => model.runtime_availability.available_for_new_jobs).length} / 3</strong></span>
            </div>
            <div className="admin-models-table-wrap">
              <table>
                <thead><tr><th>模型</th><th>启用</th><th>默认</th><th>推荐优先级</th><th>契约</th><th>运行时可用</th><th>当前推荐</th><th>能力</th><th>配置版本</th></tr></thead>
                <tbody>
                  {draft.map((model) => (
                    <tr key={model.model_id}>
                      <th scope="row"><strong>{model.display_name}</strong><code>{model.model_id}</code></th>
                      <td><input aria-label={`启用 ${model.display_name}`} checked={model.enabled} onChange={(event) => updateModel(model.model_id, { enabled: event.target.checked })} type="checkbox" /></td>
                      <td><input aria-label={`设为默认 ${model.display_name}`} checked={model.is_default} disabled={!model.enabled} name="configured-default" onChange={() => chooseDefault(model.model_id)} ref={(node) => { defaultRefs.current[model.model_id] = node; }} type="radio" /></td>
                      <td><input aria-label={`${model.display_name} 推荐优先级`} inputMode="numeric" min="1" onChange={(event) => updateModel(model.model_id, { recommendation_priority: Number(event.target.value) })} ref={(node) => { priorityRefs.current[model.model_id] = node; }} type="number" value={model.recommendation_priority} /></td>
                      <td><span className={`model-state is-${model.contract_validation_status}`}>{model.contract_validation_status}</span></td>
                      <td><span className={`model-state ${model.runtime_availability.available_for_new_jobs ? "is-available" : "is-unavailable"}`}>{runtimeLabel(model.runtime_availability)}</span><small>{new Date(model.runtime_availability.checked_at).toLocaleString("zh-CN")}</small></td>
                      <td>{configuration.recommended_model_id === model.model_id ? "是" : "否"}</td>
                      <td><span>{model.credit_cost} 点</span><small>{model.supported_ratios.join(" / ")} · 最多 {model.reference_limits.max_files} 张参考图</small></td>
                      <td>v{model.config_version}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
            <footer className="admin-models-actions">
              <div aria-live="polite">{validation.message ? <p className="admin-models-validation">{validation.message}</p> : null}{notice ? <p className="admin-models-notice" role={conflicted ? "alert" : "status"}>{notice}</p> : null}</div>
              <div>{conflicted ? <button onClick={() => void load()} type="button">刷新最新配置</button> : null}<button disabled={!validation.valid || saving || conflicted} onClick={() => void save()} type="button">{saving ? "保存中" : "保存完整配置集合"}</button></div>
            </footer>
          </>
        ) : null}
      </main>
    </div>
  );
}
