"use client";

import { useMemo, useRef, useState, type ChangeEvent } from "react";
import dynamic from "next/dynamic";
import { useRouter } from "next/navigation";
import { PencilRuler } from "lucide-react";
import { getPB } from "@/lib/pocketbase";
import {
  buildFromSpec, buildViews, buildDespiece, generateCortesCode, specFromPreset, normalizeSpec, COL3D, type Spec,
} from "@/lib/disenador/engine";

const Viewer3D = dynamic(() => import("@/components/disenador/Viewer3D"), { ssr: false });

const EJEMPLO =
  "estantería de MDF de 60 de ancho por 25 de profundidad, laterales de 9mm, estantes de 12mm, fondo de 3mm. Dos compartimentos inferiores de 38 y tres superiores de 32, con zócalo de pino de 8 cm";

// Redimensiona y comprime en el navegador para no mandar imágenes enormes a la IA.
async function fileToDataURL(file: File, max = 1024): Promise<string> {
  const img = await new Promise<HTMLImageElement>((resolve, reject) => {
    const i = new Image();
    i.onload = () => resolve(i);
    i.onerror = reject;
    i.src = URL.createObjectURL(file);
  });
  const scale = Math.min(1, max / Math.max(img.width, img.height));
  const w = Math.round(img.width * scale), h = Math.round(img.height * scale);
  const canvas = document.createElement("canvas");
  canvas.width = w; canvas.height = h;
  canvas.getContext("2d")!.drawImage(img, 0, 0, w, h);
  URL.revokeObjectURL(img.src);
  return canvas.toDataURL("image/jpeg", 0.85);
}

const MATERIALES = ["Melamina blanca", "Roble claro", "Nogal", "Negro mate", "Gris grafito", "Madera natural"];
const HERRAJES = ["Sin tiradores (uñero)", "Tiradores negros", "Tiradores dorados", "Manijas de aluminio"];
const AMBIENTES = ["Estudio neutro (catálogo)", "Living moderno", "Cocina", "Dormitorio"];
const ESTILOS = ["E-commerce, luz cálida", "Render arquitectónico", "Minimalista, luz fría"];

