import { useState, useEffect, useCallback, useContext } from "react";
import { AuthContext } from "./AuthContext";
import Login from "./Login";
import Register from "./Register";

// ─── Storage helpers with Browser/localStorage Fallback ───
const STORAGE_KEY = "coffee-logbook-data";
const defaultData = { beans: [], brewLogs: [], lastSyncedAt: null };

const storage = {
  get: async (key) => {
    try {
      if (window.storage && typeof window.storage.get === "function") {
        return await window.storage.get(key);
      }
      const val = localStorage.getItem(key);
      return val ? { value: val } : null;
    } catch {
      return null;
    }
  },
  set: async (key, val) => {
    try {
      if (window.storage && typeof window.storage.set === "function") {
        await window.storage.set(key, val);
        return;
      }
      localStorage.setItem(key, val);
    } catch (e) {
      console.error("Storage set failed:", e);
    }
  }
};

async function loadData() {
  try {
    const result = await storage.get(STORAGE_KEY);
    if (result) {
      const parsed = JSON.parse(result.value);
      return {
        beans: parsed.beans || [],
        brewLogs: parsed.brewLogs || [],
        lastSyncedAt: parsed.lastSyncedAt || null
      };
    }
    return defaultData;
  } catch {
    return defaultData;
  }
}

async function saveData(data) {
  try {
    await storage.set(STORAGE_KEY, JSON.stringify(data));
  } catch (e) {
    console.error("Save failed:", e);
  }
}

const uid = () => Date.now().toString(36) + Math.random().toString(36).slice(2, 7);

const ROAST_TYPES = ["Light", "Light-Medium", "Medium", "Medium-Dark", "Dark"];
const METHODS = ["pourover", "espresso", "coldbrew"];
const METHOD_LABELS = { pourover: "Pour Over", espresso: "Espresso", coldbrew: "Cold Brew" };
const METHOD_ICONS = { pourover: "☕", espresso: "⚡", coldbrew: "❄️" };
const METHOD_COLORS = { pourover: "#8B6914", espresso: "#5C3317", coldbrew: "#2F4F6F" };

