// PrepEditor.jsx — Daily Prep Assignment editor.
// Source-of-truth model matches the iPad app:
//   • Tonight's items = catalog items with target > 0 (no separate "in template" flag)
//   • Per-day overrides: target, priority, comment (note)
//   • PIC is shift-level (one roster for the whole prep crew tonight) — NOT per-item.
// Catalog (master list with name/category/unit) is edited separately under "Prep Catalog".

const PREP_KEY = 'snap-portal-prep-assignments-v2';
const PREP_PIC_KEY = 'snap-portal-prep-pic-v2';

const CATEGORIES = ['Meat', 'Vegetable', 'Sauce', 'Other', 'Cleaning & Fixing'];

// Read the catalog from localStorage (seeded by PrepCatalog).
const getCatalog = () => {
  try {
    const raw = localStorage.getItem(window.CATALOG_KEY || 'snap-portal-prep-catalog-v1');
    if (raw) return JSON.parse(raw);
  } catch(e) {}
  return (window.SEED_CATALOG ? window.SEED_CATALOG() : []);
};

// Build the default per-day assignment from catalog defaults.
// Each item gets a row keyed by id with { target, priority, comment }.
// Items default from SAMPLE_PREP_ITEMS (the iPad app's seed) when present,
// so the portal mirrors what staff would see if no overrides were set.
const seedAssignment = () => {
  const sampleById = {};
  (window.SAMPLE_PREP_ITEMS || []).forEach(s => { sampleById[s.id] = s; });
  const out = {};
  getCatalog().filter(c => !c.archived).forEach(c => {
    const s = sampleById[c.id];
    out[c.id] = {
      target:   s ? s.target : (c.category === 'Cleaning & Fixing' ? 0 : 1),
      priority: s ? s.priority : 'secondary',
      comment:  s?.note || '',
    };
  });
  return out;
};

// Default shift PIC roster — union of everyone the iPad app seeds across items.
const seedShiftPic = () => {
  const all = new Set();
  Object.values(window.SAMPLE_PREP_PIC || {}).forEach(arr => arr.forEach(id => all.add(id)));
  return Array.from(all);
};

