import { Fragment, useEffect, useState } from "react";
import QRCode from "qrcode";
import { api, authorizedObjectUrl } from "../api";
import { useConfirm } from "../confirm";
import { useToast } from "../toast";
import Icon from "./Icon";
import { REASONS } from "./ObjektBestand";

const reasonLabel = (v) => REASONS.find((r) => r.value === v)?.label || v;

/** Kleines QR-Bild für einen Wert (asynchron erzeugt). */
function QrImg({ text, size = 60 }) {
  const [url, setUrl] = useState(null);
  useEffect(() => {
    let ok = true;
    QRCode.toDataURL(text, { margin: 1, width: size * 2 })
      .then((u) => { if (ok) setUrl(u); })
      .catch(() => {});
    return () => { ok = false; };
  }, [text, size]);
  return url
    ? <img src={url} width={size} height={size} alt="QR" style={{ display: "block" }} />
    : <span style={{ display: "inline-block", width: size, height: size }} />;
}

const EMPTY_ADD = {
  count: 1, location_id: "", shop_id: "", acquired_on: "", warranty_until: "", note: "",
};

/**
 * Einzelstücke eines Gegenstands: jedes physische Stück mit eigener UID/QR und
 * eigenen Angaben (Lagerort, gekauft am, Garantie, gekauft bei, Notiz).
 */