// ─── Styles ───
const styles = `
  @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,600;0,700;1,400&family=Source+Sans+3:wght@300;400;500;600&display=swap');

  * { box-sizing: border-box; margin: 0; padding: 0; }

  :root {
    --bg: #FAF6F1;
    --bg2: #F3EDE4;
    --card: #FFFFFF;
    --text: #2C1810;
    --text2: #6B5744;
    --text3: #9C8B7A;
    --accent: #8B6914;
    --accent2: #C4941A;
    --border: #E8DFD3;
    --espresso: #5C3317;
    --coldbrew: #2F4F6F;
    --pourover: #8B6914;
    --danger: #B44040;
    --shadow: 0 1px 3px rgba(44,24,16,0.06), 0 4px 12px rgba(44,24,16,0.04);
    --shadow-lg: 0 4px 16px rgba(44,24,16,0.08), 0 12px 32px rgba(44,24,16,0.06);
    --radius: 12px;
    --radius-sm: 8px;
  }

  .app {
    font-family: 'Source Sans 3', sans-serif;
    background: var(--bg);
    color: var(--text);
    min-height: 100vh;
    max-width: 480px;
    margin: 0 auto;
    position: relative;
    overflow-x: hidden;
  }

  h1, h2, h3, .display { font-family: 'Playfair Display', serif; }

  /* ── Header ── */
  .header {
    padding: 24px 20px 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: sticky;
    top: 0;
    background: var(--bg);
    z-index: 50;
    border-bottom: 1px solid var(--border);
  }
  .header h1 { font-size: 22px; font-weight: 600; letter-spacing: -0.3px; }
  .header-sub { font-size: 12px; color: var(--text3); font-weight: 400; letter-spacing: 1.5px; text-transform: uppercase; }

  /* ── Navigation ── */
  .nav {
    display: flex;
    gap: 4px;
    padding: 8px 20px;
    background: var(--bg);
    position: sticky;
    top: 73px;
    z-index: 49;
  }
  .nav-btn {
    flex: 1;
    padding: 10px 8px;
    border: none;
    background: transparent;
    color: var(--text3);
    font-family: 'Source Sans 3', sans-serif;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    border-radius: var(--radius-sm);
    transition: all 0.2s;
    letter-spacing: 0.3px;
  }
  .nav-btn.active {
    background: var(--text);
    color: var(--bg);
    font-weight: 600;
  }
  .nav-btn:hover:not(.active) { background: var(--bg2); color: var(--text); }

  /* ── Content ── */
  .content { padding: 16px 20px 100px; }

  /* ── Cards ── */
  .card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 18px;
    margin-bottom: 12px;
    border: 1px solid var(--border);
    transition: box-shadow 0.2s;
    cursor: pointer;
  }
  .card:hover { box-shadow: var(--shadow-lg); }

  .bean-card-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 8px; }
  .bean-name { font-family: 'Playfair Display', serif; font-size: 17px; font-weight: 600; }
  .bean-roastery { font-size: 13px; color: var(--text2); margin-top: 2px; }
  .bean-meta { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
  .tag {
    font-size: 11px;
    padding: 4px 10px;
    border-radius: 20px;
    background: var(--bg2);
    color: var(--text2);
    font-weight: 500;
    letter-spacing: 0.3px;
  }
  .tag.roast-light { background: #FFF3D6; color: #8B6914; }
  .tag.roast-medium { background: #F0E0C8; color: #6B4E2A; }
  .tag.roast-dark { background: #E0D0BD; color: #4A3520; }

  .brew-card { position: relative; }
  .brew-method-bar {
    position: absolute;
    left: 0;
    top: 12px;
    bottom: 12px;
    width: 4px;
    border-radius: 0 4px 4px 0;
  }
  .brew-card .card { padding-left: 24px; }
  .brew-date { font-size: 11px; color: var(--text3); letter-spacing: 0.5px; }
  .brew-bean { font-size: 14px; font-weight: 600; color: var(--text); margin-top: 2px; }
  .brew-method-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; margin-top: 6px; }
  .brew-details { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 10px; }
  .brew-detail { font-size: 12px; }
  .brew-detail-label { color: var(--text3); font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px; }
  .brew-detail-value { font-weight: 600; margin-top: 1px; }
  .brew-notes { font-size: 13px; color: var(--text2); margin-top: 10px; font-style: italic; line-height: 1.5; }

  /* ── Empty State ── */
  .empty {
    text-align: center;
    padding: 48px 20px;
    color: var(--text3);
  }
  .empty-icon { font-size: 40px; margin-bottom: 12px; opacity: 0.5; }
  .empty h3 { font-size: 16px; margin-bottom: 6px; color: var(--text2); }
  .empty p { font-size: 13px; line-height: 1.5; }

  /* ── Stats row ── */
  .stats {
    display: flex;
    gap: 8px;
    margin-bottom: 20px;
  }
  .stat-card {
    flex: 1;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 12px;
    text-align: center;
  }
  .stat-num { font-family: 'Playfair Display', serif; font-size: 24px; font-weight: 700; }
  .stat-label { font-size: 10px; color: var(--text3); text-transform: uppercase; letter-spacing: 1px; margin-top: 2px; }

  /* ── Forms ── */
  .modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(44,24,16,0.4);
    z-index: 100;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    animation: fadeIn 0.2s;
  }
  @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
  @keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
  @keyframes pulse { 0% { opacity: 0.3; } 50% { opacity: 1; } 100% { opacity: 0.3; } }

  .modal {
    background: var(--bg);
    border-radius: 20px 20px 0 0;
    width: 100%;
    max-width: 480px;
    max-height: 88vh;
    overflow-y: auto;
    animation: slideUp 0.3s ease-out;
    padding: 0 20px 32px;
  }
  .modal-handle {
    width: 36px;
    height: 4px;
    background: var(--border);
    border-radius: 4px;
    margin: 12px auto 16px;
  }
  .modal-title {
    font-family: 'Playfair Display', serif;
    font-size: 20px;
    font-weight: 600;
    margin-bottom: 20px;
  }

  .form-group { margin-bottom: 16px; }
  .form-label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: var(--text2);
    margin-bottom: 6px;
    display: block;
  }
  .form-input, .form-select, .form-textarea {
    width: 100%;
    padding: 12px 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--card);
    font-family: 'Source Sans 3', sans-serif;
    font-size: 14px;
    color: var(--text);
    transition: border-color 0.2s;
    outline: none;
  }
  .form-input:focus, .form-select:focus, .form-textarea:focus {
    border-color: var(--accent);
  }
  .form-textarea { resize: vertical; min-height: 80px; }
  .form-row { display: flex; gap: 10px; }
  .form-row > .form-group { flex: 1; }
  .form-hint { font-size: 11px; color: var(--text3); margin-top: 4px; }

  .method-tabs {
    display: flex;
    gap: 6px;
    margin-bottom: 20px;
  }
  .method-tab {
    flex: 1;
    padding: 12px 8px;
    border: 2px solid var(--border);
    background: var(--card);
    border-radius: var(--radius-sm);
    cursor: pointer;
    text-align: center;
    font-family: 'Source Sans 3', sans-serif;
    font-size: 12px;
    font-weight: 600;
    transition: all 0.2s;
    letter-spacing: 0.3px;
  }
  .method-tab.active { border-color: currentColor; }
  .method-tab-icon { font-size: 20px; margin-bottom: 4px; }

  .btn {
    width: 100%;
    padding: 14px;
    border: none;
    border-radius: var(--radius-sm);
    font-family: 'Source Sans 3', sans-serif;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    letter-spacing: 0.3px;
    transition: opacity 0.2s;
    margin-top: 8px;
  }
  .btn:hover { opacity: 0.9; }
  .btn-primary { background: var(--text); color: var(--bg); }
  .btn-outline { background: transparent; border: 1px solid var(--border); color: var(--text2); }
  .btn-danger { background: transparent; border: 1px solid var(--danger); color: var(--danger); font-size: 12px; padding: 10px; }

  /* ── Image Upload ── */
  .img-upload {
    border: 2px dashed var(--border);
    border-radius: var(--radius-sm);
    padding: 20px;
    text-align: center;
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s;
    position: relative;
    overflow: hidden;
  }
  .img-upload:hover { border-color: var(--accent); background: rgba(139,105,20,0.03); }
  .img-upload.has-image { padding: 0; border-style: solid; }
  .img-upload-icon { font-size: 28px; margin-bottom: 6px; opacity: 0.4; }
  .img-upload-text { font-size: 12px; color: var(--text3); }
  .img-upload input[type="file"] {
    position: absolute;
    inset: 0;
    opacity: 0;
    cursor: pointer;
  }
  .img-preview {
    width: 100%;
    height: 160px;
    object-fit: cover;
    border-radius: var(--radius-sm);
    display: block;
  }
  .img-remove {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: rgba(44,24,16,0.7);
    color: white;
    border: none;
    font-size: 14px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .bean-card-img {
    width: 52px;
    height: 52px;
    border-radius: var(--radius-sm);
    object-fit: cover;
    flex-shrink: 0;
  }
  .bean-detail-img {
    width: 100%;
    height: 180px;
    object-fit: cover;
    border-radius: var(--radius);
    margin-bottom: 16px;
  }
  .bean-tasting { font-size: 13px; color: var(--text2); font-style: italic; margin-top: 6px; line-height: 1.4; }

  /* ── FAB ── */
  .fab {
    position: fixed;
    bottom: 24px;
    right: calc(50% - 220px);
    width: 54px;
    height: 54px;
    border-radius: 50%;
    background: var(--text);
    color: var(--bg);
    border: none;
    font-size: 26px;
    cursor: pointer;
    box-shadow: var(--shadow-lg);
    z-index: 60;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.2s;
  }
  .fab:hover { transform: scale(1.08); }

  .fab-menu {
    position: fixed;
    bottom: 88px;
    right: calc(50% - 220px);
    display: flex;
    flex-direction: column;
    gap: 8px;
    z-index: 61;
    animation: fadeIn 0.15s;
  }
  .fab-option {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 28px;
    font-family: 'Source Sans 3', sans-serif;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    box-shadow: var(--shadow);
    white-space: nowrap;
    transition: all 0.2s;
  }
  .fab-option:hover { box-shadow: var(--shadow-lg); }

  /* ── Section Header ── */
  .section-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 12px;
  }
  .section-title { font-size: 13px; font-weight: 600; color: var(--text2); text-transform: uppercase; letter-spacing: 1px; }

  /* ── Filter pills ── */
  .filter-pills {
    display: flex;
    gap: 6px;
    margin-bottom: 16px;
    overflow-x: auto;
    padding-bottom: 4px;
  }
  .filter-pill {
    padding: 6px 14px;
    border-radius: 20px;
    border: 1px solid var(--border);
    background: var(--card);
    font-family: 'Source Sans 3', sans-serif;
    font-size: 12px;
    font-weight: 500;
    color: var(--text2);
    cursor: pointer;
    white-space: nowrap;
    transition: all 0.2s;
  }
  .filter-pill.active {
    background: var(--text);
    color: var(--bg);
    border-color: var(--text);
  }

  /* ── Detail view ── */
  .detail-back {
    display: flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: none;
    font-family: 'Source Sans 3', sans-serif;
    font-size: 13px;
    color: var(--text2);
    cursor: pointer;
    padding: 0;
    margin-bottom: 16px;
  }
  .detail-section { margin-top: 20px; }
`;