export default function DisenadorPage() {
  const [descripcion, setDescripcion] = useState(EJEMPLO);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [imagen, setImagen] = useState<string | null>(null);
  const [spec, setSpec] = useState<Spec>(() => specFromPreset("rack"));
  const [specText, setSpecText] = useState(() => JSON.stringify(specFromPreset("rack"), null, 2));
  const [specErr, setSpecErr] = useState("");
  const [showDoors, setShowDoors] = useState(true);
  const [showWall, setShowWall] = useState(true);
  // Render foto-real
  const [material, setMaterial] = useState(MATERIALES[0]);
  const [herrajes, setHerrajes] = useState(HERRAJES[0]);
  const [ambiente, setAmbiente] = useState(AMBIENTES[0]);
  const [estiloRender, setEstiloRender] = useState(ESTILOS[0]);
  const [rendering, setRendering] = useState(false);
  const [renderUrl, setRenderUrl] = useState<string | null>(null);
  const [renderErr, setRenderErr] = useState("");
  const [detallesRender, setDetallesRender] = useState("");
  const [mejorando, setMejorando] = useState(false);
  const [calidad, setCalidad] = useState<"low" | "medium" | "high">("low");
  const captureRef = useRef<(() => string | null) | null>(null);

  const panels = useMemo(() => buildFromSpec(spec), [spec]);
  const viewPanels = useMemo(
    () => panels.filter((p) => !(p.role === "puerta" && !showDoors)),
    [panels, showDoors],
  );
  const views = useMemo(() => buildViews(viewPanels, spec), [viewPanels, spec]);
  const despiece = useMemo(() => buildDespiece(panels), [panels]);
  const cortesCode = useMemo(() => generateCortesCode(panels, spec), [panels, spec]);
  const router = useRouter();
  const [copied, setCopied] = useState(false);

  async function copiarCortes() {
    try {
      await navigator.clipboard.writeText(cortesCode);
      setCopied(true);
      setTimeout(() => setCopied(false), 1500);
    } catch {
      /* clipboard no disponible */
    }
  }

  async function mejorarPrompt() {
    setMejorando(true);
    try {
      const token = getPB().authStore.token;
      const r = await fetch("/api/disenador/mejorar-prompt", {
        method: "POST",
        headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
        body: JSON.stringify({ texto: detallesRender, nombre: spec.nombre, descripcion, material, herrajes, ambiente, estilo: estiloRender }),
      });
      const data = await r.json();
      if (r.ok && typeof data.prompt === "string") setDetallesRender(data.prompt);
      else setRenderErr(data?.error || "No pude mejorar el texto.");
    } catch (e) {
      setRenderErr((e as Error).message);
    } finally {
      setMejorando(false);
    }
  }

  async function generarRender() {
    const base = captureRef.current?.();
    if (!base) { setRenderErr("No pude capturar la vista 3D."); return; }
    setRendering(true); setRenderErr(""); setRenderUrl(null);
    try {
      const token = getPB().authStore.token;
      const r = await fetch("/api/disenador/render", {
        method: "POST",
        headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
        body: JSON.stringify({ imagen: base, nombre: spec.nombre, descripcion, material, herrajes, ambiente, estilo: estiloRender, detalles: detallesRender, quality: calidad }),
      });
      const data = await r.json();
      if (!r.ok) throw new Error(data?.error || `Error ${r.status}`);
      setRenderUrl(data.imagen as string);
    } catch (e) {
      setRenderErr((e as Error).message);
    } finally {
      setRendering(false);
    }
  }

  function applySpec(next: Spec) {
    setSpec(next);
    setSpecText(JSON.stringify(next, null, 2));
    setSpecErr("");
  }

  async function onPickImage(e: ChangeEvent<HTMLInputElement>) {
    const f = e.target.files?.[0];
    if (f) setImagen(await fileToDataURL(f));
    e.target.value = "";
  }

  async function generar() {
    setLoading(true);
    setError("");
    try {
      const token = getPB().authStore.token;
      const r = await fetch("/api/disenador", {
        method: "POST",
        headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
        body: JSON.stringify({ descripcion, imagen }),
      });
      const data = await r.json();
      if (!r.ok) throw new Error(data?.error || `Error ${r.status}`);
      applySpec(data.spec as Spec);
    } catch (e) {
      setError((e as Error).message);
    } finally {
      setLoading(false);
    }
  }

  function aplicarSpecText() {
    try {
      applySpec(normalizeSpec(JSON.parse(specText)));
    } catch (e) {
      setSpecErr("JSON inválido: " + (e as Error).message);
    }
  }

  return (
    <div className="space-y-5">
      <div className="flex items-center gap-2">
        <PencilRuler className="text-brand-dark" size={22} />
        <h1 className="text-xl font-semibold text-ink">Diseñador</h1>
        {spec.nombre && <span className="text-sm text-faint">· {spec.nombre}</span>}
      </div>

      {/* Entrada de texto */}
      <div className="rounded-xl border border-line bg-surface p-4 space-y-3">
        <label className="block text-sm font-medium text-ink">Describí el mueble</label>
        <textarea
          value={descripcion}
          onChange={(e) => setDescripcion(e.target.value)}
          className="w-full h-24 rounded-lg border border-line bg-canvas p-3 text-sm text-ink"
          placeholder="Ej: placard de 150 x 200 x 55, división al medio, dos puertas por lado, tres estantes…"
        />
        <div className="flex items-center gap-3 flex-wrap">
          <label className="inline-flex items-center gap-2 rounded-lg border border-line bg-canvas px-3 py-1.5 text-sm text-ink cursor-pointer hover:border-brand-dark">
            <input type="file" accept="image/*" className="hidden" onChange={onPickImage} />
            {imagen ? "Cambiar foto de referencia" : "📎 Agregar foto de referencia"}
          </label>
          {imagen && (
            <span className="inline-flex items-center gap-2">
              {/* eslint-disable-next-line @next/next/no-img-element */}
              <img src={imagen} alt="referencia" className="h-12 w-12 object-cover rounded border border-line" />
              <button type="button" onClick={() => setImagen(null)} className="text-xs text-red-600">quitar</button>
            </span>
          )}
        </div>
        <div className="flex items-center gap-3">
          <button
            onClick={generar}
            disabled={loading || !descripcion.trim()}
            className="inline-flex items-center gap-2 rounded-lg bg-brand-dark px-4 py-2 text-sm font-semibold text-white disabled:opacity-60"
          >
            {loading && (
              <span className="inline-block w-4 h-4 rounded-full border-2 border-white/40 border-t-white animate-spin" />
            )}
            {loading ? "Generando…" : "Generar diseño"}
          </button>
          {error && <span className="text-sm text-red-600">{error}</span>}
        </div>
      </div>

      <div className="grid gap-5 lg:grid-cols-2">
        {/* Columna izquierda: 3D + spec */}
        <div className="space-y-3">
          <div className="rounded-xl border border-line bg-surface overflow-hidden">
            <div className="flex items-center justify-between px-4 py-2 border-b border-line">
              <h3 className="text-sm font-medium text-ink">Vista 3D</h3>
              <div className="flex gap-3 text-xs text-faint">
                <label className="flex items-center gap-1">
                  <input type="checkbox" checked={showDoors} onChange={(e) => setShowDoors(e.target.checked)} /> Puertas
                </label>
                <label className="flex items-center gap-1">
                  <input type="checkbox" checked={showWall} onChange={(e) => setShowWall(e.target.checked)} /> Pared
                </label>
              </div>
            </div>
            <div className="resize-y overflow-hidden min-h-[300px] h-[460px]">
              <Viewer3D panels={panels} spec={spec} showDoors={showDoors} showWall={showWall} registerCapture={(fn) => { captureRef.current = fn; }} />
            </div>
            <p className="px-4 py-2 text-xs text-faint">Arrastrá el borde inferior para agrandar · arrastrá la escena para rotar.</p>
          </div>

          <div className="rounded-xl border border-line bg-surface p-4">
            <h3 className="text-sm font-medium text-ink mb-1">Estructura (spec)</h3>
            <p className="text-xs text-faint mb-2">Lo que la IA generó. Editalo y aplicá para ajustar a mano.</p>
            <textarea
              value={specText}
              onChange={(e) => setSpecText(e.target.value)}
              spellCheck={false}
              className="w-full h-44 rounded-lg border border-line bg-canvas p-3 font-mono text-xs text-ink"
            />
            {specErr && <p className="text-xs text-red-600 mt-1">{specErr}</p>}
            <button
              onClick={aplicarSpecText}
              className="mt-2 rounded-lg bg-brand-soft text-brand-dark px-3 py-1.5 text-sm font-medium"
            >
              Aplicar spec
            </button>
          </div>
        </div>

        {/* Columna derecha: plano + despiece */}
        <div className="space-y-3">
          <div className="rounded-xl border border-line bg-surface p-4">
            <h3 className="text-sm font-medium text-ink mb-3">
              Plano técnico acotado <span className="text-faint font-normal">· cm</span>
            </h3>
            <div className="grid gap-3 sm:grid-cols-2">
              <div>
                <p className="text-xs text-faint mb-1 uppercase tracking-wide">Frente</p>
                <div className="bg-white rounded-lg border border-line [&>svg]:w-full [&>svg]:h-auto" dangerouslySetInnerHTML={{ __html: views.frente }} />
              </div>
              <div>
                <p className="text-xs text-faint mb-1 uppercase tracking-wide">Lateral</p>
                <div className="bg-white rounded-lg border border-line [&>svg]:w-full [&>svg]:h-auto" dangerouslySetInnerHTML={{ __html: views.lateral }} />
              </div>
              <div className="sm:col-span-2">
                <p className="text-xs text-faint mb-1 uppercase tracking-wide">Planta</p>
                <div className="bg-white rounded-lg border border-line [&>svg]:w-full [&>svg]:h-auto" dangerouslySetInnerHTML={{ __html: views.planta }} />
              </div>
            </div>
          </div>

          <div className="rounded-xl border border-line bg-surface overflow-hidden">
            <div className="flex items-center justify-between px-4 py-2 border-b border-line">
              <h3 className="text-sm font-medium text-ink">Despiece</h3>
              <span className="text-xs text-faint">sin precio</span>
            </div>
            <table className="w-full text-sm">
              <thead>
                <tr className="text-faint text-xs uppercase">
                  <th className="text-left px-4 py-2 font-medium">Pieza</th>
                  <th className="text-left px-4 py-2 font-medium">Cant.</th>
                  <th className="text-left px-4 py-2 font-medium">Corte (cm)</th>
                  <th className="text-left px-4 py-2 font-medium">Esp.</th>
                  <th className="text-left px-4 py-2 font-medium">Material</th>
                </tr>
              </thead>
              <tbody>
                {despiece.map((r, i) => (
                  <tr key={i} className="border-t border-line">
                    <td className="px-4 py-2 text-ink">
                      <span
                        className="inline-block w-2.5 h-2.5 rounded-sm mr-2 align-middle"
                        style={{ background: `#${COL3D[r.role].toString(16).padStart(6, "0")}` }}
                      />
                      {r.nombre}
                    </td>
                    <td className="px-4 py-2 text-ink">{r.cantidad}</td>
                    <td className="px-4 py-2 text-ink">{r.corte}</td>
                    <td className="px-4 py-2 text-ink">{r.espesor}</td>
                    <td className="px-4 py-2 text-faint">{r.material}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      </div>

      {/* Código de corte para la Calculadora */}
      <div className="rounded-xl border border-line bg-surface p-4">
        <div className="flex items-center justify-between gap-3 mb-2">
          <h3 className="text-sm font-medium text-ink">Cortes para la Calculadora</h3>
          <div className="flex gap-2">
            <button
              onClick={copiarCortes}
              className="rounded-lg bg-brand-dark text-white px-3 py-1.5 text-sm font-medium"
            >
              {copied ? "¡Copiado!" : "Copiar código"}
            </button>
            <button
              onClick={() => router.push("/calculadora")}
              className="rounded-lg bg-brand-soft text-brand-dark px-3 py-1.5 text-sm font-medium"
            >
              Abrir Calculadora
            </button>
          </div>
        </div>
        <p className="text-xs text-faint mb-2">
          Pegalo en el import de la Calculadora. Formato <code>#Mueble</code>, medidas en cm, material = espesor en mm.
        </p>
        <textarea
          readOnly
          value={cortesCode}
          spellCheck={false}
          className="w-full h-32 rounded-lg border border-line bg-canvas p-3 font-mono text-xs text-ink"
        />
      </div>

      {/* Render foto-real */}
      <div className="rounded-xl border border-line bg-surface p-4">
        <div className="flex items-center justify-between gap-3 mb-3">
          <h3 className="text-sm font-medium text-ink">Render foto-real</h3>
          <span className="text-xs text-faint">fiel al 3D · gpt-image-1</span>
        </div>
        <div className="grid gap-3 sm:grid-cols-4">
          <label className="block">
            <span className="text-xs text-faint">Material</span>
            <select value={material} onChange={(e) => setMaterial(e.target.value)} className="w-full mt-1 rounded-lg border border-line bg-canvas p-2 text-sm text-ink">
              {MATERIALES.map((m) => <option key={m} value={m}>{m}</option>)}
            </select>
          </label>
          <label className="block">
            <span className="text-xs text-faint">Herrajes</span>
            <select value={herrajes} onChange={(e) => setHerrajes(e.target.value)} className="w-full mt-1 rounded-lg border border-line bg-canvas p-2 text-sm text-ink">
              {HERRAJES.map((m) => <option key={m} value={m}>{m}</option>)}
            </select>
          </label>
          <label className="block">
            <span className="text-xs text-faint">Ambiente</span>
            <select value={ambiente} onChange={(e) => setAmbiente(e.target.value)} className="w-full mt-1 rounded-lg border border-line bg-canvas p-2 text-sm text-ink">
              {AMBIENTES.map((m) => <option key={m} value={m}>{m}</option>)}
            </select>
          </label>
          <label className="block">
            <span className="text-xs text-faint">Estilo</span>
            <select value={estiloRender} onChange={(e) => setEstiloRender(e.target.value)} className="w-full mt-1 rounded-lg border border-line bg-canvas p-2 text-sm text-ink">
              {ESTILOS.map((m) => <option key={m} value={m}>{m}</option>)}
            </select>
          </label>
        </div>
        <div className="mt-3">
          <div className="flex items-center justify-between mb-1">
            <span className="text-xs text-faint">Detalles adicionales (opcional)</span>
            <button
              type="button"
              onClick={mejorarPrompt}
              disabled={mejorando}
              className="text-xs text-brand-dark underline disabled:opacity-50"
            >
              {mejorando ? "Mejorando…" : "✨ Mejorar con IA"}
            </button>
          </div>
          <textarea
            value={detallesRender}
            onChange={(e) => setDetallesRender(e.target.value)}
            className="w-full h-20 rounded-lg border border-line bg-canvas p-2 text-sm text-ink"
            placeholder="Ej: luz de atardecer entrando por una ventana, planta al costado, piso de madera clara…"
          />
        </div>
        <div className="flex items-center gap-3 mt-3 flex-wrap">
          <label className="inline-flex items-center gap-2 text-sm text-ink">
            <span className="text-xs text-faint">Calidad</span>
            <select
              value={calidad}
              onChange={(e) => setCalidad(e.target.value as "low" | "medium" | "high")}
              className="rounded-lg border border-line bg-canvas p-2 text-sm text-ink"
            >
              <option value="low">Borrador (más barato)</option>
              <option value="medium">Estándar</option>
              <option value="high">Alta (para cliente)</option>
            </select>
          </label>
          <button
            onClick={generarRender}
            disabled={rendering}
            className="inline-flex items-center gap-2 rounded-lg bg-brand-dark px-4 py-2 text-sm font-semibold text-white disabled:opacity-60"
          >
            {rendering && <span className="inline-block w-4 h-4 rounded-full border-2 border-white/40 border-t-white animate-spin" />}
            {rendering ? "Generando render…" : "Generar render"}
          </button>
          {renderErr && <span className="text-sm text-red-600">{renderErr}</span>}
          <span className="text-xs text-faint">Tarda unos segundos · consume crédito de OpenAI.</span>
        </div>
        {renderUrl && (
          <div className="mt-4 space-y-2">
            {/* eslint-disable-next-line @next/next/no-img-element */}
            <img src={renderUrl} alt="render" className="w-full max-w-xl rounded-lg border border-line" />
            <a href={renderUrl} download="render.png" className="inline-block text-sm text-brand-dark underline">Descargar PNG</a>
          </div>
        )}
      </div>
    </div>
  );
}
