import { useState, useEffect, useRef } from "react";
import { useNavigate, useParams, Link } from "react-router-dom";
import api from "../../api/client";
import ConfirmDialog from "../../components/ConfirmDialog";
import PlaybackModal from "../PlaybackModal";
import { getLocalizedValue } from "../melodyUtils";

const mutedStyle = { color: "var(--text-muted)" };
const inputClass = "w-full px-3 py-2 rounded-md text-sm border";

function copyText(text, onSuccess) {
  const fallback = () => {
    const ta = document.createElement("textarea");
    ta.value = text;
    ta.style.cssText = "position:fixed;top:0;left:0;opacity:0";
    document.body.appendChild(ta);
    ta.focus();
    ta.select();
    try { document.execCommand("copy"); onSuccess?.(); } catch (_) {}
    document.body.removeChild(ta);
  };
  if (navigator.clipboard) {
    navigator.clipboard.writeText(text).then(onSuccess).catch(fallback);
  } else {
    fallback();
  }
}

function countSteps(stepsStr) {
  if (!stepsStr || !stepsStr.trim()) return 0;
  return stepsStr.trim().split(",").length;
}

function validateSteps(stepsStr) {
  if (!stepsStr || !stepsStr.trim()) return "Steps are required.";
  const tokens = stepsStr.trim().split(",");
  for (const token of tokens) {
    const parts = token.split("+");
    for (const part of parts) {
      const trimmed = part.trim();
      if (trimmed === "") return `Invalid token near: "${token.trim()}" — empty part found.`;
      const n = parseInt(trimmed, 10);
      if (isNaN(n)) return `Invalid step value: "${trimmed}" — must be a number 0–16.`;
      if (n < 0 || n > 16) return `Step value "${trimmed}" is out of range (must be 0–16).`;
    }
  }
  return null;
}

async function downloadBinary(binaryUrl, filename) {
  const token = localStorage.getItem("access_token");
  const res = await fetch(`/api${binaryUrl}`, {
    headers: token ? { Authorization: `Bearer ${token}` } : {},
  });
  if (!res.ok) throw new Error(`Download failed: ${res.statusText}`);
  const blob = await res.blob();
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = filename;
  a.click();
  URL.revokeObjectURL(url);
}