const PrepEditor = ({ density = 'comfortable' }) => {
  const [date, setDate] = useState(() => new Date());
  const [assignments, setAssignments] = usePersistent(PREP_KEY, {});
  const [shiftPicByDate, setShiftPicByDate] = usePersistent(PREP_PIC_KEY, {});
  const [savedToast, setSavedToast] = useState(false);
  const [picPickerOpen, setPicPickerOpen] = useState(false);
  const [selected, setSelected] = useState(null);

  const dateKey = isoDate(date);
  const past = isPast(date);
  const future = isFuture(date);

  // Initialise this date if needed
  useEffect(() => {
    if (!assignments[dateKey]) {
      setAssignments(a => ({ ...a, [dateKey]: seedAssignment() }));
    }
    if (!shiftPicByDate[dateKey]) {
      setShiftPicByDate(p => ({ ...p, [dateKey]: seedShiftPic() }));
    }
  }, [dateKey]);

  const tplRows = assignments[dateKey] || seedAssignment();
  const shiftPic = shiftPicByDate[dateKey] || seedShiftPic();

  // Patch a single item row
  const updateRow = (id, patch) => {
    if (past) return;
    setAssignments(a => ({
      ...a,
      [dateKey]: { ...(a[dateKey] || {}), [id]: { ...(a[dateKey]?.[id] || {}), ...patch } },
    }));
  };

  // Drop from tonight = set target to 0
  const removeFromTonight = (id) => {
    if (past) return;
    updateRow(id, { target: 0 });
    if (selected === id) setSelected(null);
  };

  // Re-add (set a sensible default target)
  const addToTonight = (id) => {
    if (past) return;
    const sample = (window.SAMPLE_PREP_ITEMS || []).find(s => s.id === id);
    const cat = getCatalog().find(c => c.id === id);
    const t = sample?.target ?? (cat?.category === 'Cleaning & Fixing' ? 0 : 1);
    updateRow(id, { target: t || 1 });
  };

  const dupYesterday = () => {
    const y = new Date(date); y.setDate(y.getDate() - 1);
    const yKey = isoDate(y);
    if (assignments[yKey]) {
      setAssignments(a => ({ ...a, [dateKey]: JSON.parse(JSON.stringify(assignments[yKey])) }));
    }
    if (shiftPicByDate[yKey]) {
      setShiftPicByDate(p => ({ ...p, [dateKey]: [...shiftPicByDate[yKey]] }));
    }
    setSavedToast(true);
  };

  const resetToDefaults = () => {
    if (!confirm('Reset all targets, priorities and comments back to catalog defaults? Shift PIC stays.')) return;
    setAssignments(a => ({ ...a, [dateKey]: seedAssignment() }));
  };

  // Build today's list = catalog items with target > 0.
  const catalog = getCatalog().filter(c => !c.archived);
  const rows = catalog.map(c => ({
    id: c.id, name: c.name, category: c.category, unit: c.unit || '',
    target:   tplRows[c.id]?.target ?? 0,
    priority: tplRows[c.id]?.priority ?? 'secondary',
    comment:  tplRows[c.id]?.comment ?? '',
  }));

  const tonight = rows.filter(r => r.target > 0);
  const visibleRows = tonight;

  const itemCount    = tonight.length;
  const primaryCount = tonight.filter(r => r.priority === 'primary').length;

  return (
    <div className="portal-page-wide" style={{ maxWidth: 1280 }}>
      <div className="portal-page-header" style={{ marginBottom: 16 }}>
        <div>
          <h1 className="portal-page-title">Prep Assignment</h1>
          <div className="portal-page-subtitle">
            {past ? 'Read-only — historical record from this day.' :
             future ? 'Draft — items will appear on the iPad app on this date.' :
             'Set today\'s targets, priority and comments. Set target to 0 to drop an item from today. The iPad app reads from here in real time.'}
          </div>
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          <PBtn variant="primary" icon="check" onClick={() => setSavedToast(true)} disabled={past}>Publish to iPad</PBtn>
        </div>
      </div>

      {/* Combined header card: date + stats on top, shift PIC roster on bottom */}
      <div style={{
        marginBottom: 14,
        background: 'var(--bg-surface)', border: '1px solid var(--border-2)',
        borderRadius: 12,
        overflow: 'hidden',
      }}>
        {/* Top row: date + stats */}
        <div style={{
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          padding: '12px 16px',
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
            <PDatePicker value={date} onChange={setDate} />
            {past && (
              <span style={{
                display: 'inline-flex', alignItems: 'center', gap: 5,
                padding: '3px 9px', borderRadius: 999,
                background: 'var(--bg-sunken)', color: 'var(--fg-2)',
                fontSize: 11, fontWeight: 500, letterSpacing: '0.04em', textTransform: 'uppercase',
              }}>
                <PIcon name="lock" size={11} /> Read-only
              </span>
            )}
            {future && (
              <span style={{
                display: 'inline-flex', alignItems: 'center', gap: 5,
                padding: '3px 9px', borderRadius: 999,
                background: '#FFFBEB', color: '#92400E',
                fontSize: 11, fontWeight: 500, letterSpacing: '0.04em', textTransform: 'uppercase',
              }}>Draft — not yet active</span>
            )}
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 24, fontSize: 12.5 }}>
            <Summary label="Today" value={itemCount} />
            <Divider />
            <Summary label="Primary" value={primaryCount} />
            <Divider />
            <Summary label="Last published" value={past ? '—' : '11 min ago'} muted />
          </div>
        </div>

        {/* Divider */}
        <div style={{ height: 1, background: 'var(--border-2)' }} />

        {/* Bottom row: shift PIC roster */}
        <ShiftPicRow
          ids={shiftPic}
          past={past}
          onEdit={() => setPicPickerOpen(true)}
        />
      </div>

      {/* Filter row */}
      <div style={{
        display: 'flex', alignItems: 'center', gap: 12,
        margin: '14px 0 10px', padding: '0 4px',
      }}>
        <div style={{ flex: 1 }} />
        <button onClick={resetToDefaults} disabled={past} style={{
          fontSize: 12, color: 'var(--fg-3)',
          padding: '4px 10px', borderRadius: 7,
          opacity: past ? 0.4 : 1,
        }}>Reset to catalog defaults</button>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: selected ? '1fr 340px' : '1fr', gap: 20 }}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          {CATEGORIES.map(cat => {
            const catRows = visibleRows.filter(r => r.category === cat);
            if (catRows.length === 0) return null;
            return (
              <CategorySection
                key={cat}
                category={cat}
                rows={catRows}
                past={past}
                selected={selected}
                onSelect={setSelected}
                onUpdate={updateRow}
                onRemove={removeFromTonight}
                onAdd={addToTonight}
              />
            );
          })}

          {visibleRows.length === 0 && (
            <div className="portal-card" style={{ padding: 40, textAlign: 'center', color: 'var(--fg-3)', fontSize: 13 }}>
              No items assigned today. Open the <a href="#" onClick={e => { e.preventDefault(); window.location.hash = 'prep-catalog'; }} style={{ color: 'var(--fg-1)', fontWeight: 500 }}>Catalog</a> and bump targets above 0 to add items.
            </div>
          )}

          <div style={{ fontSize: 12, color: 'var(--fg-3)', textAlign: 'right', padding: '4px 4px' }}>
            Edits autosave · <span className="kbd">⌘</span> <span className="kbd">S</span> publish
          </div>
        </div>

        {selected && (() => {
          const row = rows.find(r => r.id === selected);
          if (!row) return null;
          return (
            <DetailPanel
              row={row}
              past={past}
              onClose={() => setSelected(null)}
              onUpdate={(patch) => updateRow(row.id, patch)}
              onRemove={() => removeFromTonight(row.id)}
            />
          );
        })()}
      </div>

      {/* Modals */}
      <ShiftPicPickerModal
        open={picPickerOpen}
        onClose={() => setPicPickerOpen(false)}
        currentIds={shiftPic}
        onSave={(ids) => {
          setShiftPicByDate(p => ({ ...p, [dateKey]: ids }));
          setPicPickerOpen(false);
        }}
      />

      <PToast message="Saved" open={savedToast} onClose={() => setSavedToast(false)} />
    </div>
  );
};

