import { useState } from "react";
import api from "../../api/client";

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

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

function computeStepsAndNotes(stepsStr) {
  if (!stepsStr || !stepsStr.trim()) return { steps: 0, totalNotes: 0 };
  const tokens = stepsStr.trim().split(",");
  const bellSet = new Set();
  for (const token of tokens) {
    for (const part of token.split("+")) {
      const n = parseInt(part.trim(), 10);
      if (!isNaN(n) && n >= 1 && n <= 16) bellSet.add(n);
    }
  }
  return { steps: tokens.length, totalNotes: bellSet.size || 1 };
}

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;
}

export default function BuildOnTheFlyModal({ open, melodyId, currentMelody, currentBuiltMelody, defaultName, defaultPid, onClose, onSuccess }) {
  const [name, setName] = useState(defaultName || "");
  const [pid, setPid] = useState(defaultPid || "");
  const [steps, setSteps] = useState("");
  const [building, setBuilding] = useState(false);
  const [error, setError] = useState("");
  const [statusMsg, setStatusMsg] = useState("");

  if (!open) return null;

  const handleBuildAndUpload = async () => {
    if (!name.trim()) { setError("Name is required."); return; }
    if (!pid.trim()) { setError("PID is required."); return; }
    if (!steps.trim()) { setError("Steps are required."); return; }

    const stepsError = validateSteps(steps);
    if (stepsError) { setError(stepsError); return; }

    setBuilding(true);
    setError("");
    setStatusMsg("");

    try {
      setStatusMsg("Checking for conflicts...");
      const existing = await api.get("/builder/melodies");
      const list = existing.melodies || [];
      const dupName = list.find((m) => m.name.toLowerCase() === name.trim().toLowerCase());
      if (dupName) {
        setError(`An archetype with the name "${name.trim()}" already exists.`);
        setBuilding(false);
        setStatusMsg("");
        return;
      }
      const dupPid = list.find((m) => m.pid && m.pid.toLowerCase() === pid.trim().toLowerCase());
      if (dupPid) {
        setError(`An archetype with the PID "${pid.trim()}" already exists.`);
        setBuilding(false);
        setStatusMsg("");
        return;
      }

      setStatusMsg("Creating archetype record...");
      const created = await api.post("/builder/melodies", {
        name: name.trim(),
        pid: pid.trim(),
        steps: steps.trim(),
      });
      const builtId = created.id;

      setStatusMsg("Building binary...");
      const built = await api.post(`/builder/melodies/${builtId}/build-binary`);

      setStatusMsg("Uploading to cloud storage...");
      const token = localStorage.getItem("access_token");
      const res = await fetch(`/api${built.binary_url}`, {
        headers: token ? { Authorization: `Bearer ${token}` } : {},
      });
      if (!res.ok) throw new Error(`Failed to fetch binary: ${res.statusText}`);
      const blob = await res.blob();
      const file = new File([blob], `${pid.trim()}.bsm`, { type: "application/octet-stream" });
      await api.upload(`/melodies/${melodyId}/upload/binary`, file);

      setStatusMsg("Linking to melody...");
      // Unassign from any previously assigned archetype first
      if (currentBuiltMelody?.id) {
        try {
          await api.post(`/builder/melodies/${currentBuiltMelody.id}/unassign?firestore_melody_id=${melodyId}`);
        } catch { /* best-effort */ }
      }
      await api.post(`/builder/melodies/${builtId}/assign?firestore_melody_id=${melodyId}`);

      setStatusMsg("Saving archetype data...");
      const csv = steps.trim();
      const { steps: stepCount, totalNotes } = computeStepsAndNotes(csv);
      if (currentMelody && csv) {
        const existingInfo = currentMelody.information || {};
        const body = {
          information: {
            ...existingInfo,
            archetype_csv: csv,
            steps: stepCount,
            totalNotes,
            outdated_archetype: false,
          },
          default_settings: currentMelody.default_settings,
          type: currentMelody.type,
          uid: currentMelody.uid,
          pid: currentMelody.pid,
        };
        if (currentMelody.url) body.url = currentMelody.url;
        await api.put(`/melodies/${melodyId}`, body);
      }

      setStatusMsg("Done!");
      onSuccess({ name: name.trim(), pid: pid.trim(), steps: stepCount, totalNotes, archetype_csv: csv });
    } catch (err) {
      setError(err.message);
      setStatusMsg("");
    } finally {
      setBuilding(false);
    }
  };

  return (
    <div
      className="fixed inset-0 flex items-center justify-center z-50"
      style={{ backgroundColor: "rgba(0,0,0,0.6)" }}
      onClick={(e) => e.target === e.currentTarget && !building && onClose()}
    >
      <div
        className="w-full max-w-xl rounded-lg border shadow-xl"
        style={{ backgroundColor: "var(--bg-card)", borderColor: "var(--border-primary)" }}
      >
        <div className="flex items-center justify-between px-6 py-4 border-b" style={{ borderColor: "var(--border-primary)" }}>
          <div>
            <h2 className="text-lg font-semibold" style={{ color: "var(--text-heading)" }}>Build on the Fly</h2>
            <p className="text-xs mt-0.5" style={mutedStyle}>Enter steps, build binary, and upload — all in one step.</p>
          </div>
          {!building && (
            <button onClick={onClose} className="text-xl leading-none" style={mutedStyle}>&times;</button>
          )}
        </div>

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

          <div className="grid grid-cols-2 gap-4">
            <div>
              <label className="block text-sm font-medium mb-1" style={labelStyle}>Name *</label>
              <input type="text" value={name} onChange={(e) => setName(e.target.value)} placeholder="e.g. Doksologia_3k" className={inputClass} disabled={building} />
            </div>
            <div>
              <label className="block text-sm font-medium mb-1" style={labelStyle}>PID *</label>
              <input type="text" value={pid} onChange={(e) => setPid(e.target.value)} placeholder="e.g. builtin_doksologia_3k" className={inputClass} disabled={building} />
            </div>
          </div>

          <div>
            <div className="flex items-center justify-between mb-1">
              <label className="block text-sm font-medium" style={labelStyle}>Steps *</label>
              <span className="text-xs" style={mutedStyle}>{countSteps(steps)} steps</span>
            </div>
            <textarea
              value={steps}
              onChange={(e) => setSteps(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: 2+3+1\n• Silence: 0"}
              className={inputClass}
              style={{ fontFamily: "monospace", resize: "vertical" }}
              disabled={building}
            />
          </div>

          {statusMsg && !error && (
            <div className="text-sm rounded-md p-2 text-center" style={{ color: "var(--text-muted)", backgroundColor: "var(--bg-primary)" }}>
              {statusMsg}
            </div>
          )}
        </div>

        <div className="flex items-center justify-end gap-3 px-6 py-4 border-t" style={{ borderColor: "var(--border-primary)" }}>
          <button
            onClick={onClose}
            disabled={building}
            className="px-4 py-2 text-sm rounded-md disabled:opacity-50 transition-colors"
            style={{ backgroundColor: "var(--bg-card-hover)", color: "var(--text-primary)" }}
          >
            Cancel
          </button>
          <button
            onClick={handleBuildAndUpload}
            disabled={building}
            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)" }}
          >
            {building ? "Building & Uploading..." : "Build & Upload"}
          </button>
        </div>
      </div>
    </div>
  );
}