export default function ArchetypeForm() {
  const { id } = useParams();
  const isEdit = Boolean(id);
  const navigate = useNavigate();

  const [name, setName] = useState("");
  const [pid, setPid] = useState("");
  const [steps, setSteps] = useState("");
  const [isBuiltin, setIsBuiltin] = useState(false);
  const [savedPid, setSavedPid] = useState("");

  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState("");
  const [successMsg, setSuccessMsg] = useState("");

  const [binaryBuilt, setBinaryBuilt] = useState(false);
  const [binaryUrl, setBinaryUrl] = useState(null);
  const [progmemCode, setProgmemCode] = useState("");
  const [copied, setCopied] = useState(false);
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);

  const [showDelete, setShowDelete] = useState(false);
  const [deleteWarningConfirmed, setDeleteWarningConfirmed] = useState(false);
  const [assignedCount, setAssignedCount] = useState(0);
  const [assignedMelodies, setAssignedMelodies] = useState([]); // [{id, nameRaw}]
  const [loadingAssigned, setLoadingAssigned] = useState(false);
  const [primaryLang, setPrimaryLang] = useState("en");

  // Playback
  const [showPlayback, setShowPlayback] = useState(false);
  // currentBuiltMelody: the live archetype object (for playback + binary_url)
  const [currentBuiltMelody, setCurrentBuiltMelody] = useState(null);

  const codeRef = useRef(null);

  useEffect(() => {
    api.get("/settings/melody").then((ms) => setPrimaryLang(ms.primary_language || "en")).catch(() => {});
    if (isEdit) loadArchetype();
  }, [id]);

  const loadArchetype = async () => {
    setLoading(true);
    try {
      const data = await api.get(`/builder/melodies/${id}`);
      setName(data.name || "");
      setPid(data.pid || "");
      setSteps(data.steps || "");
      setIsBuiltin(Boolean(data.is_builtin));
      setSavedPid(data.pid || "");
      setBinaryBuilt(Boolean(data.binary_path));
      setBinaryUrl(data.binary_url || null);
      setProgmemCode(data.progmem_code || "");
      setAssignedCount(data.assigned_melody_ids?.length || 0);
      setHasUnsavedChanges(false);
      setCurrentBuiltMelody(data);
      // Load assigned melody details
      if (data.assigned_melody_ids?.length > 0) {
        fetchAssignedMelodies(data.assigned_melody_ids);
      }
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  const fetchAssignedMelodies = async (ids) => {
    setLoadingAssigned(true);
    try {
      const results = await Promise.allSettled(ids.map((mid) => api.get(`/melodies/${mid}`)));
      const details = results
        .filter((r) => r.status === "fulfilled" && r.value)
        .map((r) => ({ id: r.value.id, nameRaw: r.value.information?.name }));
      setAssignedMelodies(details);
    } catch { /* best-effort */ }
    finally { setLoadingAssigned(false); }
  };

  const handleNameChange = (v) => { setName(v); setHasUnsavedChanges(true); };
  const handlePidChange = (v) => { setPid(v.toLowerCase().replace(/[^a-z0-9_]/g, "")); setHasUnsavedChanges(true); };
  const handleStepsChange = (v) => { setSteps(v); setHasUnsavedChanges(true); };

  const handleSave = async () => {
    if (!name.trim()) { setError("Name is required."); return; }
    if (!pid.trim()) { setError("PID is required."); return; }
    const stepsError = validateSteps(steps);
    if (stepsError) { setError(stepsError); return; }

    setSaving(true);
    setError("");
    setSuccessMsg("");
    try {
      const existing = await api.get("/builder/melodies");
      const list = existing.melodies || [];
      const dupName = list.find((m) => m.id !== id && m.name.toLowerCase() === name.trim().toLowerCase());
      if (dupName) { setError(`An archetype with the name "${name.trim()}" already exists.`); return; }
      const dupPid = list.find((m) => m.id !== id && m.pid && m.pid.toLowerCase() === pid.trim().toLowerCase());
      if (dupPid) { setError(`An archetype with the PID "${pid.trim()}" already exists.`); return; }

      const body = { name: name.trim(), pid: pid.trim(), steps: steps.trim(), is_builtin: isBuiltin };

      if (isEdit) {
        // PUT triggers auto-rebuild + outdated flagging on the backend
        const updated = await api.put(`/builder/melodies/${id}`, body);
        setSavedPid(pid.trim());
        setBinaryBuilt(Boolean(updated.binary_path));
        setBinaryUrl(updated.binary_url || null);
        setProgmemCode(updated.progmem_code || "");
        setCurrentBuiltMelody(updated);
        setHasUnsavedChanges(false);
        setSuccessMsg("Rebuilt and saved successfully.");
      } else {
        // POST triggers auto-build on the backend
        const created = await api.post("/builder/melodies", body);
        navigate(`/melodies/archetypes/${created.id}`);
      }
    } catch (err) {
      setError(err.message);
    } finally {
      setSaving(false);
    }
  };

  const handleCopy = () => {
    if (!progmemCode) return;
    copyText(progmemCode, () => { setCopied(true); setTimeout(() => setCopied(false), 2000); });
  };

  const handleDelete = async () => {
    try {
      await api.delete(`/builder/melodies/${id}`);
      navigate("/melodies/archetypes");
    } catch (err) {
      setError(err.message);
      setShowDelete(false);
      setDeleteWarningConfirmed(false);
    }
  };

  // Build a "virtual" builtMelody for playback using current steps (even if unsaved)
  const playbackBuiltMelody = currentBuiltMelody
    ? { ...currentBuiltMelody, steps: steps }
    : { id: "preview", name: name || "Preview", pid: pid || "", steps, binary_url: null };

  if (loading) {
    return <div className="text-center py-8" style={mutedStyle}>Loading...</div>;
  }

  return (
    <div>
      {/* Header row */}
      <div className="flex items-center justify-between mb-6">
        <div>
          <button onClick={() => navigate("/melodies/archetypes")} className="text-sm mb-2 inline-block" style={{ color: "var(--accent)" }}>
            &larr; Back to Archetypes
          </button>
          <h1 className="text-2xl font-bold" style={{ color: "var(--text-heading)" }}>
            {isEdit ? "Edit Archetype" : "New Archetype"}
          </h1>
        </div>
        <div className="flex items-center gap-2">
          {/* Section 1: Built-in + Play */}
          <button
            onClick={() => setIsBuiltin((v) => { setHasUnsavedChanges(true); return !v; })}
            className="px-3 py-2 text-sm rounded-md transition-colors flex items-center gap-1.5"
            style={isBuiltin
              ? { backgroundColor: "rgba(59,130,246,0.15)", color: "#60a5fa", border: "1px solid rgba(59,130,246,0.3)" }
              : { backgroundColor: "var(--bg-card-hover)", color: "var(--text-muted)", border: "1px solid var(--border-primary)" }
            }
            title="Toggle built-in flag"
          >
            {isBuiltin ? "Built-in ✓" : "Built-in"}
          </button>
          <button
            onClick={() => setShowPlayback(true)}
            disabled={!steps.trim()}
            title="Preview current steps"
            className="px-3 py-2 text-sm rounded-md transition-colors disabled:opacity-40 flex items-center gap-1.5"
            style={{ backgroundColor: "var(--bg-card-hover)", color: "#4ade80", border: "1px solid rgba(74,222,128,0.3)" }}
          >
            <svg width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style={{ flexShrink: 0 }}>
              <path d="M3 5C3 2.23858 5.23858 0 8 0C10.7614 0 13 2.23858 13 5V8L15 10V12H1V10L3 8V5Z" fill="currentColor"/>
              <path d="M7.99999 16C6.69378 16 5.58254 15.1652 5.1707 14H10.8293C10.4175 15.1652 9.30621 16 7.99999 16Z" fill="currentColor"/>
            </svg> Play
          </button>

          {/* Divider */}
          <div style={{ width: 1, height: 24, backgroundColor: "var(--border-primary)", margin: "0 2px" }} />

          {/* Section 2: Cancel + Delete */}
          <button
            onClick={() => navigate("/melodies/archetypes")}
            className="px-4 py-2 text-sm rounded-md transition-colors"
            style={{ backgroundColor: "var(--bg-card-hover)", color: "var(--text-primary)", border: "1px solid var(--border-primary)" }}
          >
            Cancel
          </button>
          {isEdit && (
            <button onClick={() => setShowDelete(true)}
              className="px-4 py-2 text-sm rounded-md transition-colors"
              style={{ backgroundColor: "var(--danger)", color: "#fff" }}>
              Delete
            </button>
          )}

          {/* Divider */}
          <div style={{ width: 1, height: 24, backgroundColor: "var(--border-primary)", margin: "0 2px" }} />

          {/* Section 3: Save */}
          <button
            onClick={handleSave}
            disabled={saving}
            className="px-4 py-2 text-sm rounded-md disabled:opacity-50 transition-colors font-medium"
            style={{ backgroundColor: "var(--btn-primary)", color: "var(--text-white)" }}
          >
            {saving ? "Saving..." : isEdit ? "Rebuild and Save" : "Create and Build"}
          </button>
        </div>
      </div>

      {error && (
        <div className="text-sm rounded-md p-3 mb-4 border" style={{ backgroundColor: "var(--danger-bg)", borderColor: "var(--danger)", color: "var(--danger-text)" }}>
          {error}
        </div>
      )}
      {successMsg && (
        <div className="text-sm rounded-md p-3 mb-4 border" style={{ backgroundColor: "var(--success-bg)", borderColor: "var(--success)", color: "var(--success-text)" }}>
          {successMsg}
        </div>
      )}

      <div className="space-y-6">
        {/* ── Archetype Info ────────────────────────────────────────── */}
        <section className="ui-section-card">
          <div className="ui-section-card__title-row">
            <h2 className="ui-section-card__title">Archetype Info</h2>
          </div>
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div>
              <label className="ui-form-label">Name *</label>
              <input type="text" value={name} onChange={(e) => handleNameChange(e.target.value)}
                placeholder="e.g. Doksologia_3k" className={inputClass} />
            </div>
            <div>
              <label className="ui-form-label">PID (Playback ID) *</label>
              <input type="text" value={pid} onChange={(e) => handlePidChange(e.target.value)}
                placeholder="e.g. builtin_doksologia_3k" className={inputClass} />
              <p className="text-xs mt-1" style={mutedStyle}>Lowercase letters, numbers, and underscores only. Must be unique.</p>
            </div>
            <div className="md:col-span-2">
              <div className="flex items-center justify-between mb-1">
                <label className="ui-form-label">Steps *</label>
                <span className="text-xs" style={mutedStyle}>{countSteps(steps)} steps</span>
              </div>
              <textarea
                value={steps}
                onChange={(e) => handleStepsChange(e.target.value)}
                rows={5}
                placeholder={"e.g. 1,2,2+1,1,2,3+1,0,3\n\n• Comma-separated values\n• Single bell: 1, 2, 3...\n• Multiple bells: 2+3+1\n• Silence: 0"}
                className={inputClass}
                style={{ fontFamily: "monospace", resize: "vertical" }}
              />
              <p className="text-xs mt-1" style={mutedStyle}>
                Each value = one step. Bell numbers 1–16 (1 = highest). Combine with +. Silence = 0.
              </p>
            </div>
          </div>
        </section>

        {/* ── Melodies using this Archetype ─────────────────────────── */}
        {isEdit && (
          <section className="ui-section-card">
            <div className="ui-section-card__title-row">
              <h2 className="ui-section-card__title">Melodies Using This Archetype</h2>
              <span className="text-xs px-2 py-0.5 rounded-full ml-2"
                style={{ backgroundColor: "rgba(59,130,246,0.12)", color: "#60a5fa" }}>
                {assignedCount}
              </span>
            </div>
            {loadingAssigned ? (
              <p className="text-sm" style={mutedStyle}>Loading...</p>
            ) : assignedMelodies.length === 0 ? (
              <p className="text-sm" style={mutedStyle}>None</p>
            ) : (
              <div className="space-y-1 max-h-44 overflow-y-auto">
                {assignedMelodies.slice(0, 20).map((m) => (
                  <Link key={m.id} to={`/melodies/${m.id}`} target="_blank" rel="noopener noreferrer"
                    className="flex items-center justify-between px-3 py-2 rounded-lg border transition-colors hover:bg-[var(--bg-card-hover)]"
                    style={{ borderColor: "var(--border-primary)", color: "var(--text-heading)", textDecoration: "none" }}>
                    <span className="text-sm font-medium">{getLocalizedValue(m.nameRaw, primaryLang, m.id)}</span>
                    <span className="text-xs" style={{ color: "var(--accent)" }}>Open →</span>
                  </Link>
                ))}
              </div>
            )}
          </section>
        )}

        {/* ── Build Output ─────────────────────────────────────────── */}
        {isEdit && (
          <section className="ui-section-card">
            <div className="ui-section-card__title-row">
              <h2 className="ui-section-card__title">Build Output</h2>
            </div>
            <p className="text-sm mb-3" style={mutedStyle}>
              Binary and PROGMEM code are auto-rebuilt on every save.
              {hasUnsavedChanges && (
                <span style={{ color: "var(--warning, #f59e0b)", fontWeight: 600 }}> — You have unsaved changes.</span>
              )}
            </p>

            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
              {/* Binary */}
              <div className="rounded-lg p-4 border space-y-2" style={{ borderColor: "var(--border-primary)", backgroundColor: "var(--bg-primary)" }}>
                <div className="flex items-center justify-between">
                  <div>
                    <h3 className="text-sm font-semibold" style={{ color: "var(--text-heading)" }}>Binary (.bsm)</h3>
                    <p className="text-xs mt-0.5" style={mutedStyle}>For SD card playback on the controller</p>
                  </div>
                  <span className={`px-2 py-0.5 text-xs rounded-full ${binaryBuilt ? "" : "opacity-50"}`}
                    style={binaryBuilt
                      ? { backgroundColor: "var(--success-bg)", color: "var(--success-text)" }
                      : { backgroundColor: "var(--bg-card-hover)", color: "var(--text-muted)" }}>
                    {binaryBuilt ? "Built" : "Not built"}
                  </span>
                </div>
                {binaryUrl && (
                  <button type="button"
                    onClick={() => downloadBinary(binaryUrl, `${savedPid}.bsm`).catch((e) => setError(e.message))}
                    className="block w-full text-center text-xs underline cursor-pointer"
                    style={{ color: "var(--accent)", background: "none", border: "none", padding: 0 }}>
                    Download {savedPid}.bsm
                  </button>
                )}
              </div>

              {/* PROGMEM */}
              <div className="rounded-lg p-4 border space-y-2" style={{ borderColor: "var(--border-primary)", backgroundColor: "var(--bg-primary)" }}>
                <div className="flex items-center justify-between">
                  <div>
                    <h3 className="text-sm font-semibold" style={{ color: "var(--text-heading)" }}>PROGMEM Code</h3>
                    <p className="text-xs mt-0.5" style={mutedStyle}>For built-in firmware (ESP32 PROGMEM)</p>
                  </div>
                  <span className={`px-2 py-0.5 text-xs rounded-full ${progmemCode ? "" : "opacity-50"}`}
                    style={progmemCode
                      ? { backgroundColor: "var(--success-bg)", color: "var(--success-text)" }
                      : { backgroundColor: "var(--bg-card-hover)", color: "var(--text-muted)" }}>
                    {progmemCode ? "Generated" : "Not generated"}
                  </span>
                </div>
              </div>
            </div>

            {progmemCode && (
              <div className="mt-4 rounded-lg border overflow-hidden" style={{ borderColor: "var(--border-primary)" }}>
                <div className="flex items-center justify-between px-4 py-2 border-b"
                  style={{ backgroundColor: "var(--bg-card-hover)", borderColor: "var(--border-primary)" }}>
                  <span className="text-xs font-medium font-mono" style={{ color: "var(--text-muted)" }}>
                    PROGMEM C Code — copy into your firmware
                  </span>
                  <button onClick={handleCopy} className="text-xs px-3 py-1 rounded transition-colors"
                    style={{
                      backgroundColor: copied ? "var(--success-bg)" : "var(--bg-primary)",
                      color: copied ? "var(--success-text)" : "var(--text-secondary)",
                      border: "1px solid var(--border-primary)",
                    }}>
                    {copied ? "Copied!" : "Copy"}
                  </button>
                </div>
                <pre ref={codeRef} className="p-4 text-xs overflow-x-auto"
                  style={{ backgroundColor: "var(--bg-primary)", color: "var(--text-primary)", fontFamily: "monospace", whiteSpace: "pre", maxHeight: "400px", overflowY: "auto" }}>
                  {progmemCode}
                </pre>
              </div>
            )}
          </section>
        )}

        {!isEdit && (
          <div className="ui-section-card text-sm" style={{ color: "var(--text-muted)" }}>
            Binary and PROGMEM code will be generated automatically when you click "Create and Build".
          </div>
        )}
      </div>

      {/* Delete: two-stage if assigned */}
      {showDelete && !deleteWarningConfirmed && assignedCount > 0 && (
        <div className="fixed inset-0 flex items-center justify-center z-50" style={{ backgroundColor: "rgba(0,0,0,0.6)" }}>
          <div className="w-full max-w-md rounded-lg border shadow-xl p-6 space-y-4"
            style={{ backgroundColor: "var(--bg-card)", borderColor: "var(--border-primary)" }}>
            <h3 className="text-base font-semibold" style={{ color: "var(--text-heading)" }}>Archetype In Use</h3>
            <div className="rounded-md p-3 border text-sm"
              style={{ backgroundColor: "var(--warning-bg, rgba(245,158,11,0.1))", borderColor: "var(--warning, #f59e0b)", color: "var(--warning-text, #f59e0b)" }}>
              <strong>"{name}"</strong> is currently assigned to{" "}
              <strong>{assignedCount} {assignedCount === 1 ? "melody" : "melodies"}</strong>.
              Deleting it will flag those melodies as <strong>outdated</strong>.
            </div>
            <p className="text-sm" style={{ color: "var(--text-muted)" }}>Do you still want to delete this archetype?</p>
            <div className="flex justify-end gap-3">
              <button onClick={() => { setShowDelete(false); setDeleteWarningConfirmed(false); }}
                className="px-4 py-2 text-sm rounded-md transition-colors"
                style={{ backgroundColor: "var(--bg-card-hover)", color: "var(--text-primary)" }}>Cancel</button>
              <button onClick={() => setDeleteWarningConfirmed(true)}
                className="px-4 py-2 text-sm rounded-md transition-colors font-medium"
                style={{ backgroundColor: "var(--danger)", color: "#fff" }}>
                Yes, Delete Anyway
              </button>
            </div>
          </div>
        </div>
      )}

      <ConfirmDialog
        open={showDelete && (deleteWarningConfirmed || assignedCount === 0)}
        title="Delete Archetype"
        message={`Are you sure you want to permanently delete "${name}"? This will also delete the .bsm binary file. This action cannot be undone.`}
        onConfirm={handleDelete}
        onCancel={() => { setShowDelete(false); setDeleteWarningConfirmed(false); }}
      />

      <PlaybackModal
        open={showPlayback}
        melody={null}
        builtMelody={playbackBuiltMelody}
        files={null}
        archetypeCsv={steps}
        onClose={() => setShowPlayback(false)}
      />
    </div>
  );
}
