// Entry.jsx — main "record one expense" screen with keypad, sheets, and (fake) OCR
const { useState, useMemo, useRef } = React;

const MAX_PHOTOS = 3;
const MAX_TOTAL_PHOTO_BYTES = 900_000; // safety margin under Firestore's 1 MiB doc limit

function EntryScreen({
  me, names, books, cats, templates, currentBookId, setCurrentBookId,
  onSave, defaultMode, amountFontSize, keyHeight, accent,
  editing, onCancelEdit
}) {
  const initial = editing || {};
  const [amount, setAmount] = useState(editing ? String(editing.amount) : "0");
  const [payer, setPayer] = useState(initial.payer || me);
  const [split, setSplit] = useState(initial.split || { mode: defaultMode });
  const [category, setCategory] = useState(initial.category || "food");
  const [note, setNote] = useState(initial.note || "");
  const [items, setItems] = useState(initial.items || []);
  const [bookId, setBookId] = useState(initial.bookId || currentBookId);
  const [date, setDate] = useState(initial.date || new Date().toISOString());
  const [pending, setPending] = useState(!!initial.pending);
  const [photos, setPhotos] = useState(initial.photos || []);

  function applyTemplate(tpl) {
    if (tpl.amount) setAmount(String(tpl.amount));
    if (tpl.category) setCategory(tpl.category);
    if (tpl.note) setNote(tpl.note);
    if (tpl.split) setSplit(tpl.split);
  }

  const [splitSheet, setSplitSheet] = useState(false);
  const [bookSheet, setBookSheet] = useState(false);
  const [itemSheet, setItemSheet] = useState(false);
  const [dateSheet, setDateSheet] = useState(false);
  const [photoSheet, setPhotoSheet] = useState(false);
  const [previewIdx, setPreviewIdx] = useState(null);
  const [addingPhoto, setAddingPhoto] = useState(false);
  const [ocrLoading, setOcrLoading] = useState(false);
  const [ocrConfirm, setOcrConfirm] = useState(null);
  const [tplSheet, setTplSheet] = useState(false);
  const [error, setError] = useState("");
  const [toast, setToast] = useState("");
  const ocrInputRef = useRef(null);

  const exprValue = useMemo(() => {
    const v = window.evalExpr(amount);
    return v == null ? 0 : v;
  }, [amount]);
  const showingExpr = /[+\-*/]/.test(amount);

  const activeBooks = books.filter((b) => b.status === "active");
  const currentBook = books.find((b) => b.id === bookId);

  function handleSave() {
    const finalAmount = exprValue;
    if (!pending && finalAmount <= 0) {
      setError("金額不可為 0");
      return;
    }
    if (!pending && split.mode === "custom") {
      const sum = (split.amounts.A || 0) + (split.amounts.B || 0);
      if (split.amounts.totalDriven !== true && Math.abs(sum - finalAmount) > 0.01) {
        setError(`分攤金額需等於 ${fmtMoney(finalAmount)}`);
        return;
      }
    }
    const totalPhotoBytes = photos.reduce((s, p) => s + dataUrlByteSize(p), 0);
    if (totalPhotoBytes > MAX_TOTAL_PHOTO_BYTES) {
      setError("附件總大小超過上限,請減少張數或重拍");
      return;
    }
    const tx = {
      id: editing ? editing.id : "tx" + Date.now(),
      amount: pending ? 0 : finalAmount,
      pending,
      payer, split, category, note, items, bookId, date,
    };
    if (photos.length > 0) tx.photos = photos;
    onSave(tx);
    setToast(editing ? "已更新" : "已記下");
    setTimeout(() => setToast(""), 1200);
    if (!editing) {
      setAmount("0"); setNote(""); setItems([]); setPending(false);
      setSplit({ mode: defaultMode });
      setDate(new Date().toISOString());
      setPhotos([]);
    } else {
      onCancelEdit && onCancelEdit();
    }
  }

  async function handleOcrFile(file) {
    if (!file) return;
    setOcrLoading(true);
    setError("");
    try {
      const dataUrl = await window.compressImage(file, 1600, 0.85);
      const token = await window.firebaseApi.auth.getIdToken();
      if (!token) throw new Error("請先登入");
      const url = window.__OCR_WORKER_URL__;
      if (!url) throw new Error("OCR 尚未設定");
      const res = await fetch(url, {
        method: "POST",
        headers: {
          "Authorization": "Bearer " + token,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ image: dataUrl }),
      });
      if (!res.ok) {
        throw new Error(res.status === 401 ? "登入逾時,請重新登入" : "辨識失敗");
      }
      const r = await res.json();
      setOcrConfirm({
        amount: r.amount,
        category: r.suggestedCategory || "other",
        merchant: r.merchant || "",
        date: r.date,
        items: Array.isArray(r.items) ? r.items : [],
      });
    } catch (e) {
      setError(e.message || "辨識失敗");
    } finally {
      setOcrLoading(false);
    }
  }
  function applyOcr() {
    setAmount(String(ocrConfirm.amount || 0));
    if (ocrConfirm.category) setCategory(ocrConfirm.category);
    if (ocrConfirm.merchant) setNote(ocrConfirm.merchant);
    if (ocrConfirm.date) {
      const d = new Date(ocrConfirm.date + "T12:00:00");
      if (!isNaN(d)) setDate(d.toISOString());
    }
    if (Array.isArray(ocrConfirm.items) && ocrConfirm.items.length > 0) {
      setItems(ocrConfirm.items.map((it) => ({
        name: it.name || "",
        qty: it.qty || 1,
        price: it.price || 0,
      })));
    }
    setOcrConfirm(null);
  }

  const splitLabel = useMemo(() => {
    if (split.mode === "even") return "均分";
    if (split.mode === "ratio") return `${names.A} : ${names.B} / ${split.ratio[0]} : ${split.ratio[1]}`;
    if (split.mode === "custom") {
      const a = split.amounts?.A || 0;
      const b = split.amounts?.B || 0;
      return `${names.A} ${fmtMoney(a)} / ${names.B} ${fmtMoney(b)}`;
    }
    if (split.mode === "treat") return `${names[split.treatBy]} 請客`;
    return "均分";
  }, [split, names]);

  const displayAmount = useMemo(() => {
    if (showingExpr) return amount.replace(/\*/g, "×").replace(/\//g, "÷");
    if (amount === "0") return "0";
    const n = parseFloat(amount) || 0;
    return n.toLocaleString("en-US", { maximumFractionDigits: 2 }) + (amount.endsWith(".") ? "." : "");
  }, [amount, showingExpr]);

  return (
    <div className="screen entry" data-screen-label="01 記帳">
      {editing &&
      <div className="edit-banner">
          <span>編輯一筆</span>
          <button onClick={onCancelEdit}>取消</button>
        </div>
      }

      <div className="entry-scroll">
        <div className="entry-top">
          <button className="book-pill" onClick={() => setBookSheet(true)}>
            <span className="book-pill-dot" style={{ background: currentBook?.type === "trip" ? accent : "#1A1A1A" }} />
            {currentBook?.name || "日常"}
            <span className="book-pill-caret">▾</span>
          </button>
          <button className="book-pill" onClick={() => setDateSheet(true)}>
            <span className="num">{ymd(date).slice(5).replace("-", "/")}</span>
            <span className="book-pill-caret">▾</span>
          </button>
          <div style={{ flex: 1 }} />
          <button className="cam-btn" onClick={() => ocrInputRef.current?.click()} aria-label="拍照辨識">
            <CamIcon />
          </button>
          <input ref={ocrInputRef} type="file" accept="image/*" capture="environment"
            hidden
            onChange={(e) => {
              const f = e.target.files && e.target.files[0];
              e.target.value = "";
              handleOcrFile(f);
            }} />
          <button className="cam-btn" onClick={() => setTplSheet(true)} aria-label="常用組套">
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <rect x="3" y="4" width="18" height="4" rx="1"/>
              <rect x="3" y="10" width="18" height="4" rx="1"/>
              <rect x="3" y="16" width="18" height="4" rx="1"/>
            </svg>
          </button>
        </div>

        <div className="amount-wrap">
          <div className="amount-currency">NT$</div>
          <div className="amount-num"
          style={{ fontSize: amountFontSize, color: pending ? "#C8C8C8" : exprValue === 0 && amount === "0" ? "#C8C8C8" : "#1A1A1A" }}>
            {displayAmount}
          </div>
        </div>
        {showingExpr &&
        <div className="amount-preview num">＝ {fmtMoney(exprValue)}</div>
        }

        <div className="pending-row">
          <label className={"pending-toggle" + (pending ? " is-on" : "")}>
            <input type="checkbox" checked={pending} onChange={(e) => setPending(e.target.checked)} />
            <span className="pending-box" style={pending ? { borderColor: accent, background: accent } : {}}>
              <span className="pending-tick" style={{ opacity: pending ? 1 : 0 }}>✓</span>
            </span>
            <span>待處理</span>
          </label>
        </div>

        <div className="payer-row">
          <span className="payer-label">付款</span>
          <Segment
            options={[{ value: "A", label: names.A }, { value: "B", label: names.B }]}
            value={payer} onChange={setPayer} />
        </div>

        <div className="cat-row">
          {cats.map((c) =>
          <button key={c.id}
          className={"cat-chip" + (category === c.id ? " is-on" : "")}
          onClick={() => setCategory(c.id)}
          style={category === c.id ? { borderColor: accent, color: accent } : {}}>
              {c.label}
            </button>
          )}
        </div>

        <div className="meta-list">
          <Row onClick={() => setSplitSheet(true)}>
            <span className="meta-k">分攤</span>
            <span className="meta-v">{splitLabel} <span className="caret">›</span></span>
          </Row>
          <div className="row note-row" style={{ textAlign: "left" }}>
            <span className="meta-k">備註</span>
            <textarea className="meta-input note-area" placeholder="選填"
            rows={1}
            value={note}
            onChange={(e) => {
              setNote(e.target.value);
              e.target.style.height = "auto";
              e.target.style.height = Math.min(e.target.scrollHeight, 120) + "px";
            }}
            maxLength={200} />
          </div>
          <Row onClick={() => setItemSheet(true)}>
            <span className="meta-k">明細</span>
            <span className="meta-v">
              {items.length === 0 ? <span style={{ color: "#C8C8C8" }}>選填</span> : `${items.length} 項`}
              <span className="caret">›</span>
            </span>
          </Row>
          <Row onClick={() => setPhotoSheet(true)}>
            <span className="meta-k">附件</span>
            <span className="meta-v">
              {photos.length === 0
                ? <span style={{ color: "#C8C8C8" }}>選填</span>
                : `${photos.length}/${MAX_PHOTOS}`}
              <span className="caret">›</span>
            </span>
          </Row>
        </div>

        {items.length > 0 &&
        <div className="entry-items">
            {items.map((it, i) =>
          <div key={i} className="entry-item-row">
                <span className="entry-item-name">{it.name}</span>
                <span className="num entry-item-qty">×{it.qty}</span>
                <span className="num entry-item-price">{fmtMoney(it.price * it.qty)}</span>
                <button className="entry-item-x"
            onClick={() => setItems(items.filter((_, j) => j !== i))}>×</button>
              </div>
          )}
          </div>
        }

        {error && <div className="entry-error">{error}</div>}
      </div>

      <div className="entry-pad">
        <Keypad value={amount} onChange={(v) => { if (pending) return; setAmount(v); setError(""); }}
        keyHeight={keyHeight} calc accent={accent} />
        <button className="save-btn" style={{ background: accent }} onClick={handleSave}>
          {editing ? "更新" : "記下"}
        </button>
      </div>

      <Sheet open={splitSheet} onClose={() => setSplitSheet(false)} title="分攤方式">
        <SplitPicker
          amount={exprValue} names={names} value={split} accent={accent}
          onChange={(v) => setSplit(v)}
          onTotalDriven={(newTotal) => setAmount(String(newTotal))} />

        <button className="sheet-done" style={{ color: accent }} onClick={() => setSplitSheet(false)}>完成</button>
      </Sheet>

      <Sheet open={bookSheet} onClose={() => setBookSheet(false)} title="選擇帳本">
        {activeBooks.map((b) =>
        <button key={b.id}
        className={"sheet-row" + (b.id === bookId ? " is-on" : "")}
        onClick={() => { setBookId(b.id); setBookSheet(false); }}>
            <span className="sheet-row-dot" style={{ background: b.type === "trip" ? accent : "#1A1A1A" }} />
            <span className="sheet-row-l">{b.name}</span>
            <span className="sheet-row-r">{b.type === "trip" ? "旅遊" : "日常"}</span>
          </button>
        )}
      </Sheet>

      <Sheet open={dateSheet} onClose={() => setDateSheet(false)} title="日期">
        <input type="date" className="form-in" style={{ height: 48, border: "1px solid var(--line)", borderRadius: 4, padding: "0 12px", fontFamily: "var(--mono)", fontSize: 16 }}
        value={ymd(date)}
        onChange={(e) => {
          const d = new Date(e.target.value);
          const orig = new Date(date);
          d.setHours(orig.getHours(), orig.getMinutes());
          setDate(d.toISOString());
        }} />
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 8, marginTop: 12 }}>
          {[0, 1, 2].map((n) => {
            const d = new Date(); d.setDate(d.getDate() - n);
            return (
              <button key={n} className="ocr-btn" onClick={() => {
                d.setHours(new Date(date).getHours(), new Date(date).getMinutes());
                setDate(d.toISOString()); setDateSheet(false);
              }}>{n === 0 ? "今天" : n === 1 ? "昨天" : "前天"}</button>);
          })}
        </div>
        <button className="sheet-done" style={{ color: accent }} onClick={() => setDateSheet(false)}>完成</button>
      </Sheet>

      <Sheet open={itemSheet} onClose={() => setItemSheet(false)} title="明細">
        <ItemEditor items={items} onChange={setItems} accent={accent} />
        <button className="sheet-done" style={{ color: accent }} onClick={() => setItemSheet(false)}>完成</button>
      </Sheet>

      <Sheet open={photoSheet} onClose={() => setPhotoSheet(false)} title="附件">
        <div className="photo-grid">
          {photos.map((src, i) =>
            <PhotoThumb key={i} src={src} accent={accent}
              onTap={() => setPreviewIdx(i)}
              onLongPress={() => {
                if (confirm("刪除這張？")) {
                  setPhotos((prev) => prev.filter((_, j) => j !== i));
                  setError("");
                }
              }} />
          )}
          {photos.length < MAX_PHOTOS && (
            <label className="photo-add" style={{ color: accent }}>
              <input type="file" accept="image/*" hidden
                onChange={async (e) => {
                  const file = e.target.files && e.target.files[0];
                  e.target.value = "";
                  if (!file) return;
                  setAddingPhoto(true);
                  setError("");
                  try {
                    const dataUrl = await compressImage(file);
                    setPhotos((prev) => [...prev, dataUrl]);
                  } catch (err) {
                    setError("照片壓縮失敗,請換一張試試");
                  } finally {
                    setAddingPhoto(false);
                  }
                }} />
              {addingPhoto
                ? <span className="ocr-spinner" style={{ width: 22, height: 22, borderTopColor: accent }} />
                : <span className="photo-add-plus">＋</span>}
            </label>
          )}
        </div>
        <div className="photo-tip">最多 {MAX_PHOTOS} 張 · 點擊預覽 · 長按刪除</div>
        <button className="sheet-done" style={{ color: accent }} onClick={() => setPhotoSheet(false)}>完成</button>
      </Sheet>

      <PhotoPreview
        photos={photos}
        index={previewIdx}
        onClose={() => setPreviewIdx(null)}
        onChange={setPreviewIdx} />

      <Sheet open={tplSheet} onClose={() => setTplSheet(false)} title="常用組套">
        {(!templates || templates.length === 0) ? (
          <div style={{ padding: "20px 0", textAlign: "center", color: "var(--fg2)", fontSize: 13 }}>
            尚未新增組套。
          </div>
        ) : (
          <div className="tpl-list">
            {templates.map((tpl) => {
              const cat = cats.find((c) => c.id === tpl.category);
              return (
                <button key={tpl.id} className="tpl-list-row"
                  onClick={() => { applyTemplate(tpl); setTplSheet(false); }}>
                  <span className="hist-cat" style={{ width: 32, height: 32, fontSize: 14, color: cat?.color, borderColor: cat?.color }}>{cat?.label}</span>
                  <span className="tpl-list-body">
                    <span className="tpl-list-name">{tpl.name}</span>
                    <span className="tpl-list-sub">
                      {(() => {
                        const parts = [];
                        if (tpl.note) parts.push(tpl.note);
                        if (tpl.amount) parts.push(fmtMoney(tpl.amount));
                        if (tpl.split) {
                          if (tpl.split.mode === "even") {
                            parts.push("均分");
                          } else if (tpl.split.mode === "ratio") {
                            parts.push(`${names.A} : ${names.B} / ${tpl.split.ratio[0]} : ${tpl.split.ratio[1]}`);
                          } else if (tpl.split.mode === "custom") {
                            parts.push(`${names.A} ${fmtMoney(tpl.split.amounts.A || 0)} / ${names.B} ${fmtMoney(tpl.split.amounts.B || 0)}`);
                          }
                        }
                        return parts.join(" · ");
                      })()}
                    </span>
                  </span>
                </button>
              );
            })}
          </div>
        )}
      </Sheet>

      {ocrLoading &&
      <div className="ocr-overlay">
          <div className="ocr-card">
            <div className="ocr-spinner" style={{ borderTopColor: accent }} />
            <div className="ocr-text">辨識中</div>
            <div className="ocr-sub">讀取收據資訊</div>
          </div>
        </div>
      }
      <Sheet open={!!ocrConfirm} onClose={() => setOcrConfirm(null)} title="辨識結果">
        {ocrConfirm &&
        <div className="ocr-confirm">
            <div className="ocr-merchant">{ocrConfirm.merchant}</div>
            <div className="ocr-grid">
              <div className="ocr-cell">
                <div className="ocr-cell-k">金額</div>
                <div className="ocr-cell-v num">NT$ {ocrConfirm.amount}</div>
              </div>
              <div className="ocr-cell">
                <div className="ocr-cell-k">分類</div>
                <div className="ocr-cat-row">
                  {cats.map((c) =>
                <button key={c.id}
                className={"ocr-cat-chip" + (ocrConfirm.category === c.id ? " is-on" : "")}
                onClick={() => setOcrConfirm({ ...ocrConfirm, category: c.id })}
                style={ocrConfirm.category === c.id ? { borderColor: accent, color: accent } : {}}>
                      {c.label}
                    </button>
                )}
                </div>
              </div>
            </div>
            {ocrConfirm.items && ocrConfirm.items.length > 0 &&
              <div className="ocr-items">
                {ocrConfirm.items.map((it, i) =>
                  <div key={i} className="ocr-item-row">
                    <span>{it.name}</span>
                    <span className="num" style={{ color: "#888" }}>×{it.qty || 1}</span>
                    <span className="num">{fmtMoney(it.price)}</span>
                  </div>
                )}
              </div>
            }
            <div className="ocr-actions">
              <button className="ocr-btn" onClick={() => setOcrConfirm(null)}>取消</button>
              <button className="ocr-btn solid" style={{ background: accent, borderColor: accent }} onClick={applyOcr}>套用</button>
            </div>
          </div>
        }
      </Sheet>

      {toast && <div className="toast">{toast}</div>}
    </div>);
}

