import { useEffect, useMemo, useState } from "react";

import { apiRequest } from "../../api/client";
import type { Beladungsvorlage, Material, Objektposition } from "../../api/types";
import { gruppiereNachFach, OHNE_FACH } from "../../utils/fachGruppierung";
import { GeraeteInstanzenListe } from "./GeraeteInstanzenListe";

interface Props {
  objektId: number;
  vorlageId: number | null;
  materialien: Material[];
  onFehler: (text: string) => void;
}

interface ZeilenFormular {
  sollmengeOverride: string;
  ablaufdatum: string;
  chargennummer: string;
  pruefintervallMonate: string;
}

function leeresFormular(p: Objektposition): ZeilenFormular {
  return {
    sollmengeOverride: p.sollmenge_override ?? "",
    ablaufdatum: p.ablaufdatum ?? "",
    chargennummer: p.chargennummer ?? "",
    pruefintervallMonate: p.pruefintervall_monate?.toString() ?? "",
  };
}

/**
 * Bestückung eines Objekts pflegen (Prompt 10): Sollmenge-Override je Position
 * (Abweichung vom Vorlagen-Soll), Position entfernen/reaktivieren, zusätzliches
 * Material hinzufügen das nicht in der Vorlage steht - plus Ablaufdatum/Charge/
 * Prüfintervall/Geräte-Instanzen für die entsprechenden Materialtypen. Backend-
 * Endpunkte existierten schon (PATCH/POST .../positionen), waren im Frontend
 * bisher nur für ablauf_charge/geraet_sn und nicht für Sollmenge/Status/Neuanlage
 * angebunden.
 *
 * Nutzer-Vorgabe: Fach-Sidebar links, damit die Bestückung übersichtlich bleibt
 * UND damit auch Dritte (Vertretung, wenn die Kontrollperson nicht da ist)
 * auf einen Blick sehen, wo welches Material im Rucksack hingehört - gleiche
 * Fach-Zuordnung wie in der Kontroll-Erfassung (Vorlagenposition.fach).
 */