// ------------------------------------------------------------------
// Shift PIC row — single roster, inline inside the header card
// ------------------------------------------------------------------
const ShiftPicRow = ({ ids, past, onEdit }) => {
  const staff = ids.map(id => window.SAMPLE_STAFF.find(s => s.id === id)).filter(Boolean);
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 16,
      padding: '10px 16px',
      background: 'var(--bg-sunken)',
    }}>
      <div style={{
        fontSize: 10.5, fontWeight: 500, letterSpacing: '0.06em',
        textTransform: 'uppercase', color: 'var(--fg-3)',
        flexShrink: 0,
      }}>
        Shift PIC
      </div>
      <div style={{ flex: 1, minWidth: 0, display: 'flex', flexWrap: 'wrap', gap: 6, alignItems: 'center' }}>
        {staff.length === 0 ? (
          <span style={{ fontSize: 12.5, color: 'var(--fg-3)' }}>Unassigned — pick a crew before publishing</span>
        ) : staff.map(s => (
          <span key={s.id} style={{
            display: 'inline-flex', alignItems: 'center', gap: 6,
            fontSize: 12.5, fontWeight: 500, color: 'var(--fg-1)',
            padding: '3px 10px 3px 3px',
            background: 'var(--bg-card)', borderRadius: 999,
            border: '1px solid var(--border-2)',
          }}>
            <PAvatar staff={s} size={20} />
            {s.name}
          </span>
        ))}
      </div>
      <button
        onClick={onEdit}
        disabled={past}
        title="Edit roster"
        style={{
          width: 28, height: 28, borderRadius: 7,
          border: '1px solid var(--border-2)',
          background: 'var(--bg-card)',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          cursor: past ? 'default' : 'pointer',
          opacity: past ? 0.5 : 1,
          flexShrink: 0,
        }}
      >
        <PIcon name="edit" size={13} color="var(--fg-2)" />
      </button>
    </div>
  );
};

