// Designs.jsx — save/load designs to localStorage, plus JSON file import/export.
// Exposes a `<DesignsMenu>` dropdown for the toolbar.

const { useState, useEffect, useRef } = React;

const STORE_KEY = "lps:designs";
const AUTOSAVE_KEY = "lps:autosave";
const SCHEMA_VERSION = 1;

// --- Storage helpers --------------------------------------------------------

function loadAll() {
  try {
    const raw = localStorage.getItem(STORE_KEY);
    if (!raw) return [];
    const parsed = JSON.parse(raw);
    if (!Array.isArray(parsed)) return [];
    return parsed;
  } catch (e) {
    console.warn("Could not load designs:", e);
    return [];
  }
}

function saveAll(list) {
  try {
    localStorage.setItem(STORE_KEY, JSON.stringify(list));
    return true;
  } catch (e) {
    alert("Could not save: " + e.message);
    return false;
  }
}

function uid() {
  return "d" + Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
}

function loadAutosave() {
  try {
    const raw = localStorage.getItem(AUTOSAVE_KEY);
    if (!raw) return null;
    const parsed = JSON.parse(raw);
    if (parsed && parsed.v === SCHEMA_VERSION && parsed.state) return parsed.state;
    return null;
  } catch (e) {
    return null;
  }
}

function writeAutosave(state) {
  try {
    localStorage.setItem(AUTOSAVE_KEY, JSON.stringify({ v: SCHEMA_VERSION, state }));
  } catch (e) {
    // fail quietly — autosave shouldn't interrupt the user
  }
}

function formatTimestamp(ts) {
  if (!ts) return "";
  const d = new Date(ts);
  const now = new Date();
  const sameDay = d.toDateString() === now.toDateString();
  if (sameDay) {
    return d.toLocaleTimeString(undefined, { hour: "numeric", minute: "2-digit" });
  }
  return d.toLocaleDateString(undefined, { month: "short", day: "numeric" });
}

// --- Design API the App uses ------------------------------------------------

function createDesign(name, state) {
  const list = loadAll();
  const item = { id: uid(), name: name || "Untitled", savedAt: Date.now(), state };
  list.unshift(item);
  saveAll(list);
  return item;
}

function updateDesign(id, patch) {
  const list = loadAll();
  const i = list.findIndex((d) => d.id === id);
  if (i < 0) return null;
  list[i] = { ...list[i], ...patch, savedAt: Date.now() };
  saveAll(list);
  return list[i];
}

function deleteDesign(id) {
  const list = loadAll().filter((d) => d.id !== id);
  saveAll(list);
}

function exportToFile(design) {
  const payload = {
    type: "lyrics-poster-design",
    v: SCHEMA_VERSION,
    name: design.name,
    savedAt: design.savedAt,
    state: design.state,
  };
  const json = JSON.stringify(payload, null, 2);
  const blob = new Blob([json], { type: "application/json" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  const safe = (design.name || "design").replace(/[^a-z0-9-_]+/gi, "-").toLowerCase();
  a.href = url;
  a.download = `lyrics-poster-${safe}.json`;
  a.click();
  setTimeout(() => URL.revokeObjectURL(url), 1000);
}

function importFromFile(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      try {
        const parsed = JSON.parse(reader.result);
        if (parsed && parsed.type === "lyrics-poster-design" && parsed.state) {
          resolve({ name: parsed.name || "Imported", state: parsed.state });
        } else {
          reject(new Error("File is not a Lyrics Poster design."));
        }
      } catch (e) {
        reject(new Error("Couldn't read JSON: " + e.message));
      }
    };
    reader.onerror = () => reject(reader.error || new Error("Read failed"));
    reader.readAsText(file);
  });
}

// --- Dropdown UI ------------------------------------------------------------