function ItemEditor({ items, onChange, accent }) {
  const [draft, setDraft] = useState({ name: "", qty: "1", price: "" });
  function add() {
    if (!draft.name.trim()) return;
    const it = {
      name: draft.name.trim(),
      qty: parseFloat(draft.qty) || 1,
      price: parseFloat(draft.price) || 0
    };
    onChange([...items, it]);
    setDraft({ name: "", qty: "1", price: "" });
  }
  function remove(i) { onChange(items.filter((_, j) => j !== i)); }
  return (
    <div className="item-editor">
      {items.length > 0 &&
      <div className="item-list">
          {items.map((it, i) =>
        <div key={i} className="item-row">
              <span className="item-name">{it.name}</span>
              <span className="num item-qty">×{it.qty}</span>
              <span className="num item-price">{fmtMoney(it.price * it.qty)}</span>
              <button className="item-x" onClick={() => remove(i)}>×</button>
            </div>
        )}
        </div>
      }
      <div className="item-add">
        <input className="item-in name" placeholder="品項" value={draft.name}
        onChange={(e) => setDraft({ ...draft, name: e.target.value })} />
        <input className="item-in qty num" placeholder="1" value={draft.qty}
        onChange={(e) => setDraft({ ...draft, qty: e.target.value })} />
        <input className="item-in price num" placeholder="單價" inputMode="decimal" value={draft.price}
        onChange={(e) => setDraft({ ...draft, price: e.target.value })} />
        <button className="item-plus" style={{ color: accent }} onClick={add}>＋</button>
      </div>
    </div>);
}