// ─── Components ───

function BeanForm({ onSave, onClose, initial }) {
  const [form, setForm] = useState(initial || { name: "", roastery: "", roastDate: "", roastType: "", image: "", tastingNotes: "" });
  const set = (k, v) => setForm(p => ({ ...p, [k]: v }));
  const canSave = form.name.trim().length > 0;

  const handleImage = (e) => {
    const file = e.target.files?.[0];
    if (!file) return;
    if (file.size > 2 * 1024 * 1024) { alert("Image must be under 2 MB"); return; }
    const reader = new FileReader();
    reader.onload = () => set("image", reader.result);
    reader.readAsDataURL(file);
  };

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        <div className="modal-handle" />
        <div className="modal-title">{initial ? "Edit Bean" : "Add Bean"}</div>

        <div className="form-group">
          <label className="form-label">Bean Name *</label>
          <input className="form-input" placeholder="e.g. Ethiopia Yirgacheffe" value={form.name} onChange={e => set("name", e.target.value)} />
        </div>
        <div className="form-group">
          <label className="form-label">Roastery</label>
          <input className="form-input" placeholder="e.g. Blue Tokai" value={form.roastery} onChange={e => set("roastery", e.target.value)} />
        </div>
        <div className="form-row">
          <div className="form-group">
            <label className="form-label">Roast Date</label>
            <input className="form-input" type="date" value={form.roastDate} onChange={e => set("roastDate", e.target.value)} />
          </div>
          <div className="form-group">
            <label className="form-label">Roast Type</label>
            <select className="form-select" value={form.roastType} onChange={e => set("roastType", e.target.value)}>
              <option value="">Select…</option>
              {ROAST_TYPES.map(r => <option key={r} value={r}>{r}</option>)}
            </select>
          </div>
        </div>

        <div className="form-group">
          <label className="form-label">Bean Photo</label>
          <div className={`img-upload ${form.image ? "has-image" : ""}`}>
            {form.image ? (
              <>
                <img src={form.image} alt="Bean" className="img-preview" />
                <button className="img-remove" onClick={(e) => { e.stopPropagation(); set("image", ""); }} type="button">×</button>
              </>
            ) : (
              <>
                <div className="img-upload-icon">📷</div>
                <div className="img-upload-text">Tap to upload a photo</div>
              </>
            )}
            <input type="file" accept="image/*" onChange={handleImage} />
          </div>
          <div className="form-hint">Max 2 MB · JPG, PNG, or WebP</div>
        </div>

        <div className="form-group">
          <label className="form-label">Tasting Notes</label>
          <textarea className="form-textarea" placeholder="e.g. Citrus, dark chocolate, floral with a honey finish…" value={form.tastingNotes || ""} onChange={e => set("tastingNotes", e.target.value)} />
          <div className="form-hint">Flavour profile from the bag or your own impressions</div>
        </div>

        <button className="btn btn-primary" disabled={!canSave} style={{ opacity: canSave ? 1 : 0.4 }} onClick={() => { if (canSave) onSave(form); }}>
          {initial ? "Save Changes" : "Add to Library"}
        </button>
      </div>
    </div>
  );
}

