import { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { api } from "../api";
import { useConfirm } from "../confirm";
import Icon from "../components/Icon";
import CategorySelect from "../components/CategorySelect";
import { QrImg, printQrLabels } from "../qr";

export default function Locations() {
  const confirm = useConfirm();
  const [locations, setLocations] = useState([]);
  const [name, setName] = useState("");
  const [parentId, setParentId] = useState("");
  const [error, setError] = useState(null);
  // Inline-Bearbeiten (Umbenennen + Umhängen) eines vorhandenen Orts.
  const [editId, setEditId] = useState(null);
  const [editName, setEditName] = useState("");
  const [editParent, setEditParent] = useState(null);

  async function load() {
    try {
      setLocations(await api.listLocations());
    } catch (err) {
      setError(err.message);
    }
  }

  useEffect(() => { load(); }, []);

  async function add(e) {
    e.preventDefault();
    setError(null);
    try {
      await api.createLocation({ name, parent_id: parentId === "" ? null : parentId });
      setName("");
      // Übergeordneten Ort absichtlich stehen lassen – beim Anlegen vieler Orte
      // unter demselben Elternteil spart das jedes Mal die Neuauswahl.
      load();
    } catch (err) {
      setError(err.message);
    }
  }

  function startEdit(l) {
    setEditId(l.id);
    setEditName(l.name);
    setEditParent(l.parent_id ?? null);
    setError(null);
  }

  function cancelEdit() {
    setEditId(null);
  }

  async function saveEdit() {
    setError(null);
    try {
      await api.updateLocation(editId, {
        name: editName.trim(),
        parent_id: editParent == null ? null : editParent,
      });
      setEditId(null);
      load();
    } catch (err) {
      setError(err.message);
    }
  }

  // Eigene Unterorte (rekursiv) – als Ziel beim Umhängen ausgeschlossen.
  function descendantIds(id) {
    const result = new Set();
    const stack = [id];
    while (stack.length) {
      const cur = stack.pop();
      for (const c of locations.filter((l) => l.parent_id === cur)) {
        if (!result.has(c.id)) { result.add(c.id); stack.push(c.id); }
      }
    }
    return result;
  }

  async function remove(id) {
    const ok = await confirm({
      title: "Lagerort löschen?",
      message: "Untergeordnete Orte rücken eine Ebene nach oben.",
      confirmLabel: "Löschen",
      danger: true,
    });
    if (!ok) return;
    try {
      await api.deleteLocation(id);
      load();
    } catch (err) {
      setError(err.message);
    }
  }

  const nameById = Object.fromEntries(locations.map((l) => [l.id, l.name]));
  const ids = new Set(locations.map((l) => l.id));
  const isRoot = (l) => !l.parent_id || !ids.has(l.parent_id);

  // Rekursiv über beliebig viele Ebenen (Schrank -> Fach -> Kiste -> …).
  const ordered = [];
  const seen = new Set();
  function walk(node, depth) {
    if (seen.has(node.id)) return; // Schutz vor Zyklen
    seen.add(node.id);
    ordered.push({ ...node, depth });
    for (const c of locations.filter((l) => l.parent_id === node.id)) walk(c, depth + 1);
  }
  for (const r of locations.filter(isRoot)) walk(r, 0);

  // Mögliche neue Elternorte beim Bearbeiten: alle außer dem Ort selbst und
  // seinen Unterorten (sonst entstünde ein Ring).
  const editDesc = editId != null ? descendantIds(editId) : new Set();
  const editParentNodes = ordered.filter((o) => o.id !== editId && !editDesc.has(o.id));

  return (
    <div>
      <div className="page-head">
        <div>
          <h1>Lagerorte</h1>
          <div className="sub">Orte lassen sich verschachteln (z.B. Keller → Regal 2 → Fach A)</div>
        </div>
        {locations.length > 0 && (
          <button className="btn" onClick={() => printQrLabels("Lagerort-Etiketten",
            locations.map((l) => ({ text: `${window.location.origin}/l/${l.id}`, line1: l.name, line2: "Lagerort" })))}>
            <Icon name="download" size={16} />QR-Etiketten drucken
          </button>
        )}
      </div>
      {error && <div className="alert error"><Icon name="alert" size={16} />{error}</div>}

      <div className="card form-narrow">
        <form onSubmit={add}>
          <div className="row">
            <label className="grow">
              Name
              <input placeholder="z.B. Speisekammer oder Regal 2" value={name}
                onChange={(e) => setName(e.target.value)} required />
            </label>
            <label className="grow">
              Übergeordneter Lagerort (optional)
              <CategorySelect
                value={parentId === "" ? null : parentId}
                nodes={ordered}
                rootLabel="– keiner (oberste Ebene) –"
                onChange={(id) => setParentId(id == null ? "" : String(id))}
              />
            </label>
          </div>
          <button className="btn primary"><Icon name="plus" size={16} />Hinzufügen</button>
        </form>

        <ul className="simple-list">
          {ordered.map((l) => (
            editId === l.id ? (
              <li key={l.id}>
                <div className="row" style={{ width: "100%", gap: 8, alignItems: "flex-end" }}>
                  <label className="grow" style={{ margin: 0 }}>
                    Name
                    <input value={editName} onChange={(e) => setEditName(e.target.value)} />
                  </label>
                  <label className="grow" style={{ margin: 0 }}>
                    Übergeordnet
                    <CategorySelect
                      value={editParent}
                      nodes={editParentNodes}
                      rootLabel="– keiner (oberste Ebene) –"
                      onChange={(id) => setEditParent(id == null ? null : id)}
                    />
                  </label>
                  <span style={{ display: "flex", gap: 6 }}>
                    <button className="btn primary" onClick={saveEdit} disabled={!editName.trim()}>
                      <Icon name="check" size={16} />Speichern
                    </button>
                    <button type="button" className="btn ghost" onClick={cancelEdit}>Abbrechen</button>
                  </span>
                </div>
              </li>
            ) : (
              <li key={l.id}>
                <span style={{ display: "flex", alignItems: "center", gap: 8, paddingLeft: l.depth * 22 }}>
                  {l.depth > 0 && <span className="muted">↳</span>}
                  <Icon name="location" size={15} className="muted" />
                  {l.name}
                  {l.depth > 0 && l.parent_id && nameById[l.parent_id] && (
                    <span className="badge">in {nameById[l.parent_id]}</span>
                  )}
                </span>
                <span style={{ display: "flex", alignItems: "center", gap: 8 }}>
                  <Link className="btn-icon" to={`/l/${l.id}`} title="Inhalt ansehen">
                    <Icon name="search" size={16} />
                  </Link>
                  <QrImg text={`${window.location.origin}/l/${l.id}`} size={44} />
                  <button className="btn-icon" onClick={() => startEdit(l)} title="Bearbeiten">
                    <Icon name="edit" size={16} />
                  </button>
                  <button className="btn-icon danger" onClick={() => remove(l.id)} title="Löschen">
                    <Icon name="trash" size={16} />
                  </button>
                </span>
              </li>
            )
          ))}
          {locations.length === 0 && <li className="empty">Noch keine Lagerorte.</li>}
        </ul>
      </div>
    </div>
  );
}