function CamIcon() {
  return (
    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4">
      <path d="M4 8h3l1.5-2h7L17 8h3v11H4z" />
      <circle cx="12" cy="13.5" r="3.5" />
    </svg>);
}
// PhotoThumb — single thumbnail with tap (preview) and long-press (delete) on
// touch + mouse. The 600ms hold timer is shared between both event paths so
// it works in desktop preview (mouse) and on iOS (touch).
function PhotoThumb({ src, accent, onTap, onLongPress }) {
  const timer = useRef(null);
  const triggered = useRef(false);
  const start = () => {
    triggered.current = false;
    timer.current = setTimeout(() => {
      triggered.current = true;
      if (typeof navigator !== "undefined" && navigator.vibrate) navigator.vibrate(20);
      onLongPress();
    }, 600);
  };
  const cancel = () => {
    if (timer.current) { clearTimeout(timer.current); timer.current = null; }
  };
  return (
    <div className="photo-thumb"
      style={{ backgroundImage: `url(${src})`, borderColor: accent }}
      onTouchStart={start} onTouchEnd={cancel} onTouchMove={cancel} onTouchCancel={cancel}
      onMouseDown={start} onMouseUp={cancel} onMouseLeave={cancel}
      onContextMenu={(e) => e.preventDefault()}
      onClick={() => { if (!triggered.current) onTap(); }}
    />
  );
}

window.EntryScreen = EntryScreen;