function BrewForm({ beans, onSave, onClose }) {
  const [method, setMethod] = useState("pourover");
  const [form, setForm] = useState({ beanId: beans[0]?.id || "" });
  const set = (k, v) => setForm(p => ({ ...p, [k]: v }));

  if (beans.length === 0) {
    return (
      <div className="modal-overlay" onClick={onClose}>
        <div className="modal" onClick={e => e.stopPropagation()}>
          <div className="modal-handle" />
          <div className="modal-title">Log a Brew</div>
          <div className="empty">
            <div className="empty-icon">🫘</div>
            <h3>No beans yet</h3>
            <p>Add a bean to your library first, then come back to log a brew.</p>
          </div>
          <button className="btn btn-outline" onClick={onClose}>Close</button>
        </div>
      </div>
    );
  }

  const fields = {
    pourover: [
      { key: "grindSize", label: "Grind Size", placeholder: "e.g. 18 clicks", hint: "Relative to your grinder" },
      { key: "waterTemp", label: "Water Temp", placeholder: "e.g. 93°C" },
      { key: "beanWeight", label: "Bean Weight", placeholder: "e.g. 15g" },
      { key: "brewRatio", label: "Brew Ratio", placeholder: "e.g. 1:16" },
      { key: "brewTime", label: "Brew Time", placeholder: "e.g. 3:30" },
      { key: "numPours", label: "# of Pours", placeholder: "e.g. 4", type: "number" },
    ],
    espresso: [
      { key: "grindSize", label: "Grind Size", placeholder: "e.g. 8" },
      { key: "dose", label: "Dose", placeholder: "e.g. 18g" },
      { key: "yield", label: "Yield", placeholder: "e.g. 36g" },
      { key: "brewTime", label: "Brew Time", placeholder: "e.g. 28s" },
    ],
    coldbrew: [
      { key: "grindSize", label: "Grind Size", placeholder: "e.g. coarse" },
      { key: "beanWeight", label: "Bean Weight", placeholder: "e.g. 100g" },
      { key: "waterVolume", label: "Water Volume", placeholder: "e.g. 700ml" },
      { key: "steepTime", label: "Steep Time", placeholder: "e.g. 18 hours" },
    ],
  };

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        <div className="modal-handle" />
        <div className="modal-title">Log a Brew</div>

        <div className="method-tabs">
          {METHODS.map(m => (
            <button key={m} className={`method-tab ${method === m ? "active" : ""}`}
              style={{ color: method === m ? METHOD_COLORS[m] : undefined }}
              onClick={() => setMethod(m)}>
              <div className="method-tab-icon">{METHOD_ICONS[m]}</div>
              {METHOD_LABELS[m]}
            </button>
          ))}
        </div>

        <div className="form-group">
          <label className="form-label">Bean *</label>
          <select className="form-select" value={form.beanId} onChange={e => set("beanId", e.target.value)}>
            {beans.map(b => <option key={b.id} value={b.id}>{b.name}{b.roastery ? ` — ${b.roastery}` : ""}</option>)}
          </select>
        </div>

        <div className="form-row" style={{ flexWrap: "wrap" }}>
          {fields[method].map(f => (
            <div key={f.key} className="form-group" style={{ flex: "1 1 45%", minWidth: 0 }}>
              <label className="form-label">{f.label}</label>
              <input className="form-input" type={f.type || "text"} placeholder={f.placeholder}
                value={form[f.key] || ""} onChange={e => set(f.key, e.target.value)} />
              {f.hint && <div className="form-hint">{f.hint}</div>}
            </div>
          ))}
        </div>

        <div className="form-group">
          <label className="form-label">{method === "pourover" ? "Recipe Details" : "Notes"}</label>
          <textarea className="form-textarea" placeholder="Describe your recipe, technique, or anything notable…"
            value={form.recipeDetails || ""} onChange={e => set("recipeDetails", e.target.value)} />
        </div>
        <div className="form-group">
          <label className="form-label">Taste Notes</label>
          <input className="form-input" placeholder="e.g. citrus, chocolate, floral"
            value={form.tasteNotes || ""} onChange={e => set("tasteNotes", e.target.value)} />
        </div>

        <button className="btn btn-primary" onClick={() => onSave({ ...form, method })}>
          Save Brew Log
        </button>
      </div>
    </div>
  );
}

