import { useEffect, useMemo, useState } from "react";
import { Link } from "react-router-dom";
import { api } from "../api";
import { useAuth } from "../auth";
import Icon from "../components/Icon";
import DataTable from "../components/DataTable";
import SplitLotDialog from "../components/SplitLotDialog";
import { ProduktThumb } from "../components/ProduktBild";
import { useSettings } from "../settings";
import { locationOptions, locationPathById } from "../locationPath";
import { expiryRowClass, fmt, gebinde, unitShort } from "../units";

// Artikeleinheit einer Charge (Gebinde, sonst Produkteinheit).
const artFactor = (l) => (l.package_size && l.package_size > 0 ? l.package_size : (l.unit_factor || 1));
function mengeText(l) {
  const menge = l.quantity / artFactor(l);
  const label = l.package_size && l.package_size > 0
    ? gebinde(menge, l.package_label)
    : (l.unit_name || unitShort(l.base_unit));
  return `${fmt(menge)} ${label}`;
}

/**
 * Übergreifende Chargenliste (wie die Einzelstückliste, aber für Chargen). Zeigt
 * je Charge Artikel, Menge, MHD und Lagerort; der Lagerort ist je Zeile direkt
 * änderbar, und alle Chargen ohne Ort lassen sich in einem Klick zuordnen.
 */
