import { useState } from "react";
import { invoke } from "@tauri-apps/api/core";
import { ImagePlus, Sparkles } from "lucide-react";
import { useToast } from "./Toast";
import { addGeneration, type Generation } from "../lib/generations";
import { usePrefillEffect } from "../lib/usePrefill";

const DEFAULT_MODEL = "x/flux2-klein:4b";

interface Props {
  prefill?: Generation | null;
  onPrefillConsumed?: () => void;
}

export function ImageGenerator({ prefill, onPrefillConsumed }: Props = {}) {
  const [prompt, setPrompt] = useState("");
  const [model, setModel] = useState("");
  const [dataUrl, setDataUrl] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
  const [variant, setVariant] = useState(0);
  const [unsupported, setUnsupported] = useState(false);
  const { addToast } = useToast();

  usePrefillEffect(prefill ?? null, "image", () => onPrefillConsumed?.(), (g) => {
    setPrompt(g.title);
    setDataUrl(g.data);
    addToast(`Loaded "${g.title}" from history`, "info");
  });

  async function generate() {
    if (!prompt.trim()) return;
    setLoading(true);
    setDataUrl(null);
    try {
      // ponytail: append a variant tag to bust the backend's prompt-hash cache
      // so "regenerate" actually produces a new image instead of the cached one.
      const v = variant > 0 ? `\n\n(variation ${variant})` : "";
      const url = await invoke<string>("generate_image", {
        req: { prompt: `${prompt}${v}`, model: model.trim() || null },
      });
      setDataUrl(url);
      setUnsupported(false);
      addToast("Image generated", "success");
      // ponytail: persist the PNG data URL so the DM can re-open past renders.
      void addGeneration({ kind: "image", title: prompt, data: url, source: model.trim() || DEFAULT_MODEL });
    } catch (e) {
      const msg = String(e);
      if (msg.toLowerCase().includes("macos-only")) setUnsupported(true);
      addToast(`Image generation failed: ${msg}`, "error");
    }
    setLoading(false);
  }

  function regenerate() {
    setVariant((v) => v + 1);
    // run after state update flushes
    setTimeout(generate, 0);
  }

  return (
    <div className="flex flex-col gap-3 text-sm">
      <div className="flex flex-col gap-1">
        <label className="text-[var(--color-text-secondary)] text-xs font-medium">Prompt</label>
        <textarea
          className="rounded-lg bg-[var(--color-bg-surface)] border border-[var(--color-border-glass)] px-3 py-2 text-[var(--color-text-primary)] placeholder-[var(--color-text-dim)] focus:outline-none focus:border-[var(--color-gold-bright)] text-sm min-h-24 resize-y"
          value={prompt}
          onChange={(e) => setPrompt(e.target.value)}
          placeholder="e.g. portrait of a grizzled dwarf blacksmith at a forge, warm light, oil-painting fantasy style, 1024x1024"
          onKeyDown={(e) => e.key === "Enter" && (e.metaKey || e.ctrlKey) && generate()}
        />
      </div>

      <div className="flex flex-col gap-1">
        <label className="text-[var(--color-text-secondary)] text-xs font-medium">
          Model (optional — defaults to {DEFAULT_MODEL})
        </label>
        <input
          className="rounded-lg bg-[var(--color-bg-surface)] border border-[var(--color-border-glass)] px-3 py-1.5 text-[var(--color-text-primary)] placeholder-[var(--color-text-dim)] focus:outline-none focus:border-[var(--color-gold-bright)] text-sm"
          value={model}
          onChange={(e) => setModel(e.target.value)}
          placeholder="x/flux2-klein:4b  ·  x/z-image-turbo for speed"
        />
      </div>

      <div className="flex gap-2">
        <button
          onClick={generate}
          disabled={loading || !prompt.trim()}
          className="flex-1 rounded-lg bg-[var(--color-gold-bright)] text-[var(--color-bg-deep)] px-4 py-2 text-sm font-semibold hover:bg-[var(--color-gold-muted)] transition-colors cursor-pointer disabled:opacity-50"
        >
          {loading ? "✨ Generating…" : "✨ Generate Image"}
        </button>
        {dataUrl && !loading && (
          <button
            onClick={regenerate}
            className="rounded-lg bg-[var(--color-bg-card)] border border-[var(--color-border-glass)] text-[var(--color-gold-bright)] px-3 py-2 text-sm hover:border-[var(--color-gold-bright)] transition-colors cursor-pointer"
            title="Generate a new variation"
          >
            <Sparkles size={16} />
          </button>
        )}
      </div>

      {loading && (
        <div className="aspect-square w-full max-w-md mx-auto rounded-lg border border-[var(--color-border-glass)] bg-[var(--color-bg-deep)] flex items-center justify-center">
          <ImagePlus size={28} className="text-[var(--color-gold-bright)] animate-pulse" />
        </div>
      )}

      {unsupported && (
        <div className="rounded-lg bg-[var(--color-danger)]/10 border border-[var(--color-danger)]/30 p-3 text-[var(--color-danger)] text-xs">
          Image generation is macOS-only via Ollama (for now). On other platforms the
          ✨ buttons elsewhere fall back to a placeholder.
        </div>
      )}


      {dataUrl && !loading && (
        <div className="flex flex-col gap-2">
          <div className="aspect-square w-full max-w-md mx-auto rounded-lg overflow-hidden border border-[var(--color-border-glass)] bg-[var(--color-bg-deep)]">
            <img src={dataUrl} alt={prompt} className="w-full h-full object-cover" />
          </div>
          <div className="flex justify-center gap-3">
            <a
              href={dataUrl}
              download="dm-pal-image.png"
              className="text-xs text-[var(--color-gold-bright)] hover:text-[var(--color-gold-muted)] cursor-pointer transition-colors"
            >
              ⬇ Save PNG
            </a>
            <button
              onClick={() => {
                // ponytail: copy the rendered PNG to the clipboard. The
                // Clipboard API needs a Blob, not a data URL string.
                fetch(dataUrl).then((r) => r.blob()).then((blob) =>
                  navigator.clipboard.write([new ClipboardItem({ [blob.type]: blob })]),
                ).then(() => addToast("Image copied to clipboard", "success"))
                  .catch(() => addToast("Copy failed", "error"));
              }}
              className="text-xs text-[var(--color-gold-bright)] hover:text-[var(--color-gold-muted)] cursor-pointer transition-colors"
            >
              ⧉ Copy
            </button>
          </div>
        </div>
      )}

      {!dataUrl && !loading && !unsupported && (
        <div className="flex flex-col items-center justify-center aspect-square max-w-md mx-auto text-center text-[var(--color-text-dim)] text-xs">
          <span>No image yet.</span>
          <span className="mt-1">Describe a scene or portrait, then Generate.</span>
        </div>
      )}
    </div>
  );
}