function BeanDetail({ bean, logs, onBack, onEdit, onDelete }) {
  const beanLogs = logs.filter(l => l.beanId === bean.id).sort((a, b) => b.createdAt - a.createdAt);
  const roastClass = bean.roastType?.toLowerCase().includes("dark") ? "roast-dark" : bean.roastType?.toLowerCase().includes("medium") ? "roast-medium" : "roast-light";

  return (
    <div>
      <button className="detail-back" onClick={onBack}>← Back</button>
      {bean.image && <img src={bean.image} alt={bean.name} className="bean-detail-img" />}
      <h2 style={{ fontFamily: "'Playfair Display', serif", fontSize: 22, marginBottom: 4 }}>{bean.name}</h2>
      {bean.roastery && <div style={{ color: "var(--text2)", fontSize: 14, marginBottom: 8 }}>{bean.roastery}</div>}
      {bean.tastingNotes && <div className="bean-tasting" style={{ marginBottom: 10 }}>👅 {bean.tastingNotes}</div>}
      <div className="bean-meta">
        {bean.roastType && <span className={`tag ${roastClass}`}>{bean.roastType}</span>}
        {bean.roastDate && <span className="tag">Roasted {bean.roastDate}</span>}
        <span className="tag">{beanLogs.length} brew{beanLogs.length !== 1 ? "s" : ""}</span>
      </div>
      <div style={{ display: "flex", gap: 8, marginTop: 16 }}>
        <button className="btn btn-outline" style={{ flex: 1 }} onClick={onEdit}>Edit</button>
        <button className="btn btn-danger" style={{ flex: 1 }} onClick={onDelete}>Delete</button>
      </div>

      <div className="detail-section">
        <div className="section-title" style={{ marginBottom: 12 }}>Brew History</div>
        {beanLogs.length === 0 ? (
          <div className="empty" style={{ padding: 24 }}>
            <p>No brews logged with this bean yet.</p>
          </div>
        ) : beanLogs.map(log => <BrewCard key={log.id} log={log} beanName={bean.name} />)}
      </div>
    </div>
  );
}