export default function Charges() {
  const { isAdmin } = useAuth();
  const { formatBestBefore } = useSettings();
  const [lots, setLots] = useState([]);
  const [locations, setLocations] = useState([]);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(true);
  const [bulkLoc, setBulkLoc] = useState("");
  const [selected, setSelected] = useState(() => new Set());
  const [visible, setVisible] = useState([]);   // aktuell gefiltert sichtbare Chargen
  const [splitting, setSplitting] = useState(null);  // Charge, die gerade aufgeteilt wird
  const [warnDays, setWarnDays] = useState(7);       // Warnfrist für „bald ablaufend"

  async function load() {
    setLoading(true);
    try {
      const [ls, locs] = await Promise.all([api.listAllLots(), api.listLocations()]);
      setLots(ls);
      setLocations(locs);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  }
  useEffect(() => { load(); }, []);
  // Warnfrist (Tage) für die gelbe „bald ablaufend"-Markierung – wie auf der Artikelseite.
  useEffect(() => {
    api.listSettings()
      .then((s) => { const r = s.find((x) => x.key === "expiry_warning_days"); if (r) setWarnDays(parseInt(r.value, 10) || 7); })
      .catch(() => {});
  }, []);

  const ohneOrt = useMemo(() => lots.filter((l) => !l.location_id), [lots]);

  function toggle(id) {
    setSelected((alt) => {
      const neu = new Set(alt);
      if (neu.has(id)) neu.delete(id); else neu.add(id);
      return neu;
    });
  }
  // Menge von IDs zur Auswahl hinzufügen (für „alle sichtbaren/ohne Ort").
  function selectAll(ids) { setSelected(new Set(ids)); }
  function clearSelection() { setSelected(new Set()); }

  async function setLocation(lotId, locId) {
    setError(null);
    try {
      await api.updateLot(lotId, { location_id: locId || null });
      setLots((ls) => ls.map((l) => (l.id === lotId ? { ...l, location_id: locId || null } : l)));
    } catch (err) {
      setError(err.message);
    }
  }

  // Lagerort für die aktuell ausgewählten Chargen setzen (leer = Ort entfernen).
  async function applyToSelection() {
    if (selected.size === 0) return;
    setError(null);
    try {
      await api.bulkLotLocation([...selected], bulkLoc);
      setBulkLoc("");
      clearSelection();
      await load();
    } catch (err) {
      setError(err.message);
    }
  }

  const columns = [
    { key: "select", header: "", label: "Auswahl", fixed: true, width: 44,
      render: (l) => (
        <input type="checkbox" style={{ width: "auto", margin: 0, cursor: "pointer" }}
          checked={selected.has(l.id)} onChange={() => toggle(l.id)}
          aria-label={`${l.product_name} auswählen`} />
      ) },
    { key: "thumb", header: "", label: "Bild", fixed: true, width: 56,
      render: (l) => <ProduktThumb productId={l.product_id} alt={l.product_name} /> },
    { key: "product", header: "Artikel", grow: true, min: 180,
      filterText: (l) => `${l.product_name} ${l.product_brand || ""}`, sortValue: (l) => l.product_name,
      render: (l) => (
        <span className="cell-row">
          <span className="strong">{l.product_name}</span>
          {l.product_brand && <span className="muted small">{l.product_brand}</span>}
        </span>
      ) },
    { key: "art", header: "Art", width: 130,
      filterText: (l) => (l.tracking === "object" ? "Gegenstand" : "Lebensmittel"),
      filterValues: (l) => [l.tracking === "object" ? "Gegenstand" : "Lebensmittel"],
      render: (l) => (
        <span className="badge nowrap">{l.tracking === "object" ? "Gegenstand" : "Lebensmittel"}</span>
      ) },
    { key: "menge", header: "Menge", width: 150, align: "num",
      sortValue: (l) => l.quantity / artFactor(l), render: mengeText },
    { key: "mhd", header: "MHD", width: 150,
      filterText: (l) => (l.best_before ? formatBestBefore(l.best_before, l.best_before_precision) : ""),
      sortValue: (l) => l.best_before || "9999-99-99",
      render: (l) => (l.best_before ? formatBestBefore(l.best_before, l.best_before_precision) : <span className="muted">–</span>) },
    { key: "location", header: "Lagerort", width: 240,
      filterText: (l) => (l.location_id ? (locationPathById(l.location_id, locations) || "") : "(ohne)"),
      filterValues: (l) => [l.location_id ? (locationPathById(l.location_id, locations) || "?") : "(ohne)"],
      render: (l) => (isAdmin ? (
        <select value={l.location_id || ""} style={{ marginTop: 0, minWidth: 150 }}
          onChange={(e) => setLocation(l.id, e.target.value)}>
          <option value="">– ohne –</option>
          {locationOptions(locations).map((o) => <option key={o.id} value={o.id}>{o.label}</option>)}
        </select>
      ) : (
        l.location_id ? (locationPathById(l.location_id, locations) || "?") : <span className="muted">– ohne –</span>
      )) },
    { key: "created", header: "Eingelagert", width: 130,
      sortValue: (l) => new Date(l.created_at).getTime(),
      render: (l) => <span className="muted">{new Date(l.created_at).toLocaleDateString("de-DE")}</span> },
    { key: "split", header: "Aufteilen", label: "Aufteilen", width: 118, align: "num",
      render: (l) => (isAdmin ? (
        <button type="button" className="btn sm ghost" title="Charge aufteilen und Teil umlagern"
          onClick={() => setSplitting(l)}><Icon name="split" size={15} />Aufteilen</button>
      ) : null) },
    { key: "details", header: "Artikel", label: "Artikel", width: 90, align: "num",
      render: (l) => <Link to={`/products/${l.product_id}`}>Artikel</Link> },
  ];

  return (
    <div>
      <div className="page-head">
        <div>
          <h1>Chargen</h1>
          <div className="sub">
            {loading ? "Wird geladen…" : `${lots.length} Chargen · ${ohneOrt.length} ohne Lagerort`}
          </div>
        </div>
      </div>

      {error && <div className="alert error"><Icon name="alert" size={16} />{error}</div>}

      {isAdmin && (
        <div className="card" style={{ marginBottom: "var(--sp-3)" }}>
          <div className="card-head"><Icon name="location" /><h2>Lagerort für ausgewählte Chargen setzen</h2></div>
          <p className="muted small mt-0">
            {selected.size > 0
              ? `${selected.size} Charge(n) ausgewählt – diese bekommen den gewählten Lagerort (leer = Ort entfernen).`
              : "Chargen in der Tabelle anhaken, dann hier den Lagerort setzen. Oder unten schnell alle sichtbaren / alle ohne Ort auswählen."}
          </p>
          <div className="field-inline" style={{ flexWrap: "wrap" }}>
            <select value={bulkLoc} onChange={(e) => setBulkLoc(e.target.value)} style={{ maxWidth: 360 }}
              disabled={selected.size === 0}>
              <option value="">– ohne Lagerort –</option>
              {locationOptions(locations).map((o) => <option key={o.id} value={o.id}>{o.label}</option>)}
            </select>
            <button className="btn primary" disabled={selected.size === 0} onClick={applyToSelection}>
              <Icon name="check" size={16} />Auf {selected.size} Auswahl anwenden
            </button>
          </div>
          <div className="field-inline" style={{ flexWrap: "wrap", marginTop: "var(--sp-2)", marginBottom: 0 }}>
            <button type="button" className="btn sm ghost" onClick={() => selectAll(visible.map((l) => l.id))}
              disabled={visible.length === 0}>
              Alle {visible.length} sichtbaren auswählen
            </button>
            <button type="button" className="btn sm ghost" onClick={() => selectAll(ohneOrt.map((l) => l.id))}
              disabled={ohneOrt.length === 0}>
              Alle {ohneOrt.length} ohne Lagerort auswählen
            </button>
            {selected.size > 0 && (
              <button type="button" className="btn sm ghost" onClick={clearSelection}>Auswahl aufheben</button>
            )}
          </div>
        </div>
      )}

      <div className="card">
        <DataTable id="charges" columns={columns} rows={lots} loading={loading}
          onVisibleRows={setVisible}
          rowClassName={(l) => [expiryRowClass(l.best_before, warnDays), selected.has(l.id) ? "row-active" : ""].filter(Boolean).join(" ")}
          onRowClick={(l, e) => {
            // Klicks auf Bedienelemente (Checkbox, Lagerort-Dropdown, Link) nicht
            // als Zeilenauswahl werten – überall sonst die Zeile umschalten.
            if (!e.target.closest("input, select, a, button, label")) toggle(l.id);
          }}
          getRowKey={(l) => l.id} empty="Keine Chargen im Bestand." />
      </div>

      {splitting && (
        <SplitLotDialog
          lot={splitting}
          factor={artFactor(splitting)}
          labelFor={(q) => (splitting.package_size && splitting.package_size > 0
            ? gebinde(q, splitting.package_label)
            : (splitting.unit_name || unitShort(splitting.base_unit)))}
          locations={locations}
          onClose={() => setSplitting(null)}
          onDone={load}
          onError={setError}
        />
      )}
    </div>
  );
}
