import { FormEvent, useMemo, useRef, useState } from "react";
import { apiFetch } from "../api";
import { DownloadMediaButton } from "../components/DownloadMediaButton";
import { ElapsedTimer } from "../components/ElapsedTimer";
import { ImageSlot } from "../components/ImageSlot";
import { useGenerationOptions } from "../context/GenerationOptionsContext";

const FLASH25_ID = "gemini-2.5-flash-image";
const FLASH_ID = "gemini-3.1-flash-image-preview";
const PRO_ID = "gemini-3-pro-image-preview";

/** Order: older flash → Nano Banana 2 (default) → long-thinking → Pro */
type ImageGenVariant = "nb25-minimal" | "flash-minimal" | "flash-high" | "pro-high";

export function ImageGen() {
  const opts = useGenerationOptions();
  const nano25Label =
    opts.image.models.find((m) => m.value === FLASH25_ID)?.label ?? "Nano Banana";
  const flashLabel =
    opts.image.models.find((m) => m.value === FLASH_ID)?.label ?? "Nano Banana 2";
  const proLabel =
    opts.image.models.find((m) => m.value === PRO_ID)?.label ?? "Nano Banana Pro";

  const [prompt, setPrompt] = useState("");
  const [variant, setVariant] = useState<ImageGenVariant>("flash-minimal");
  const [aspect, setAspect] = useState(opts.image.aspect_ratios[0] ?? "1:1");
  const [res, setRes] = useState(opts.image.resolutions[0] ?? "1K");
  const [f0, setF0] = useState<File | null>(null);
  const [f1, setF1] = useState<File | null>(null);
  const [f2, setF2] = useState<File | null>(null);
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState<string | null>(null);
  const [out, setOut] = useState<string | null>(null);
  const formRef = useRef<HTMLFormElement>(null);

  const variantOptions = useMemo(
    () => [
      { id: "nb25-minimal" as const, label: nano25Label },
      { id: "flash-minimal" as const, label: flashLabel },
      { id: "flash-high" as const, label: `${flashLabel}（长思考）` },
      { id: "pro-high" as const, label: `${proLabel}（长思考）` },
    ],
    [nano25Label, flashLabel, proLabel],
  );

  async function onSubmit(e: FormEvent) {
    e.preventDefault();
    setErr(null);
    setOut(null);
    if (!prompt.trim()) {
      setErr("请填写提示词。");
      return;
    }
    let model: string;
    let thinking: "minimal" | "high";
    switch (variant) {
      case "nb25-minimal":
        model = FLASH25_ID;
        thinking = "minimal";
        break;
      case "flash-minimal":
        model = FLASH_ID;
        thinking = "minimal";
        break;
      case "flash-high":
        model = FLASH_ID;
        thinking = "high";
        break;
      case "pro-high":
        model = PRO_ID;
        thinking = "high";
        break;
    }

    const fd = new FormData();
    fd.append("prompt", prompt.trim());
    fd.append("model", model);
    fd.append("aspect_ratio", aspect);
    fd.append("resolution", res);
    fd.append("thinking_level", thinking);
    if (f0) fd.append("image_0", f0);
    if (f1) fd.append("image_1", f1);
    if (f2) fd.append("image_2", f2);

    setBusy(true);
    try {
      const r = await apiFetch("/api/generate/image", {
        method: "POST",
        body: fd,
      });
      const j = await r.json().catch(() => ({}));
      if (!r.ok) {
        throw new Error((j as { detail?: string }).detail || r.statusText);
      }
      const b64 = (j as { image_base64: string; mime_type: string }).image_base64;
      const mime = (j as { mime_type: string }).mime_type;
      setOut(`data:${mime};base64,${b64}`);
    } catch (e: unknown) {
      setErr(e instanceof Error ? e.message : "请求失败");
    } finally {
      setBusy(false);
    }
  }

  return (
    <div className="max-w-3xl">
      <h1 className="font-display text-2xl font-semibold text-ink mb-2">图片编辑或生成</h1>
      <div className="mb-6 space-y-1.5">
        <p className="text-mist text-sm leading-relaxed">
          填写提示词；参考图最多三张。再选比例与分辨率。
        </p>
        <p className="text-xs text-mist leading-relaxed">
          {nano25Label} 为稳定版；{flashLabel} 与 {proLabel} 为实验性，接口或效果可能变更。
        </p>
      </div>

      <form ref={formRef} onSubmit={onSubmit} className="space-y-5">
        <fieldset
          disabled={busy}
          className="border-0 p-0 m-0 min-w-0 space-y-5 disabled:pointer-events-none disabled:opacity-[0.92]"
        >
          <div>
            <label className="block text-sm font-semibold text-ink mb-1">模型</label>
            <select
              className="w-full max-w-md rounded-lg border border-slate-300 bg-white px-2 py-2 text-sm"
              value={variant}
              onChange={(e) => setVariant(e.target.value as ImageGenVariant)}
            >
              {variantOptions.map((opt) => (
                <option key={opt.id} value={opt.id}>
                  {opt.label}
                </option>
              ))}
            </select>
            <p className="text-xs text-mist mt-1.5">
              {nano25Label} 为上一代快速；{flashLabel} 为默认推荐；{flashLabel}（长思考）与 {proLabel}（长思考）为长思考模式，更慢、更细；{proLabel} 为 Pro 路线。
            </p>
          </div>

          <div>
            <label className="block text-sm font-semibold text-ink mb-1">提示词（必填）</label>
            <textarea
              className="w-full min-h-[120px] rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-clay/50"
              value={prompt}
              onChange={(e) => setPrompt(e.target.value)}
              placeholder="填写画面描述…"
            />
          </div>

          <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
            <div>
              <label className="block text-sm font-semibold text-ink mb-1">宽高比</label>
              <select
                className="w-full rounded-lg border border-slate-300 bg-white px-2 py-2 text-sm"
                value={aspect}
                onChange={(e) => setAspect(e.target.value)}
              >
                {opts.image.aspect_ratios.map((a) => (
                  <option key={a} value={a}>
                    {a}
                  </option>
                ))}
              </select>
            </div>
            <div>
              <label className="block text-sm font-semibold text-ink mb-1">分辨率</label>
              <select
                className="w-full rounded-lg border border-slate-300 bg-white px-2 py-2 text-sm"
                value={res}
                onChange={(e) => setRes(e.target.value)}
              >
                {opts.image.resolutions.map((x) => (
                  <option key={x} value={x}>
                    {x}
                  </option>
                ))}
              </select>
            </div>
          </div>

          <div>
            <p className="text-sm font-semibold text-ink mb-2">参考图（最多三张）</p>
            <div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
              <ImageSlot label="参考图 1" file={f0} onChange={setF0} />
              <ImageSlot label="参考图 2" file={f1} onChange={setF1} />
              <ImageSlot label="参考图 3" file={f2} onChange={setF2} />
            </div>
          </div>

          <div className="flex items-center gap-4">
            <button
              type="submit"
              className="rounded-lg bg-ink text-paper px-5 py-2 text-sm font-medium hover:bg-slate-800 disabled:opacity-40"
            >
              {busy ? "生成中…" : "生成图片"}
            </button>
            <ElapsedTimer active={busy} />
          </div>
        </fieldset>
        {err && <p className="text-sm text-red-700">{err}</p>}
      </form>

      {out && (
        <div className="mt-10 border-t border-slate-200 pt-8">
          <h2 className="font-display text-xl font-semibold text-ink mb-3">生成结果</h2>
          <div className="mb-3 flex flex-wrap items-center gap-3">
            <DownloadMediaButton dataUrl={out} filenameBase="image-gen" label="下载图片" />
            <button
              type="button"
              onClick={() => formRef.current?.requestSubmit()}
              className="rounded-lg border border-slate-300 bg-white px-5 py-2 text-sm font-medium text-ink hover:bg-slate-50"
            >
              重新生成
            </button>
          </div>
          <img
            src={out}
            alt="生成结果"
            className="max-w-full rounded-xl border border-slate-200 shadow-lg"
          />
        </div>
      )}
    </div>
  );
}