export function ObjektPositionenPanel({ objektId, vorlageId, materialien, onFehler }: Props) {
  const [positionen, setPositionen] = useState<Objektposition[]>([]);
  const [vorlage, setVorlage] = useState<Beladungsvorlage | null>(null);
  const [formulare, setFormulare] = useState<Record<string, ZeilenFormular>>({});
  const [speichertId, setSpeichertId] = useState<string | null>(null);
  const [neuesMaterialId, setNeuesMaterialId] = useState<number | "">("");
  const [neueSollmenge, setNeueSollmenge] = useState("");
  const [wirdHinzugefuegt, setWirdHinzugefuegt] = useState(false);
  const [aktivesFach, setAktivesFach] = useState<string | null>(null);

  async function laden() {
    try {
      const [liste, vorlageDaten] = await Promise.all([
        apiRequest<Objektposition[]>(`/objekte/${objektId}/positionen`),
        vorlageId ? apiRequest<Beladungsvorlage>(`/vorlagen/${vorlageId}`) : Promise.resolve(null),
      ]);
      setPositionen(liste);
      setVorlage(vorlageDaten);
      setFormulare(Object.fromEntries(liste.map((p) => [p.id, leeresFormular(p)])));
    } catch {
      onFehler("Positionen konnten nicht geladen werden.");
    }
  }

  useEffect(() => {
    laden();
    setAktivesFach(null);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [objektId, vorlageId]);

  const fachByMaterialId = useMemo(() => {
    const map = new Map<number, string | null>();
    for (const vp of vorlage?.positionen ?? []) {
      map.set(vp.material_id, vp.fach);
    }
    return map;
  }, [vorlage]);

  const fachGruppen = useMemo(
    () => gruppiereNachFach(positionen, (p) => fachByMaterialId.get(p.material_id) ?? null),
    [positionen, fachByMaterialId]
  );
  const sichtbarePositionen = aktivesFach
    ? fachGruppen.find(([fach]) => fach === aktivesFach)?.[1] ?? []
    : positionen;

  function materialName(materialId: number) {
    return materialien.find((m) => m.id === materialId)?.name ?? `Material ${materialId}`;
  }

  function materialtyp(materialId: number) {
    return materialien.find((m) => m.id === materialId)?.materialtyp;
  }

  async function speichern(position: Objektposition) {
    const formular = formulare[position.id];
    setSpeichertId(position.id);
    try {
      const aktualisiert = await apiRequest<Objektposition>(`/objekte/${objektId}/positionen/${position.id}`, {
        method: "PATCH",
        body: {
          sollmenge_override: formular.sollmengeOverride === "" ? null : Number(formular.sollmengeOverride),
          ablaufdatum: formular.ablaufdatum || null,
          chargennummer: formular.chargennummer || null,
          pruefintervall_monate: formular.pruefintervallMonate ? Number(formular.pruefintervallMonate) : null,
        },
      });
      setPositionen((bisherige) => bisherige.map((p) => (p.id === position.id ? aktualisiert : p)));
    } catch {
      onFehler("Position konnte nicht gespeichert werden.");
    } finally {
      setSpeichertId(null);
    }
  }

  async function statusUmschalten(position: Objektposition) {
    const neuerStatus = position.ist_status === "aktiv" ? "entfernt" : "aktiv";
    try {
      const aktualisiert = await apiRequest<Objektposition>(`/objekte/${objektId}/positionen/${position.id}`, {
        method: "PATCH",
        body: { ist_status: neuerStatus },
      });
      setPositionen((bisherige) => bisherige.map((p) => (p.id === position.id ? aktualisiert : p)));
    } catch {
      onFehler("Status konnte nicht geändert werden.");
    }
  }

  async function materialHinzufuegen() {
    if (neuesMaterialId === "" || !neueSollmenge) return;
    setWirdHinzugefuegt(true);
    try {
      await apiRequest(`/objekte/${objektId}/positionen`, {
        method: "POST",
        body: { material_id: neuesMaterialId, sollmenge_override: Number(neueSollmenge) },
      });
      setNeuesMaterialId("");
      setNeueSollmenge("");
      await laden();
    } catch {
      onFehler("Material konnte nicht hinzugefügt werden (evtl. schon vorhanden).");
    } finally {
      setWirdHinzugefuegt(false);
    }
  }

  const vorhandeneMaterialIds = new Set(positionen.map((p) => p.material_id));
  const verfuegbareMaterialien = materialien.filter((m) => !vorhandeneMaterialIds.has(m.id));

  return (
    <div>
      <div className="row" style={{ flexWrap: "wrap", marginBottom: "1rem" }}>
        <select
          className="input"
          value={neuesMaterialId}
          onChange={(e) => setNeuesMaterialId(Number(e.target.value) || "")}
        >
          <option value="">Material hinzufügen…</option>
          {verfuegbareMaterialien.map((m) => (
            <option key={m.id} value={m.id}>
              {m.name}
            </option>
          ))}
        </select>
        <input
          type="number"
          min="0"
          className="input"
          style={{ maxWidth: "8rem" }}
          placeholder="Sollmenge"
          value={neueSollmenge}
          onChange={(e) => setNeueSollmenge(e.target.value)}
        />
        <button
          className="btn btn-secondary"
          onClick={materialHinzufuegen}
          disabled={neuesMaterialId === "" || !neueSollmenge || wirdHinzugefuegt}
        >
          Hinzufügen
        </button>
      </div>

      {positionen.length === 0 && <p className="text-muted">Keine Positionen in diesem Objekt.</p>}

      {positionen.length > 0 && (
        <div className="row" style={{ alignItems: "flex-start", gap: "1.25rem" }}>
          <nav
            className="card"
            style={{ minWidth: "11rem", flexShrink: 0, padding: "0.5rem", position: "sticky", top: "0.5rem" }}
          >
            <button
              className={aktivesFach === null ? "btn btn-primary btn-block" : "btn btn-secondary btn-block"}
              style={{ marginBottom: "0.3rem" }}
              onClick={() => setAktivesFach(null)}
            >
              Alle ({positionen.length})
            </button>
            {fachGruppen.map(([fach, gruppenPositionen]) => (
              <button
                key={fach}
                className={aktivesFach === fach ? "btn btn-primary btn-block" : "btn btn-secondary btn-block"}
                style={{ marginBottom: "0.3rem" }}
                onClick={() => setAktivesFach(fach)}
              >
                {fach} ({gruppenPositionen.length})
              </button>
            ))}
          </nav>

          <div style={{ flex: 1, minWidth: 0 }}>
      <ul className="card-list">
        {sichtbarePositionen.map((p) => {
          const typ = materialtyp(p.material_id);
          const formular = formulare[p.id] ?? leeresFormular(p);
          const entfernt = p.ist_status === "entfernt";
          return (
            <li key={p.id} className="card" style={entfernt ? { opacity: 0.6 } : undefined}>
              <div className="card-title-row">
                <strong>{materialName(p.material_id)}</strong>
                <span className="row" style={{ gap: "0.4rem" }}>
                  <span className="badge badge-neutral">{fachByMaterialId.get(p.material_id) ?? OHNE_FACH}</span>
                  <span className="badge badge-neutral">{typ}</span>
                  {entfernt && <span className="badge badge-danger">entfernt</span>}
                </span>
              </div>
              <div className="card-subtitle">Soll (Vorlage/aktuell wirksam): {p.sollmenge_effektiv}</div>
              <div className="row" style={{ marginTop: "0.6rem", flexWrap: "wrap" }}>
                <div className="field" style={{ maxWidth: "10rem" }}>
                  <label>Sollmenge-Override</label>
                  <input
                    type="number"
                    min="0"
                    className="input"
                    placeholder="wie Vorlage"
                    value={formular.sollmengeOverride}
                    onChange={(e) =>
                      setFormulare((f) => ({ ...f, [p.id]: { ...formular, sollmengeOverride: e.target.value } }))
                    }
                  />
                </div>
                {typ === "ablauf_charge" && (
                  <>
                    <input
                      type="date"
                      className="input"
                      value={formular.ablaufdatum}
                      onChange={(e) =>
                        setFormulare((f) => ({ ...f, [p.id]: { ...formular, ablaufdatum: e.target.value } }))
                      }
                    />
                    <input
                      className="input"
                      placeholder="Chargennummer"
                      value={formular.chargennummer}
                      onChange={(e) =>
                        setFormulare((f) => ({ ...f, [p.id]: { ...formular, chargennummer: e.target.value } }))
                      }
                    />
                  </>
                )}
                {typ === "geraet_sn" && (
                  <input
                    type="number"
                    min="0"
                    className="input"
                    placeholder="Prüfintervall (Monate)"
                    value={formular.pruefintervallMonate}
                    onChange={(e) =>
                      setFormulare((f) => ({
                        ...f,
                        [p.id]: { ...formular, pruefintervallMonate: e.target.value },
                      }))
                    }
                  />
                )}
                <button className="btn btn-primary" onClick={() => speichern(p)} disabled={speichertId === p.id}>
                  Speichern
                </button>
                <button className="btn btn-secondary" onClick={() => statusUmschalten(p)}>
                  {entfernt ? "Reaktivieren" : "Entfernen"}
                </button>
              </div>
              {typ === "geraet_sn" && (
                <GeraeteInstanzenListe
                  objektpositionId={p.id}
                  pruefintervallMonate={p.pruefintervall_monate}
                  onFehler={onFehler}
                />
              )}
            </li>
          );
        })}
      </ul>
          </div>
        </div>
      )}
    </div>
  );
}