function DesignsMenu({ currentState, currentDesignId, currentDesignName, onLoad, onCurrentDesignChange }) {
  const [open, setOpen] = useState(false);
  const [list, setList] = useState(() => loadAll());
  const [renamingId, setRenamingId] = useState(null);
  const [renameValue, setRenameValue] = useState("");
  const [toast, setToast] = useState(null);
  const fileInputRef = useRef(null);
  const wrapRef = useRef(null);

  useEffect(() => {
    if (!open) return;
    setList(loadAll()); // refresh on open
    const onDoc = (e) => {
      if (!wrapRef.current) return;
      if (!wrapRef.current.contains(e.target)) setOpen(false);
    };
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, [open]);

  const flashToast = (msg) => {
    setToast(msg);
    setTimeout(() => setToast(null), 1600);
  };

  const handleSaveNew = () => {
    const name = window.prompt("Name this design:", currentDesignName || "Untitled");
    if (!name) return;
    const item = createDesign(name.trim(), currentState);
    setList(loadAll());
    onCurrentDesignChange({ id: item.id, name: item.name });
    flashToast("Saved");
  };

  const handleOverwrite = () => {
    if (!currentDesignId) return handleSaveNew();
    updateDesign(currentDesignId, { state: currentState });
    setList(loadAll());
    flashToast("Updated");
  };

  const handleLoad = (item) => {
    onLoad(item.state);
    onCurrentDesignChange({ id: item.id, name: item.name });
    setOpen(false);
    flashToast("Loaded " + item.name);
  };

  const handleDelete = (item) => {
    if (!window.confirm(`Delete "${item.name}"?`)) return;
    deleteDesign(item.id);
    setList(loadAll());
    if (currentDesignId === item.id) onCurrentDesignChange({ id: null, name: null });
  };

  const beginRename = (item) => {
    setRenamingId(item.id);
    setRenameValue(item.name);
  };
  const commitRename = () => {
    if (!renamingId) return;
    const name = renameValue.trim() || "Untitled";
    updateDesign(renamingId, { name });
    if (currentDesignId === renamingId) onCurrentDesignChange({ id: renamingId, name });
    setRenamingId(null);
    setRenameValue("");
    setList(loadAll());
  };

  const handleExport = (item) => exportToFile(item);

  const handleExportCurrent = () => {
    exportToFile({
      id: currentDesignId || uid(),
      name: currentDesignName || "Untitled",
      savedAt: Date.now(),
      state: currentState,
    });
  };

  const handleImportClick = () => fileInputRef.current && fileInputRef.current.click();
  const handleImportFile = async (e) => {
    const file = e.target.files && e.target.files[0];
    e.target.value = ""; // allow re-selecting same file
    if (!file) return;
    try {
      const { name, state } = await importFromFile(file);
      const item = createDesign(name, state);
      setList(loadAll());
      onLoad(state);
      onCurrentDesignChange({ id: item.id, name: item.name });
      setOpen(true);
      flashToast("Imported " + name);
    } catch (err) {
      alert("Import failed: " + err.message);
    }
  };

  return (
    <div ref={wrapRef} style={{ position: "relative", display: "inline-flex", gap: 8 }}>
      <button
        type="button"
        onClick={handleOverwrite}
        title={currentDesignId ? `Update "${currentDesignName}"` : "Save current design"}
        style={toolbarBtnStyle}
      >
        {currentDesignId ? "Update" : "Save"}
      </button>
      <button
        type="button"
        onClick={() => setOpen((o) => !o)}
        style={{ ...toolbarBtnStyle, display: "inline-flex", alignItems: "center", gap: 6 }}
      >
        Designs
        <span style={{ fontSize: 8, opacity: 0.55 }}>▾</span>
        {list.length > 0 && (
          <span style={{ fontSize: 10, color: "#888", fontFamily: '"JetBrains Mono", monospace', marginLeft: 2 }}>
            {list.length}
          </span>
        )}
      </button>

      {toast && (
        <div style={{ position: "absolute", top: 38, right: 0, padding: "6px 10px", background: "#1a1a1a", color: "white", fontSize: 11, borderRadius: 4, zIndex: 50, whiteSpace: "nowrap" }}>
          {toast}
        </div>
      )}

      <input
        ref={fileInputRef}
        type="file"
        accept="application/json,.json"
        onChange={handleImportFile}
        style={{ display: "none" }}
      />

      {open && (
        <div
          style={{
            position: "absolute",
            top: 38,
            right: 0,
            width: 320,
            maxHeight: 480,
            background: "white",
            border: "1px solid #d8d8d6",
            borderRadius: 6,
            boxShadow: "0 12px 30px rgba(0,0,0,.16), 0 4px 10px rgba(0,0,0,.08)",
            zIndex: 40,
            display: "flex",
            flexDirection: "column",
            overflow: "hidden",
          }}
        >
          {/* Header actions */}
          <div style={{ padding: "10px 12px", borderBottom: "1px solid #ececea", display: "flex", flexDirection: "column", gap: 6 }}>
            <div style={{ fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: "#888" }}>
              Saved designs
            </div>
            <div style={{ display: "flex", gap: 6 }}>
              <button type="button" onClick={handleSaveNew} style={menuActionBtn}>Save as new…</button>
              <button type="button" onClick={handleImportClick} style={menuActionBtn}>Import…</button>
              <button type="button" onClick={handleExportCurrent} style={menuActionBtn}>Export</button>
            </div>
          </div>

          {/* List */}
          <div style={{ flex: 1, overflow: "auto" }}>
            {list.length === 0 && (
              <div style={{ padding: "24px 14px", textAlign: "center", fontSize: 12, color: "#999", lineHeight: 1.5 }}>
                No saved designs yet.
                <br />
                Tap <b style={{ color: "#555" }}>Save as new…</b> to keep this one.
              </div>
            )}
            {list.map((item) => {
              const isCurrent = item.id === currentDesignId;
              const isRenaming = item.id === renamingId;
              return (
                <div
                  key={item.id}
                  style={{
                    padding: "10px 12px",
                    borderBottom: "1px solid #f3f3f1",
                    background: isCurrent ? "#fafaf7" : "white",
                    display: "flex",
                    flexDirection: "column",
                    gap: 4,
                  }}
                >
                  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8 }}>
                    {isRenaming ? (
                      <input
                        autoFocus
                        value={renameValue}
                        onChange={(e) => setRenameValue(e.target.value)}
                        onBlur={commitRename}
                        onKeyDown={(e) => {
                          if (e.key === "Enter") commitRename();
                          if (e.key === "Escape") { setRenamingId(null); setRenameValue(""); }
                        }}
                        style={{ flex: 1, padding: "4px 6px", fontSize: 12, fontFamily: "inherit", border: "1px solid #d8d8d6", borderRadius: 3 }}
                      />
                    ) : (
                      <button
                        type="button"
                        onClick={() => handleLoad(item)}
                        style={{
                          flex: 1,
                          textAlign: "left",
                          background: "transparent",
                          border: "none",
                          padding: 0,
                          cursor: "pointer",
                          fontFamily: "inherit",
                          fontSize: 13,
                          fontWeight: isCurrent ? 600 : 500,
                          color: "#1a1a1a",
                          minWidth: 0,
                          overflow: "hidden",
                          textOverflow: "ellipsis",
                          whiteSpace: "nowrap",
                        }}
                        title={`Load "${item.name}"`}
                      >
                        {item.name}
                        {isCurrent && (
                          <span style={{ marginLeft: 6, fontSize: 9, color: "#999", fontFamily: '"JetBrains Mono", monospace', fontWeight: 500 }}>
                            current
                          </span>
                        )}
                      </button>
                    )}
                    <span style={{ fontSize: 10, color: "#aaa", fontFamily: '"JetBrains Mono", monospace', flex: "0 0 auto" }}>
                      {formatTimestamp(item.savedAt)}
                    </span>
                  </div>
                  <div style={{ display: "flex", gap: 4, marginTop: 2 }}>
                    <button type="button" style={rowBtn} onClick={() => handleLoad(item)}>Load</button>
                    <button type="button" style={rowBtn} onClick={() => beginRename(item)}>Rename</button>
                    <button type="button" style={rowBtn} onClick={() => handleExport(item)}>Export</button>
                    <button type="button" style={{ ...rowBtn, marginLeft: "auto", color: "#a14242" }} onClick={() => handleDelete(item)}>Delete</button>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
}

const toolbarBtnStyle = {
  padding: "7px 14px",
  fontSize: 12,
  fontFamily: "inherit",
  fontWeight: 500,
  border: "1px solid #d8d8d6",
  background: "white",
  color: "#1a1a1a",
  borderRadius: 4,
  cursor: "pointer",
  whiteSpace: "nowrap",
};

const menuActionBtn = {
  flex: 1,
  padding: "6px 8px",
  fontSize: 11,
  fontFamily: "inherit",
  fontWeight: 500,
  border: "1px solid #d8d8d6",
  background: "white",
  color: "#1a1a1a",
  borderRadius: 4,
  cursor: "pointer",
};

const rowBtn = {
  padding: "3px 7px",
  fontSize: 10,
  fontFamily: "inherit",
  border: "1px solid #e5e5e3",
  background: "white",
  color: "#555",
  borderRadius: 3,
  cursor: "pointer",
};

window.DesignsMenu = DesignsMenu;
window.loadAutosave = loadAutosave;
window.writeAutosave = writeAutosave;