const Summary = ({ label, value, muted }) => (
  <div style={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
    <span style={{ fontSize: 10.5, fontWeight: 500, letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--fg-3)' }}>{label}</span>
    <span style={{ fontSize: 14, fontWeight: 600, color: muted ? 'var(--fg-2)' : 'var(--fg-1)', fontVariantNumeric: 'tabular-nums', letterSpacing: '-0.005em' }}>{value}</span>
  </div>
);

const Divider = () => <div style={{ width: 1, height: 24, background: 'var(--border-1)' }} />;

// ------------------------------------------------------------------
// Category section — rows of catalog items
// ------------------------------------------------------------------
const CategorySection = ({ category, rows, past, selected, onSelect, onUpdate, onRemove, onAdd }) => {
  const [collapsed, setCollapsed] = useState(false);
  const onTonight = rows.filter(r => r.target > 0).length;
  const primaryCount = rows.filter(r => r.priority === 'primary' && r.target > 0).length;

  return (
    <div className="portal-card">
      <div className="portal-card-header" style={{ cursor: 'pointer' }} onClick={() => setCollapsed(c => !c)}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <PIcon name={collapsed ? 'chevronR' : 'chevronD'} size={13} color="var(--fg-3)" />
          <div className="portal-card-title">{category}</div>
          <span style={{ fontSize: 12, color: 'var(--fg-3)' }}>
            {onTonight} · {primaryCount} primary
          </span>
        </div>
      </div>

      {!collapsed && (
        <table className="portal-table">
          <thead>
            <tr>
              <th>Item</th>
              <th style={{ width: 140 }}>Target</th>
              <th style={{ width: 110 }}>Priority</th>
              <th style={{ width: 240 }}>Comment</th>
              <th style={{ width: 70 }}></th>
            </tr>
          </thead>
          <tbody>
            {rows.map(row => (
              <PrepRow
                key={row.id}
                row={row}
                isSelected={selected === row.id}
                past={past}
                onSelect={() => onSelect(row.id)}
                onUpdate={(patch) => onUpdate(row.id, patch)}
                onRemove={() => onRemove(row.id)}
                onAdd={() => onAdd(row.id)}
              />
            ))}
          </tbody>
        </table>
      )}
    </div>
  );
};

// ------------------------------------------------------------------
// Single editable row
// Name, category and unit are catalog-managed; not editable here.
// ------------------------------------------------------------------
const PrepRow = ({ row, isSelected, past, onSelect, onUpdate, onRemove, onAdd }) => {
  const offTonight = row.target === 0;
  return (
    <tr style={{
      background: isSelected ? 'rgba(0,0,0,0.025)' : undefined,
      opacity: offTonight ? 0.55 : 1,
    }}>
      <td>
        <span style={{
          fontSize: 13, fontWeight: 500,
          color: 'var(--fg-1)',
          textDecoration: offTonight ? 'line-through' : 'none',
        }}>{row.name}</span>
      </td>
      <td>
        <PStepper value={row.target} onChange={v => onUpdate({ target: v })} max={50} />
      </td>
      <td>
        <button
          onClick={() => !past && !offTonight && onUpdate({ priority: row.priority === 'primary' ? 'secondary' : 'primary' })}
          disabled={past || offTonight}
          style={{ padding: 0, opacity: (past || offTonight) ? 0.6 : 1 }}
        >
          <PPriorityPill priority={row.priority} />
        </button>
      </td>
      <td>
        <input
          className="portal-input is-ghost"
          placeholder={past || offTonight ? '' : 'Comment for today…'}
          value={row.comment || ''}
          disabled={past || offTonight}
          onChange={e => onUpdate({ comment: e.target.value })}
          style={{ height: 30, fontSize: 12.5, color: row.comment ? 'var(--fg-1)' : 'var(--fg-3)' }}
        />
      </td>
      <td>
        <div className="row-actions">
          <button title="Details" onClick={onSelect}><PIcon name="eye" size={14} /></button>
          {!past && (
            offTonight
              ? <button title="Add to today" onClick={onAdd}><PIcon name="plus" size={14} /></button>
              : <button title="Drop from today" onClick={onRemove}><PIcon name="trash" size={14} /></button>
          )}
        </div>
      </td>
    </tr>
  );
};

// ------------------------------------------------------------------
// Detail panel (right rail)
// ------------------------------------------------------------------
const DetailPanel = ({ row, past, onClose, onUpdate, onRemove }) => {
  const offTonight = row.target === 0;
  return (
    <div style={{ position: 'sticky', top: 80, alignSelf: 'start' }}>
      <div className="portal-card" style={{ padding: 0 }}>
        <div style={{ padding: '14px 18px', borderBottom: '1px solid var(--border-2)', display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12 }}>
          <div>
            <PCategoryChip category={row.category} />
            <div style={{ fontSize: 17, fontWeight: 600, letterSpacing: '-0.015em', marginTop: 8 }}>{row.name}</div>
            <div style={{ fontSize: 12, color: 'var(--fg-2)', marginTop: 2 }}>
              {offTonight ? 'Not on today' : `${row.target} target · `}<PPriorityPill priority={row.priority} />
            </div>
          </div>
          <button onClick={onClose} style={{ width: 26, height: 26, borderRadius: 6, color: 'var(--fg-3)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
            <PIcon name="x" size={14} />
          </button>
        </div>

        <div style={{ padding: '14px 18px', display: 'flex', flexDirection: 'column', gap: 14 }}>
          <Field label="Target" hint="Set to 0 to drop this item from today.">
            <PStepper value={row.target} onChange={v => onUpdate({ target: v })} max={50} />
          </Field>

          <Field label="Priority">
            <div style={{ display: 'flex', gap: 6 }}>
              {['primary', 'secondary'].map(p => (
                <button key={p} disabled={past || offTonight}
                  onClick={() => onUpdate({ priority: p })}
                  style={{
                    padding: '6px 12px', borderRadius: 999,
                    fontSize: 12, fontWeight: 500,
                    background: row.priority === p ? 'var(--fg-1)' : 'var(--bg-sunken)',
                    color: row.priority === p ? '#fff' : 'var(--fg-2)',
                    opacity: (past || offTonight) ? 0.5 : 1,
                    textTransform: 'capitalize',
                  }}>{p}</button>
              ))}
            </div>
          </Field>

          <Field label="Comment for staff" hint="Shown on the iPad item card. Overrides catalog/default for today.">
            <textarea
              className="portal-input"
              placeholder={past || offTonight ? '' : 'e.g. "Use yesterday\'s leftovers first"'}
              value={row.comment || ''}
              disabled={past || offTonight}
              onChange={e => onUpdate({ comment: e.target.value })}
              rows={3}
            />
          </Field>

          {!past && !offTonight && (
            <button onClick={onRemove} style={{
              fontSize: 12.5, color: '#8B2A1A',
              padding: '8px 10px', borderRadius: 8,
              background: '#FEF2F2',
              fontWeight: 500,
              display: 'inline-flex', alignItems: 'center', gap: 6,
            }}>
              <PIcon name="trash" size={13} color="#8B2A1A" /> Drop from today
            </button>
          )}

          <div style={{ paddingTop: 12, borderTop: '1px solid var(--border-2)' }}>
            <div style={{ fontSize: 11, fontWeight: 500, letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--fg-3)', marginBottom: 8 }}>
              Recent History
            </div>
            <div style={{ fontSize: 12, color: 'var(--fg-2)', lineHeight: 1.6 }}>
              <div>Yesterday — 4 prepped by Mei, Jorge</div>
              <div>2 days ago — 3 prepped by Mei</div>
              <div>3 days ago — 4 prepped by Jorge</div>
            </div>
            <a href="#" style={{ fontSize: 12, color: 'var(--fg-1)', fontWeight: 500, marginTop: 8, display: 'inline-block' }}>View full log →</a>
          </div>
        </div>
      </div>
    </div>
  );
};

const Field = ({ label, hint, children }) => (
  <div>
    <div style={{ fontSize: 11.5, fontWeight: 500, letterSpacing: '0.04em', textTransform: 'uppercase', color: 'var(--fg-3)', marginBottom: 6 }}>{label}</div>
    {children}
    {hint && <div style={{ fontSize: 11.5, color: 'var(--fg-3)', marginTop: 5 }}>{hint}</div>}
  </div>
);

// ------------------------------------------------------------------
// Shift PIC picker — multi-select roster for tonight's prep crew
// ------------------------------------------------------------------
const ShiftPicPickerModal = ({ open, onClose, currentIds, onSave }) => {
  const [picked, setPicked] = useState(currentIds || []);
  useEffect(() => { if (open) setPicked(currentIds || []); }, [open, currentIds]);
  if (!open) return null;
  const toggle = (id) => setPicked(p => p.includes(id) ? p.filter(x => x !== id) : [...p, id]);

  return (
    <PModal open onClose={onClose} title="Today's prep crew" width={460}>
      <div style={{ padding: '14px 18px 4px', fontSize: 12, color: 'var(--fg-2)' }}>
        Pick everyone working prep today. Anyone on this list can log work against any item on the iPad.
      </div>
      <div style={{ padding: 14, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6 }}>
        {window.SAMPLE_STAFF.map(s => {
          const on = picked.includes(s.id);
          return (
            <button key={s.id} onClick={() => toggle(s.id)} style={{
              display: 'flex', alignItems: 'center', gap: 10,
              padding: '8px 12px',
              background: on ? 'var(--fg-1)' : 'var(--bg-sunken)',
              borderRadius: 8,
              textAlign: 'left',
            }}>
              <div style={{
                width: 16, height: 16, borderRadius: 4,
                background: on ? '#FFFFFF' : 'transparent',
                border: on ? 'none' : '1.5px solid var(--border-2)',
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
              }}>
                {on && <PIcon name="check" size={11} color="var(--fg-1)" strokeWidth={2.5} />}
              </div>
              <PAvatar staff={s} size={22} />
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 13, fontWeight: 500, color: on ? '#fff' : 'var(--fg-1)' }}>{s.name}</div>
              </div>
            </button>
          );
        })}
      </div>
      <div style={{ padding: '12px 18px', display: 'flex', justifyContent: 'flex-end', gap: 8, borderTop: '1px solid var(--border-2)' }}>
        <PBtn variant="secondary" onClick={onClose}>Cancel</PBtn>
        <PBtn variant="primary" onClick={() => onSave(picked)}>
          Save{picked.length > 0 && ` (${picked.length})`}
        </PBtn>
      </div>
    </PModal>
  );
};

window.PrepEditor = PrepEditor;