function BrewCard({ log, beanName }) {
  const color = METHOD_COLORS[log.method];
  const allFields = Object.entries(log)
    .filter(([k]) => !["id", "beanId", "method", "createdAt", "recipeDetails", "tasteNotes"].includes(k))
    .filter(([, v]) => v !== "" && v != null);
  const fieldLabels = {
    grindSize: "Grind", waterTemp: "Temp", beanWeight: "Weight", brewRatio: "Ratio",
    brewTime: "Time", numPours: "Pours", dose: "Dose", yield: "Yield",
    waterVolume: "Water", steepTime: "Steep",
  };

  return (
    <div className="brew-card" style={{ position: "relative" }}>
      <div className="brew-method-bar" style={{ background: color }} />
      <div className="card" style={{ cursor: "default" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
          <div>
            <div className="brew-date">{new Date(log.createdAt).toLocaleDateString("en-IN", { day: "numeric", month: "short", year: "numeric" })}</div>
            {beanName && <div className="brew-bean">{beanName}</div>}
          </div>
          <div className="brew-method-label" style={{ color }}>{METHOD_ICONS[log.method]} {METHOD_LABELS[log.method]}</div>
        </div>
        {allFields.length > 0 && (
          <div className="brew-details">
            {allFields.map(([k, v]) => (
              <div key={k} className="brew-detail">
                <div className="brew-detail-label">{fieldLabels[k] || k}</div>
                <div className="brew-detail-value">{v}</div>
              </div>
            ))}
          </div>
        )}
        {log.recipeDetails && <div className="brew-notes">📝 {log.recipeDetails}</div>}
        {log.tasteNotes && <div className="brew-notes">👅 {log.tasteNotes}</div>}
      </div>
    </div>
  );
}

// ─── Main App ───
export default function CoffeeLogbook() {
  const { token, user, loading, logout } = useContext(AuthContext);
  const [authView, setAuthView] = useState("login"); // login | register
  const [data, setData] = useState(null);
  const [view, setView] = useState("dashboard"); // dashboard | beans | brews
  const [modal, setModal] = useState(null); // null | "addBean" | "editBean" | "addBrew"
  const [fabOpen, setFabOpen] = useState(false);
  const [selectedBean, setSelectedBean] = useState(null);
  const [brewFilter, setBrewFilter] = useState("all");
  const [editingBean, setEditingBean] = useState(null);

  const [isOnline, setIsOnline] = useState(navigator.onLine);
  const [syncing, setSyncing] = useState(false);

  // Load local data on mount
  useEffect(() => {
    loadData().then(setData);
  }, []);

  // Sync logic
  const syncData = useCallback(async (currentData = data) => {
    if (!token || !currentData) return;
    if (!navigator.onLine) {
      setIsOnline(false);
      return;
    }
    setIsOnline(true);
    setSyncing(true);

    try {
      const { beans = [], brewLogs = [], lastSyncedAt = null } = currentData;

      const res = await fetch('/api/sync', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${token}`
        },
        body: JSON.stringify({
          lastSyncedAt,
          beans,
          brewLogs
        })
      });

      if (!res.ok) {
        throw new Error('Sync failed');
      }

      const responseData = await res.json();
      const { serverTime, beans: serverBeans, brewLogs: serverLogs } = responseData;

      // Merge server beans
      const mergedBeans = [...beans];
      serverBeans.forEach(sb => {
        const idx = mergedBeans.findIndex(b => b.id === sb.id);
        if (idx >= 0) {
          const localBean = mergedBeans[idx];
          if (new Date(sb.updatedAt) > new Date(localBean.updatedAt || 0)) {
            mergedBeans[idx] = sb;
          }
        } else {
          mergedBeans.push(sb);
        }
      });

      // Merge server logs
      const mergedLogs = [...brewLogs];
      serverLogs.forEach(sl => {
        const idx = mergedLogs.findIndex(l => l.id === sl.id);
        if (idx >= 0) {
          const localLog = mergedLogs[idx];
          if (new Date(sl.updatedAt) > new Date(localLog.updatedAt || 0)) {
            mergedLogs[idx] = sl;
          }
        } else {
          mergedLogs.push(sl);
        }
      });

      // Purge soft-deleted items that are successfully synced to the database
      const finalBeans = mergedBeans.filter(b => !(b.isDeleted && new Date(b.updatedAt) <= new Date(serverTime)));
      const finalLogs = mergedLogs.filter(l => !(l.isDeleted && new Date(l.updatedAt) <= new Date(serverTime)));

      const nextData = {
        beans: finalBeans,
        brewLogs: finalLogs,
        lastSyncedAt: serverTime
      };

      setData(nextData);
      await saveData(nextData);
    } catch (err) {
      console.error('Failed to sync data:', err);
    } finally {
      setSyncing(false);
    }
  }, [token, data]);

  // Periodic and connectivity event-driven sync triggers
  useEffect(() => {
    const handleOnline = () => {
      setIsOnline(true);
      syncData();
    };
    const handleOffline = () => {
      setIsOnline(false);
    };

    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);

    // Initial sync once token and data are loaded
    if (token && data) {
      syncData();
    }

    // Sync every 30 seconds
    const interval = setInterval(() => {
      if (token && data) {
        syncData();
      }
    }, 30000);

    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
      clearInterval(interval);
    };
  }, [token, data === null, syncData]);

  const persist = useCallback(async (newData) => {
    setData(newData);
    await saveData(newData);
    syncData(newData);
  }, [syncData]);

  if (loading) {
    return (
      <div className="app" style={{ display: "flex", alignItems: "center", justifyContent: "center", minHeight: "100vh" }}>
        <style>{styles}</style>
        <div style={{ textAlign: "center", color: "var(--text3)" }}>
          <div style={{ fontSize: 32 }}>☕</div>
          <div style={{ marginTop: 8 }}>Loading…</div>
        </div>
      </div>
    );
  }

  // If not authenticated, show login/register
  if (!token || !user) {
    return (
      <div className="app">
        <style>{styles}</style>
        {authView === "login" ? (
          <>
            <Login onLoginSuccess={() => {}} />
            <div style={{ textAlign: "center", marginTop: "20px" }}>
              <p style={{ color: "var(--text3)" }}>Don't have an account?{' '}
                <button 
                  onClick={() => setAuthView("register")}
                  style={{ background: 'none', border: 'none', color: 'var(--accent)', cursor: 'pointer', textDecoration: 'underline' }}
                >
                  Register
                </button>
              </p>
            </div>
          </>
        ) : (
          <>
            <Register onRegisterSuccess={() => setAuthView("login")} />
            <div style={{ textAlign: "center", marginTop: "20px" }}>
              <p style={{ color: "var(--text3)" }}>Already have an account?{' '}
                <button 
                  onClick={() => setAuthView("login")}
                  style={{ background: 'none', border: 'none', color: 'var(--accent)', cursor: 'pointer', textDecoration: 'underline' }}
                >
                  Login
                </button>
              </p>
            </div>
          </>
        )}
      </div>
    );
  }

  if (!data) return <div className="app" style={{ display: "flex", alignItems: "center", justifyContent: "center", minHeight: "100vh" }}><div style={{ textAlign: "center", color: "var(--text3)" }}><div style={{ fontSize: 32 }}>☕</div><div style={{ marginTop: 8 }}>Loading…</div></div></div>;

  // Filter out soft-deleted items for UI rendering
  const allBeans = data.beans || [];
  const allLogs = data.brewLogs || [];
  
  const beans = allBeans.filter(b => !b.isDeleted);
  const brewLogs = allLogs.filter(l => !l.isDeleted);

  const addBean = (form) => {
    const now = new Date().toISOString();
    const bean = { id: uid(), ...form, updatedAt: now, isDeleted: false };
    persist({ ...data, beans: [...allBeans, bean] });
    setModal(null);
  };

  const updateBean = (form) => {
    const now = new Date().toISOString();
    const nextBeans = allBeans.map(b => b.id === editingBean.id ? { ...b, ...form, updatedAt: now } : b);
    persist({ ...data, beans: nextBeans });
    setModal(null);
    setEditingBean(null);
    if (selectedBean?.id === editingBean.id) setSelectedBean({ ...selectedBean, ...form, updatedAt: now });
  };

  const deleteBean = (id) => {
    const now = new Date().toISOString();
    const nextBeans = allBeans.map(b => b.id === id ? { ...b, isDeleted: true, updatedAt: now } : b);
    const nextLogs = allLogs.map(l => l.beanId === id ? { ...l, isDeleted: true, updatedAt: now } : l);
    persist({ ...data, beans: nextBeans, brewLogs: nextLogs });
    setSelectedBean(null);
  };

  const addBrew = (form) => {
    const now = new Date().toISOString();
    const log = { id: uid(), createdAt: Date.now(), ...form, updatedAt: now, isDeleted: false };
    persist({ ...data, brewLogs: [...allLogs, log] });
    setModal(null);
  };

  const getBeanName = (id) => allBeans.find(b => b.id === id)?.name || "Unknown Bean";

  const filteredLogs = (brewFilter === "all" ? brewLogs : brewLogs.filter(l => l.method === brewFilter))
    .sort((a, b) => b.createdAt - a.createdAt);

  const methodCounts = { pourover: 0, espresso: 0, coldbrew: 0 };
  brewLogs.forEach(l => { if (methodCounts[l.method] !== undefined) methodCounts[l.method]++; });

  return (
    <div className="app">
      <style>{styles}</style>

      {/* Header */}
      <div className="header">
        <div>
          <div className="header-sub">Coffee Logbook</div>
          <h1>Brew Journal</h1>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: "12px" }}>
          <div 
            style={{ 
              display: "flex", 
              alignItems: "center", 
              gap: "4px", 
              fontSize: "11px", 
              fontWeight: "500",
              color: isOnline ? "#4A7C59" : "#B44040",
              background: isOnline ? "rgba(74,124,89,0.08)" : "rgba(180,64,64,0.08)",
              padding: "4px 8px",
              borderRadius: "12px",
              transition: "all 0.3s"
            }}
            title={isOnline ? "All local logs are synchronized with PostgreSQL database" : "No internet connection. Saved locally."}
          >
            <span style={{ fontSize: "10px", animation: syncing ? "pulse 1.5s infinite" : "none" }}>●</span>
            <span>{isOnline ? (syncing ? "Syncing..." : "Synced") : "Offline"}</span>
          </div>
          <span style={{ fontSize: "12px", color: "var(--text2)" }}>{user?.username}</span>
          <button 
            onClick={() => logout()}
            style={{
              fontSize: 28,
              background: 'none',
              border: 'none',
              cursor: 'pointer',
              padding: '4px 8px'
            }}
            title="Logout"
          >
            🚪
          </button>
        </div>
      </div>

      {/* Nav */}
      <div className="nav">
        <button className={`nav-btn ${view === "dashboard" ? "active" : ""}`} onClick={() => { setView("dashboard"); setSelectedBean(null); }}>Dashboard</button>
        <button className={`nav-btn ${view === "beans" ? "active" : ""}`} onClick={() => { setView("beans"); setSelectedBean(null); }}>Bean Library</button>
        <button className={`nav-btn ${view === "brews" ? "active" : ""}`} onClick={() => { setView("brews"); setSelectedBean(null); }}>Brew Logs</button>
      </div>

      {/* Content */}
      <div className="content">

        {/* ── Dashboard ── */}
        {view === "dashboard" && (
          <>
            <div className="stats">
              <div className="stat-card">
                <div className="stat-num">{beans.length}</div>
                <div className="stat-label">Beans</div>
              </div>
              <div className="stat-card">
                <div className="stat-num">{brewLogs.length}</div>
                <div className="stat-label">Brews</div>
              </div>
              <div className="stat-card">
                <div className="stat-num">{new Set(brewLogs.map(l => l.beanId)).size}</div>
                <div className="stat-label">Tried</div>
              </div>
            </div>

            <div className="section-header">
              <div className="section-title">By Method</div>
            </div>
            <div style={{ display: "flex", gap: 8, marginBottom: 24 }}>
              {METHODS.map(m => (
                <div key={m} className="stat-card" style={{ borderTop: `3px solid ${METHOD_COLORS[m]}` }}>
                  <div style={{ fontSize: 20, marginBottom: 4 }}>{METHOD_ICONS[m]}</div>
                  <div className="stat-num" style={{ fontSize: 20 }}>{methodCounts[m]}</div>
                  <div className="stat-label">{METHOD_LABELS[m]}</div>
                </div>
              ))}
            </div>

            <div className="section-header">
              <div className="section-title">Recent Brews</div>
            </div>
            {brewLogs.length === 0 ? (
              <div className="empty">
                <div className="empty-icon">📝</div>
                <h3>No brews yet</h3>
                <p>Tap + to add a bean and start logging your brews.</p>
              </div>
            ) : (
              brewLogs.sort((a, b) => b.createdAt - a.createdAt).slice(0, 5).map(log => (
                <BrewCard key={log.id} log={log} beanName={getBeanName(log.beanId)} />
              ))
            )}
          </>
        )}

        {/* ── Bean Library ── */}
        {view === "beans" && !selectedBean && (
          <>
            <div className="section-header">
              <div className="section-title">Your Beans ({beans.length})</div>
            </div>
            {beans.length === 0 ? (
              <div className="empty">
                <div className="empty-icon">🫘</div>
                <h3>Library is empty</h3>
                <p>Add your first bean to start tracking your coffee journey.</p>
              </div>
            ) : beans.map(bean => {
              const count = brewLogs.filter(l => l.beanId === bean.id).length;
              const roastClass = bean.roastType?.toLowerCase().includes("dark") ? "roast-dark" : bean.roastType?.toLowerCase().includes("medium") ? "roast-medium" : "roast-light";
              return (
                <div key={bean.id} className="card" onClick={() => setSelectedBean(bean)}>
                  <div className="bean-card-header" style={{ gap: 12 }}>
                    {bean.image && <img src={bean.image} alt="" className="bean-card-img" />}
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div className="bean-name">{bean.name}</div>
                      {bean.roastery && <div className="bean-roastery">{bean.roastery}</div>}
                    </div>
                    <span className="tag">{count} brew{count !== 1 ? "s" : ""}</span>
                  </div>
                  {bean.tastingNotes && <div className="bean-tasting">👅 {bean.tastingNotes}</div>}
                  <div className="bean-meta">
                    {bean.roastType && <span className={`tag ${roastClass}`}>{bean.roastType}</span>}
                    {bean.roastDate && <span className="tag">Roasted {bean.roastDate}</span>}
                  </div>
                </div>
              );
            })}
          </>
        )}

        {/* ── Bean Detail ── */}
        {view === "beans" && selectedBean && (
          <BeanDetail
            bean={selectedBean}
            logs={brewLogs}
            onBack={() => setSelectedBean(null)}
            onEdit={() => { setEditingBean(selectedBean); setModal("editBean"); }}
            onDelete={() => { if (confirm("Delete this bean and all its brew logs?")) deleteBean(selectedBean.id); }}
          />
        )}

        {/* ── Brew Logs ── */}
        {view === "brews" && (
          <>
            <div className="filter-pills">
              <button className={`filter-pill ${brewFilter === "all" ? "active" : ""}`} onClick={() => setBrewFilter("all")}>All</button>
              {METHODS.map(m => (
                <button key={m} className={`filter-pill ${brewFilter === m ? "active" : ""}`} onClick={() => setBrewFilter(m)}>
                  {METHOD_ICONS[m]} {METHOD_LABELS[m]}
                </button>
              ))}
            </div>
            {filteredLogs.length === 0 ? (
              <div className="empty">
                <div className="empty-icon">📋</div>
                <h3>No logs {brewFilter !== "all" ? `for ${METHOD_LABELS[brewFilter]}` : "yet"}</h3>
                <p>Start brewing and log your recipes here.</p>
              </div>
            ) : filteredLogs.map(log => (
              <BrewCard key={log.id} log={log} beanName={getBeanName(log.beanId)} />
            ))}
          </>
        )}
      </div>

      {/* FAB */}
      <button className="fab" onClick={() => setFabOpen(!fabOpen)}>{fabOpen ? "×" : "+"}</button>
      {fabOpen && (
        <div className="fab-menu">
          <button className="fab-option" onClick={() => { setFabOpen(false); setModal("addBrew"); }}>☕ Log a Brew</button>
          <button className="fab-option" onClick={() => { setFabOpen(false); setModal("addBean"); }}>🫘 Add Bean</button>
        </div>
      )}

      {/* Modals */}
      {modal === "addBean" && <BeanForm onSave={addBean} onClose={() => setModal(null)} />}
      {modal === "editBean" && editingBean && <BeanForm initial={editingBean} onSave={updateBean} onClose={() => { setModal(null); setEditingBean(null); }} />}
      {modal === "addBrew" && <BrewForm beans={beans} onSave={addBrew} onClose={() => setModal(null)} />}
    </div>
  );
}