export default function Einzelstuecke({ product, locations, shops, isAdmin, onChanged, onError }) {
  const confirm = useConfirm();
  const toast = useToast();
  const [items, setItems] = useState([]);
  const [addForm, setAddForm] = useState(EMPTY_ADD);
  const [remove, setRemove] = useState(null); // { item, reason, note } | null
  const [showAdd, setShowAdd] = useState(false); // Anlege-Maske ein-/ausklappen
  const [suggestion, setSuggestion] = useState(null); // { itemId, date } aus PDF-Analyse
  const origin = window.location.origin;

  async function load() {
    try {
      setItems(await api.listItems(product.id));
    } catch (err) { onError(err.message); }
  }
  useEffect(() => { load(); /* eslint-disable-next-line */ }, [product.id]);

  async function nachAktion() {
    await load();
    if (onChanged) await onChanged();
  }

  async function add(e) {
    e.preventDefault();
    try {
      await api.createItems(product.id, {
        count: Number(addForm.count) || 1,
        location_id: addForm.location_id === "" ? null : Number(addForm.location_id),
        shop_id: addForm.shop_id === "" ? null : Number(addForm.shop_id),
        acquired_on: addForm.acquired_on || null,
        warranty_until: addForm.warranty_until || null,
        note: addForm.note || null,
      });
      setAddForm({ ...EMPTY_ADD, location_id: addForm.location_id, shop_id: addForm.shop_id });
      await nachAktion();
      toast("Einzelstück(e) angelegt.");
    } catch (err) { onError(err.message); }
  }

  // Kaufpreis in Hauptwährungseinheit eingeben, als Rappen/Cent speichern.
  function savePrice(item, value) {
    const roh = value.trim().replace(",", ".");
    const cents = roh === "" ? null : Math.round(parseFloat(roh) * 100);
    if (cents !== null && Number.isNaN(cents)) return;
    if (cents === (item.price_cents ?? null)) return;
    patchItem(item, { price_cents: cents, currency: cents == null ? null : (item.currency || "CHF") });
  }

  async function uploadDoc(item, file) {
    try {
      const res = await api.uploadItemDocument(item.id, file);
      await load();
      if (res && (res.suggested_warranty_until || res.suggested_price_cents != null)) {
        setSuggestion({
          itemId: item.id,
          date: res.suggested_warranty_until || null,
          priceCents: res.suggested_price_cents ?? null,
        });
      }
      toast("Beleg hochgeladen.");
    } catch (err) { onError(err.message); }
  }

  async function deleteDoc(item, doc) {
    try {
      await api.deleteItemDocument(item.id, doc.id);
      await load();
    } catch (err) { onError(err.message); }
  }

  async function viewDoc(item, doc) {
    try {
      const url = await authorizedObjectUrl(`/items/${item.id}/documents/${doc.id}`);
      if (url) window.open(url, "_blank", "noopener");
    } catch (err) { onError(err.message); }
  }

  async function patchItem(item, body) {
    try {
      await api.updateItem(item.id, body);
      await load();
    } catch (err) { onError(err.message); }
  }

  async function doRemove(e) {
    e.preventDefault();
    try {
      await api.removeItem(remove.item.id, { reason: remove.reason, note: remove.note || null });
      setRemove(null);
      await nachAktion();
      toast("Einzelstück entfernt.");
    } catch (err) { onError(err.message); }
  }

  async function loeschen(item) {
    const ok = await confirm({
      title: `Einzelstück ${item.uid} löschen?`,
      message: "Ohne Grund – nur als Korrektur. Für „kaputt/verloren“ bitte „Entfernen“.",
      confirmLabel: "Löschen", danger: true,
    });
    if (!ok) return;
    try {
      await api.deleteItem(item.id);
      await nachAktion();
    } catch (err) { onError(err.message); }
  }

  async function druckeEtiketten() {
    const labels = await Promise.all(items.map(async (it) => {
      const url = await QRCode.toDataURL(`${origin}/i/${it.uid}`, { margin: 1, width: 260 });
      const name = (product.name || "").replace(/[<>&]/g, "");
      return `<div class="label"><img src="${url}"/><div class="uid">${it.uid}</div><div class="name">${name}</div></div>`;
    }));
    const w = window.open("", "_blank");
    if (!w) { onError("Bitte Pop-ups für den Druck erlauben."); return; }
    w.document.write(
      `<!doctype html><html><head><meta charset="utf-8"><title>Etiketten</title><style>
        body{font-family:sans-serif;margin:8mm;display:flex;flex-wrap:wrap;gap:6mm}
        .label{width:34mm;text-align:center;border:1px solid #ccc;border-radius:3mm;padding:3mm;page-break-inside:avoid}
        .label img{width:28mm;height:28mm}
        .uid{font-weight:700;font-size:11pt;letter-spacing:1px;margin-top:1mm}
        .name{font-size:8pt;color:#444}
      </style></head><body>${labels.join("")}
      <script>window.onload=function(){window.print()}</script></body></html>`,
    );
    w.document.close();
  }

  const ortName = (id) => (id == null ? "" : locations.find((l) => l.id === id)?.name || "");

  return (
    <section className="card">
      <div className="card-head">
        <Icon name="tag" /><h2>Einzelstücke</h2>
        <span className="muted small">{items.length} Stück</span>
        {items.length > 0 && (
          <button type="button" className="btn sm" style={{ marginLeft: "auto" }}
            onClick={druckeEtiketten}>
            <Icon name="download" size={15} />Etiketten drucken
          </button>
        )}
      </div>

      <div className="table-wrap">
        <table className="table">
          <thead>
            <tr>
              <th>QR</th><th>UID</th><th>Lagerort</th><th>Gekauft am</th>
              <th>Garantie bis</th><th>Gekauft bei</th><th>Notiz</th><th></th>
            </tr>
          </thead>
          <tbody>
            {items.map((it) => (
              <Fragment key={it.id}>
              <tr>
                <td><QrImg text={`${origin}/i/${it.uid}`} size={56} /></td>
                <td data-label="UID" className="strong nowrap">{it.uid}</td>
                <td data-label="Lagerort">
                  {isAdmin ? (
                    <select value={it.location_id ?? ""} style={{ marginTop: 0, minWidth: 120 }}
                      onChange={(e) => patchItem(it, { location_id: e.target.value === "" ? null : Number(e.target.value) })}>
                      <option value="">– ohne –</option>
                      {locations.map((l) => <option key={l.id} value={l.id}>{l.name}</option>)}
                    </select>
                  ) : <span>{ortName(it.location_id) || "–"}</span>}
                </td>
                <td data-label="Gekauft am">
                  {isAdmin ? (
                    <input type="date" defaultValue={it.acquired_on || ""} style={{ marginTop: 0 }}
                      onBlur={(e) => { if ((e.target.value || "") !== (it.acquired_on || "")) patchItem(it, { acquired_on: e.target.value || null }); }} />
                  ) : <span>{it.acquired_on || "–"}</span>}
                </td>
                <td data-label="Garantie bis">
                  {isAdmin ? (
                    <input key={it.warranty_until || "none"} type="date"
                      defaultValue={it.warranty_until || ""} style={{ marginTop: 0 }}
                      onBlur={(e) => { if ((e.target.value || "") !== (it.warranty_until || "")) patchItem(it, { warranty_until: e.target.value || null }); }} />
                  ) : <span>{it.warranty_until || "–"}</span>}
                </td>
                <td data-label="Gekauft bei">
                  {isAdmin ? (
                    <select value={it.shop_id ?? ""} style={{ marginTop: 0, minWidth: 120 }}
                      onChange={(e) => patchItem(it, { shop_id: e.target.value === "" ? null : Number(e.target.value) })}>
                      <option value="">– unbekannt –</option>
                      {shops.map((s) => <option key={s.id} value={s.id}>{s.name}</option>)}
                    </select>
                  ) : <span>{it.shop_name || "–"}</span>}
                </td>
                <td data-label="Notiz">
                  {isAdmin ? (
                    <input defaultValue={it.note || ""} placeholder="z.B. Zustand" style={{ marginTop: 0, minWidth: 120 }}
                      onBlur={(e) => { if ((e.target.value || "") !== (it.note || "")) patchItem(it, { note: e.target.value || null }); }} />
                  ) : <span>{it.note || "–"}</span>}
                </td>
                <td className="num">
                  {isAdmin && (
                    <div className="field-inline" style={{ justifyContent: "flex-end" }}>
                      <button className="btn-icon" title="Mit Grund entfernen"
                        onClick={() => setRemove({ item: it, reason: "broken", note: "" })}>
                        <Icon name="checkout" size={16} />
                      </button>
                      <button className="btn-icon danger" title="Löschen (Korrektur)"
                        onClick={() => loeschen(it)}>
                        <Icon name="trash" size={16} />
                      </button>
                    </div>
                  )}
                </td>
              </tr>
              <tr className="einzel-detailrow">
                <td colSpan={8}>
                    <div style={{ display: "grid", gap: "var(--sp-4)",
                      gridTemplateColumns: "repeat(auto-fit, minmax(240px, 1fr))" }}>
                      <label style={{ margin: 0 }}>Kaufpreis
                        <div className="field-inline">
                          <input key={it.price_cents ?? "none"} type="number" step="0.01" min="0"
                            style={{ maxWidth: 140 }} disabled={!isAdmin}
                            defaultValue={it.price_cents != null ? (it.price_cents / 100) : ""}
                            placeholder="0.00" onBlur={(e) => savePrice(it, e.target.value)} />
                          <select defaultValue={it.currency || "CHF"} disabled={!isAdmin}
                            onChange={(e) => patchItem(it, { currency: e.target.value })}>
                            <option value="CHF">CHF</option>
                            <option value="EUR">EUR</option>
                          </select>
                        </div>
                      </label>
                      <div>
                        <label style={{ margin: 0 }}>Belege (Rechnung/Garantieschein)
                          {isAdmin && (
                            <input type="file" accept="application/pdf,image/*"
                              onChange={(e) => { const f = e.target.files?.[0]; if (f) uploadDoc(it, f); e.target.value = ""; }} />
                          )}
                        </label>
                        {suggestion && suggestion.itemId === it.id
                          && (suggestion.date || suggestion.priceCents != null) && (
                          <div className="alert ok" style={{ marginTop: "var(--sp-2)" }}>
                            <Icon name="check" size={16} />
                            <span>
                              Im Beleg erkannt:
                              {suggestion.date ? ` Garantie bis ${suggestion.date}` : ""}
                              {suggestion.date && suggestion.priceCents != null ? "," : ""}
                              {suggestion.priceCents != null ? ` Kaufpreis ${(suggestion.priceCents / 100).toFixed(2)}` : ""}.
                            </span>
                            <button type="button" className="btn sm" style={{ marginLeft: "auto" }}
                              onClick={() => {
                                const body = {};
                                if (suggestion.date) body.warranty_until = suggestion.date;
                                if (suggestion.priceCents != null) {
                                  body.price_cents = suggestion.priceCents;
                                  body.currency = it.currency || "CHF";
                                }
                                patchItem(it, body);
                                setSuggestion(null);
                              }}>
                              Übernehmen
                            </button>
                            <button type="button" className="btn sm ghost" onClick={() => setSuggestion(null)}>Verwerfen</button>
                          </div>
                        )}
                        <ul className="clean-list" style={{ marginTop: "var(--sp-2)" }}>
                          {(it.documents || []).map((d) => (
                            <li key={d.id} className="cell-row">
                              <button type="button" className="btn sm ghost" onClick={() => viewDoc(it, d)}>
                                <Icon name="download" size={14} />{d.filename}
                              </button>
                              {isAdmin && (
                                <button className="btn-icon danger" style={{ marginLeft: "auto" }}
                                  title="Beleg löschen" onClick={() => deleteDoc(it, d)}>
                                  <Icon name="trash" size={15} />
                                </button>
                              )}
                            </li>
                          ))}
                          {(it.documents || []).length === 0 && (
                            <li className="muted small">Noch keine Belege.</li>
                          )}
                        </ul>
                      </div>
                    </div>
                  </td>
                </tr>
              </Fragment>
            ))}
            {items.length === 0 && <tr><td colSpan={8} className="empty">Noch keine Einzelstücke.</td></tr>}
          </tbody>
        </table>
      </div>

      {isAdmin && !showAdd && (
        <button type="button" className="btn" style={{ marginTop: "var(--sp-3)" }}
          onClick={() => setShowAdd(true)}>
          <Icon name="plus" size={16} />Einzelstück anlegen
        </button>
      )}

      {isAdmin && showAdd && (
        <form onSubmit={add} className="card-sub" style={{ marginTop: "var(--sp-3)" }}>
          <div className="card-head"><Icon name="plus" /><h3>Einzelstücke anlegen</h3>
            <button type="button" className="btn-icon" style={{ marginLeft: "auto" }}
              title="Schließen" onClick={() => setShowAdd(false)}>
              <Icon name="close" size={16} />
            </button>
          </div>
          <div className="row">
            <label style={{ width: 90 }}>Anzahl
              <input type="number" min="1" max="200" value={addForm.count}
                onChange={(e) => setAddForm({ ...addForm, count: e.target.value })} />
            </label>
            <label className="grow">Lagerort
              <select value={addForm.location_id}
                onChange={(e) => setAddForm({ ...addForm, location_id: e.target.value })}>
                <option value="">– ohne –</option>
                {locations.map((l) => <option key={l.id} value={l.id}>{l.name}</option>)}
              </select>
            </label>
            <label className="grow">Gekauft bei
              <select value={addForm.shop_id}
                onChange={(e) => setAddForm({ ...addForm, shop_id: e.target.value })}>
                <option value="">– unbekannt –</option>
                {shops.map((s) => <option key={s.id} value={s.id}>{s.name}</option>)}
              </select>
            </label>
          </div>
          <div className="row">
            <label className="grow">Gekauft am
              <input type="date" value={addForm.acquired_on}
                onChange={(e) => setAddForm({ ...addForm, acquired_on: e.target.value })} />
            </label>
            <label className="grow">Garantie bis
              <input type="date" value={addForm.warranty_until}
                onChange={(e) => setAddForm({ ...addForm, warranty_until: e.target.value })} />
            </label>
            <label className="grow">Notiz
              <input value={addForm.note} placeholder="optional"
                onChange={(e) => setAddForm({ ...addForm, note: e.target.value })} />
            </label>
          </div>
          <p className="muted small">
            Gemeinsame Startwerte für alle neuen Stücke – danach je Stück änderbar
            (z.B. dasselbe Modell 2024 und 2025). Jedes bekommt eine eigene UID + QR.
          </p>
          <button className="btn primary"><Icon name="plus" size={16} />Anlegen</button>
        </form>
      )}

      {isAdmin && remove && (
        <form onSubmit={doRemove} className="card-sub" style={{ marginTop: "var(--sp-3)" }}>
          <div className="card-head"><Icon name="trash" /><h3>Einzelstück {remove.item.uid} entfernen</h3>
            <button type="button" className="btn-icon" style={{ marginLeft: "auto" }}
              onClick={() => setRemove(null)}><Icon name="close" size={16} /></button>
          </div>
          <div className="row">
            <label className="grow">Grund
              <select value={remove.reason} onChange={(e) => setRemove({ ...remove, reason: e.target.value })}>
                {REASONS.map((r) => <option key={r.value} value={r.value}>{r.label}</option>)}
              </select>
            </label>
            <label className="grow">Notiz (optional)
              <input value={remove.note} onChange={(e) => setRemove({ ...remove, note: e.target.value })} />
            </label>
          </div>
          <button className="btn danger">Entfernen</button>
        </form>
      )}
    </section>
  );
}
