// ChecklistTemplate.jsx — admin editor for Daily Checklist groups + items.
//
// Schema mirror (see migrations):
//   checklist_groups: id, name, trigger_time (HH:MM:SS), weekdays int[],
//                     reminder_minutes, sort_order, archived
//   checklist_items:  id, group_id, name, sort_order, archived
// Groups own a fire time + weekday mask + reminder cadence — when that
// time arrives the iPad pops a full-screen reminder. Items are plain
// text tasks belonging to a group.

const WEEKDAY_LABELS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];

const checklistGroupFromRow = (r) => ({
  id: r.id, name: r.name,
  triggerTime: (r.trigger_time || '08:30:00').slice(0, 5),
  weekdays: r.weekdays || [0, 1, 2, 3, 4, 5, 6],
  // 0 means "no re-reminder after the initial pop" — keep that
  // sentinel by checking the source value explicitly rather than the
  // `|| 15` fallback (which would treat 0 as missing).
  reminderMinutes: r.reminder_minutes == null ? 15 : Number(r.reminder_minutes),
  sortOrder: Number(r.sort_order) || 0,
  archived: !!r.archived,
});
const checklistGroupToRow = (o) => ({
  id: o.id, name: o.name,
  // Postgres `time` accepts HH:MM, expands to HH:MM:00.
  trigger_time: o.triggerTime || '08:30',
  weekdays: o.weekdays || [0, 1, 2, 3, 4, 5, 6],
  reminder_minutes: o.reminderMinutes == null ? 15 : Math.max(0, Number(o.reminderMinutes)),
  sort_order: Number(o.sortOrder) || 0,
  archived: !!o.archived,
  updated_at: new Date().toISOString(),
});

const checklistItemFromRow = (r) => ({
  id: r.id, groupId: r.group_id, name: r.name,
  sortOrder: Number(r.sort_order) || 0, archived: !!r.archived,
});
const checklistItemToRow = (o) => ({
  id: o.id, group_id: o.groupId, name: o.name,
  sort_order: Number(o.sortOrder) || 0, archived: !!o.archived,
  updated_at: new Date().toISOString(),
});

const ChecklistTemplate = () => {
  const [groups, setGroups] = window.useSupaList('checklist_groups', {
    fromRow: checklistGroupFromRow,
    toRow: checklistGroupToRow,
    initial: () => window.SAMPLE_CHECKLIST_GROUPS || [],
  });
  const [items, setItems] = window.useSupaList('checklist_items', {
    fromRow: checklistItemFromRow,
    toRow: checklistItemToRow,
    initial: () => window.SAMPLE_CHECKLIST_ITEMS || [],
  });

  const [editingGroup, setEditingGroup] = useState(null); // group object or 'new'
  const [editingItem, setEditingItem]   = useState(null); // item object or { groupId, _new: true }
  const [toast, setToast] = useState('');
  // Segmented view — 'everyday' (default) or 'specific'. Two sections
  // stacked was visually noisy; toggle keeps the page focused.
  const [segment, setSegment] = useState('everyday');

  // Split groups into "every day" vs "specific days". Every day is the
  // bulk of the template; specific-day groups (e.g. Tuesday-only fryer
  // oil change) get their own section so admin sees them at a glance.
  // Within each segment, sort by trigger time so the admin can scan
  // the schedule top-down chronologically.
  const activeGroups = groups.filter(g => !g.archived);
  const everydayGroups = activeGroups
    .filter(g => (g.weekdays || []).length === 7)
    .sort((a, b) => a.triggerTime.localeCompare(b.triggerTime));
  const specialGroups = activeGroups
    .filter(g => (g.weekdays || []).length < 7)
    .sort((a, b) => a.triggerTime.localeCompare(b.triggerTime));

  const itemsByGroup = useMemo(() => {
    const m = {};
    items.filter(i => !i.archived).forEach(i => {
      (m[i.groupId] = m[i.groupId] || []).push(i);
    });
    Object.values(m).forEach(arr => arr.sort((a, b) => a.sortOrder - b.sortOrder));
    return m;
  }, [items]);

  const saveGroup = (draft) => {
    if (!draft.name.trim()) return;
    if (draft.id && groups.some(g => g.id === draft.id)) {
      setGroups(gs => gs.map(g => g.id === draft.id ? { ...draft, name: draft.name.trim() } : g));
      setToast('Group updated');
    } else {
      const id = 'cg-' + Date.now().toString(36);
      const maxSort = groups.reduce((m, g) => Math.max(m, g.sortOrder), 0);
      setGroups(gs => [...gs, {
        ...draft, id,
        name: draft.name.trim(),
        sortOrder: maxSort + 10,
        archived: false,
      }]);
      setToast('Group added');
    }
    setEditingGroup(null);
  };

  const deleteGroup = (group) => {
    const itemCount = itemsByGroup[group.id]?.length || 0;
    const warn = itemCount > 0
      ? `Delete "${group.name}" and its ${itemCount} item${itemCount === 1 ? '' : 's'}? Past completion log entries for these items stay readable in the log.`
      : `Delete "${group.name}"?`;
    if (!confirm(warn)) return;
    // Items cascade via the FK ON DELETE CASCADE, so we only need to drop
    // them from local state for the immediate UI update.
    setItems(is => is.filter(i => i.groupId !== group.id));
    setGroups(gs => gs.filter(g => g.id !== group.id));
    setToast('Group deleted');
  };

  const saveItem = (draft) => {
    if (!draft.name.trim()) return;
    if (draft.id && items.some(i => i.id === draft.id)) {
      setItems(is => is.map(i => i.id === draft.id ? { ...draft, name: draft.name.trim() } : i));
      setToast('Item updated');
    } else {
      const id = 'ci-' + Date.now().toString(36);
      const groupItems = itemsByGroup[draft.groupId] || [];
      const maxSort = groupItems.reduce((m, i) => Math.max(m, i.sortOrder), 0);
      setItems(is => [...is, {
        ...draft, id,
        name: draft.name.trim(),
        sortOrder: maxSort + 10,
        archived: false,
      }]);
      setToast('Item added');
    }
    setEditingItem(null);
  };

  const deleteItem = (item) => {
    if (!confirm(`Delete "${item.name}"? Past completion log entries for this item stay readable in the log.`)) return;
    setItems(is => is.filter(i => i.id !== item.id));
    setToast('Item deleted');
  };

  const activeGroupCount = everydayGroups.length + specialGroups.length;
  const activeItemCount = items.filter(i => !i.archived).length;

  return (
    <div className="portal-page-wide" style={{ maxWidth: 1080 }}>
      <div className="portal-page-header">
        <div>
          <h1 className="portal-page-title">Checklist Template</h1>
          <div className="portal-page-subtitle">
            Groups are the recurring blocks of tasks — each has a fire
            time, a set of weekdays, and a reminder cadence. When the time
            comes, the iPad pops a full-screen reminder; if items remain
            incomplete, it pops again every N minutes.
          </div>
        </div>
        <PBtn variant="primary" icon="plus" onClick={() => setEditingGroup('new')}>Add group</PBtn>
      </div>

      <div style={{
        marginBottom: 14, padding: 12,
        background: 'var(--bg-sunken)', borderRadius: 10,
        fontSize: 12.5, color: 'var(--fg-2)',
      }}>
        <strong style={{ color: 'var(--fg-1)' }}>{activeGroupCount} group{activeGroupCount === 1 ? '' : 's'}</strong>
        {' · '}
        <strong style={{ color: 'var(--fg-1)' }}>{activeItemCount} item{activeItemCount === 1 ? '' : 's'}</strong> active.
        The template repeats every day per its weekday rules — there's no per-day publish step.
      </div>

      {activeGroupCount === 0 ? (
        <div className="portal-card" style={{ padding: 48, textAlign: 'center', color: 'var(--fg-3)' }}>
          <div style={{ fontSize: 14, color: 'var(--fg-2)', marginBottom: 14 }}>
            No checklist groups yet.
          </div>
          <PBtn variant="primary" icon="plus" onClick={() => setEditingGroup('new')}>Add your first group</PBtn>
        </div>
      ) : (
        <>
          <SegmentSwitch
            value={segment}
            onChange={setSegment}
            options={[
              { id: 'everyday', label: 'Every day',      count: everydayGroups.length, hint: 'Repeats Sun–Sat, sorted by fire time.' },
              { id: 'specific', label: 'Specific days',  count: specialGroups.length,  hint: 'Fires only on the days you set (e.g. fryer oil change every Tuesday).' },
            ]}
          />

          {segment === 'everyday' ? (
            everydayGroups.length === 0 ? (
              <SegmentEmpty hint="No every-day groups yet. Add one or check the Specific days tab." />
            ) : everydayGroups.map(group => (
              <GroupCard
                key={group.id}
                group={group}
                items={itemsByGroup[group.id] || []}
                onEditGroup={() => setEditingGroup(group)}
                onDeleteGroup={() => deleteGroup(group)}
                onAddItem={() => setEditingItem({ groupId: group.id, _new: true })}
                onEditItem={(item) => setEditingItem(item)}
                onDeleteItem={(item) => deleteItem(item)}
              />
            ))
          ) : (
            specialGroups.length === 0 ? (
              <SegmentEmpty hint="No specific-day groups yet. Add a group and pick its days." />
            ) : specialGroups.map(group => (
              <GroupCard
                key={group.id}
                group={group}
                items={itemsByGroup[group.id] || []}
                onEditGroup={() => setEditingGroup(group)}
                onDeleteGroup={() => deleteGroup(group)}
                onAddItem={() => setEditingItem({ groupId: group.id, _new: true })}
                onEditItem={(item) => setEditingItem(item)}
                onDeleteItem={(item) => deleteItem(item)}
              />
            ))
          )}
        </>
      )}

      {editingGroup && (
        <GroupEditor
          initial={editingGroup === 'new' ? null : editingGroup}
          onClose={() => setEditingGroup(null)}
          onSave={saveGroup}
        />
      )}
      {editingItem && (
        <ItemEditor
          initial={editingItem._new ? null : editingItem}
          groupId={editingItem.groupId}
          onClose={() => setEditingItem(null)}
          onSave={saveItem}
        />
      )}

      <PToast message={toast} open={!!toast} onClose={() => setToast('')} />
    </div>
  );
};

// ------------------------------------------------------------------
// SegmentSwitch — pill-style toggle for the two template views. Each
// option shows its count so the admin sees at a glance which segment
// has groups even when the off-segment is hidden. A small hint line
// below the toggle clarifies what the active segment means.
const SegmentSwitch = ({ value, onChange, options }) => {
  const active = options.find(o => o.id === value) || options[0];
  return (
    <div style={{ marginBottom: 16 }}>
      <div style={{
        display: 'inline-flex', background: 'var(--bg-sunken)',
        borderRadius: 10, padding: 3,
      }}>
        {options.map(opt => {
          const on = value === opt.id;
          return (
            <button
              key={opt.id}
              onClick={() => onChange(opt.id)}
              style={{
                display: 'inline-flex', alignItems: 'center', gap: 6,
                padding: '6px 14px',
                background: on ? '#FFFFFF' : 'transparent',
                border: 'none', borderRadius: 7,
                fontSize: 12.5, fontWeight: on ? 600 : 500,
                color: on ? 'var(--fg-1)' : 'var(--fg-2)',
                cursor: 'pointer',
                boxShadow: on ? '0 1px 2px rgba(0,0,0,0.08)' : 'none',
              }}
            >
              {opt.label}
              <span style={{
                fontSize: 10.5, fontWeight: 600,
                padding: '1px 7px', borderRadius: 999,
                background: on ? 'var(--bg-sunken)' : 'rgba(0,0,0,0.06)',
                color: 'var(--fg-2)', fontFamily: 'var(--font-num)',
              }}>{opt.count}</span>
            </button>
          );
        })}
      </div>
      <div style={{ fontSize: 11.5, color: 'var(--fg-3)', marginTop: 8 }}>
        {active.hint}
      </div>
    </div>
  );
};

const SegmentEmpty = ({ hint }) => (
  <div className="portal-card" style={{ padding: 40, textAlign: 'center', color: 'var(--fg-3)', fontSize: 13 }}>
    {hint}
  </div>
);

// Single group card with its items inline. The toolbar shows the
// scheduling summary (time + weekday chips + reminder cadence) so the
// owner can read it without opening the editor.
// ------------------------------------------------------------------
const GroupCard = ({ group, items, onEditGroup, onDeleteGroup, onAddItem, onEditItem, onDeleteItem }) => {
  const dayChips = group.weekdays.length === 7
    ? <span style={{ fontSize: 12, color: 'var(--fg-2)' }}>Every day</span>
    : (
      <div style={{ display: 'inline-flex', gap: 3 }}>
        {WEEKDAY_LABELS.map((label, i) => {
          const on = group.weekdays.includes(i);
          return (
            <span key={i} style={{
              fontSize: 10.5, fontWeight: on ? 600 : 400,
              padding: '2px 6px', borderRadius: 6,
              background: on ? 'var(--fg-1)' : 'var(--bg-sunken)',
              color: on ? '#fff' : 'var(--fg-3)',
              fontFamily: 'var(--font-num)',
            }}>{label}</span>
          );
        })}
      </div>
    );

  const timeLabel = formatTime12(group.triggerTime);

  return (
    <div className="portal-card" style={{ padding: 0, marginBottom: 14 }}>
      {/* Whole header row is clickable to edit the group. Action buttons
          are nested inside but stop event propagation so trash doesn't
          double-fire as "edit then delete". row-actions opacity is
          forced visible — the default CSS rule only un-hides on tr:hover,
          and this card isn't a table row, so without the override the
          icons stayed permanently invisible. */}
      <div
        onClick={onEditGroup}
        title="Edit group"
        className="portal-card-header"
        style={{ alignItems: 'flex-start', cursor: 'pointer' }}
      >
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 4 }}>
            <div className="portal-card-title" style={{ fontSize: 15 }}>{group.name}</div>
            <span style={{
              fontSize: 11, fontWeight: 500,
              padding: '2px 8px', borderRadius: 999,
              background: 'var(--bg-sunken)', color: 'var(--fg-2)',
              fontFamily: 'var(--font-num)', letterSpacing: '0.02em',
            }}>{timeLabel}</span>
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 12, fontSize: 12, color: 'var(--fg-3)' }}>
            {dayChips}
            <span style={{ color: 'var(--border-1)' }}>·</span>
            <span>
              {group.reminderMinutes > 0
                ? `Remind every ${group.reminderMinutes}m if incomplete`
                : 'No re-reminder'}
            </span>
          </div>
        </div>
        <div className="row-actions" style={{ opacity: 1 }}>
          <button onClick={(e) => { e.stopPropagation(); onEditGroup(); }} title="Edit group"><PIcon name="edit" size={13} /></button>
          <button onClick={(e) => { e.stopPropagation(); onDeleteGroup(); }} title="Delete group"><PIcon name="trash" size={13} /></button>
        </div>
      </div>

      <div style={{ padding: '4px 16px 12px' }}>
        {items.length === 0 ? (
          <div style={{ padding: '14px 4px', fontSize: 12.5, color: 'var(--fg-3)' }}>
            No items yet. Add one →
          </div>
        ) : items.map(item => (
          <div
            key={item.id}
            onClick={() => onEditItem(item)}
            title="Edit item"
            style={{
              display: 'flex', alignItems: 'center', gap: 10,
              padding: '8px 4px',
              borderBottom: '1px solid var(--border-2)',
              cursor: 'pointer',
            }}
          >
            <div style={{
              width: 16, height: 16, borderRadius: 4,
              border: '1.5px solid var(--border-1)',
              flexShrink: 0,
            }} />
            <div style={{ flex: 1, fontSize: 13, color: 'var(--fg-1)' }}>{item.name}</div>
            <div className="row-actions" style={{ opacity: 1 }}>
              <button onClick={(e) => { e.stopPropagation(); onEditItem(item); }} title="Edit"><PIcon name="edit" size={13} /></button>
              <button onClick={(e) => { e.stopPropagation(); onDeleteItem(item); }} title="Delete"><PIcon name="trash" size={13} /></button>
            </div>
          </div>
        ))}
        <button onClick={onAddItem} style={{
          marginTop: 10,
          fontSize: 12.5, color: 'var(--fg-2)',
          padding: '6px 10px', borderRadius: 7,
          background: 'transparent',
          border: '1px dashed var(--border-1)',
          width: '100%', textAlign: 'left',
        }}>
          <PIcon name="plus" size={12} /> Add item
        </button>
      </div>
    </div>
  );
};

// ------------------------------------------------------------------
// Group editor modal: name, time, weekdays, reminder minutes
// ------------------------------------------------------------------
const GroupEditor = ({ initial, onClose, onSave }) => {
  const [draft, setDraft] = useState(() => initial || {
    id: null, name: '', triggerTime: '08:30',
    weekdays: [0, 1, 2, 3, 4, 5, 6], reminderMinutes: 15,
  });
  const toggleDay = (i) => setDraft(d => ({
    ...d,
    weekdays: d.weekdays.includes(i)
      ? d.weekdays.filter(x => x !== i)
      : [...d.weekdays, i].sort((a, b) => a - b),
  }));

  return (
    <PModal open onClose={onClose} title={initial ? 'Edit group' : 'New group'} width={520} footer={
      <>
        <PBtn variant="secondary" onClick={onClose}>Cancel</PBtn>
        <PBtn variant="primary" onClick={() => onSave(draft)} disabled={!draft.name.trim() || draft.weekdays.length === 0}>
          {initial ? 'Save changes' : 'Add group'}
        </PBtn>
      </>
    }>
      <div style={{ padding: '14px 18px', display: 'flex', flexDirection: 'column', gap: 16 }}>
        <PField label="Name">
          <input
            className="portal-input"
            value={draft.name}
            placeholder="e.g. Opening prep, Closing checks"
            onChange={e => setDraft({ ...draft, name: e.target.value })}
            style={{ height: 36 }}
            autoFocus
          />
        </PField>

        <PField label="Time of day" hint="When the iPad first pops the reminder.">
          <input
            type="time"
            className="portal-input"
            value={draft.triggerTime}
            onChange={e => setDraft({ ...draft, triggerTime: e.target.value })}
            style={{ height: 36, width: 140 }}
          />
        </PField>

        <PField label="Days" hint="Only fire the reminder on these days.">
          <div style={{ display: 'flex', gap: 6 }}>
            {WEEKDAY_LABELS.map((label, i) => {
              const on = draft.weekdays.includes(i);
              return (
                <button
                  key={i}
                  type="button"
                  onClick={() => toggleDay(i)}
                  style={{
                    padding: '6px 12px', borderRadius: 999,
                    background: on ? 'var(--fg-1)' : 'var(--bg-sunken)',
                    color: on ? '#fff' : 'var(--fg-2)',
                    border: 'none', fontSize: 12.5, fontWeight: 500,
                    fontFamily: 'var(--font-num)',
                    cursor: 'pointer',
                  }}
                >{label}</button>
              );
            })}
          </div>
          <div style={{ display: 'flex', gap: 10, marginTop: 8 }}>
            <button type="button" onClick={() => setDraft({ ...draft, weekdays: [0, 1, 2, 3, 4, 5, 6] })} style={{ fontSize: 11.5, color: 'var(--fg-3)' }}>All days</button>
            <button type="button" onClick={() => setDraft({ ...draft, weekdays: [1, 2, 3, 4, 5] })} style={{ fontSize: 11.5, color: 'var(--fg-3)' }}>Weekdays</button>
            <button type="button" onClick={() => setDraft({ ...draft, weekdays: [0, 6] })} style={{ fontSize: 11.5, color: 'var(--fg-3)' }}>Weekends</button>
          </div>
        </PField>

        <PField
          label="Reminder cadence"
          hint={draft.reminderMinutes > 0
            ? 'If items remain unchecked after the initial pop, re-fire every N minutes.'
            : 'Fires once at the scheduled time and won\'t re-pop, even if items remain unchecked.'}
        >
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span style={{ fontSize: 13, color: 'var(--fg-2)' }}>Every</span>
            <input
              type="number" min={0} max={120}
              className="portal-input"
              disabled={draft.reminderMinutes === 0}
              value={draft.reminderMinutes === 0 ? '' : draft.reminderMinutes}
              placeholder={draft.reminderMinutes === 0 ? 'off' : ''}
              onChange={e => {
                const n = Number(e.target.value);
                setDraft({ ...draft, reminderMinutes: isFinite(n) && n > 0 ? n : 0 });
              }}
              style={{ height: 36, width: 80, textAlign: 'right', fontFamily: 'var(--font-num)' }}
            />
            <span style={{ fontSize: 13, color: 'var(--fg-2)' }}>minutes</span>
          </div>
          <div style={{ display: 'flex', gap: 6, marginTop: 8 }}>
            {[
              { v: 0,  label: 'Off' },
              { v: 5,  label: '5m' },
              { v: 10, label: '10m' },
              { v: 15, label: '15m' },
              { v: 30, label: '30m' },
              { v: 60, label: '60m' },
            ].map(opt => {
              const on = draft.reminderMinutes === opt.v;
              return (
                <button
                  key={opt.v}
                  type="button"
                  onClick={() => setDraft({ ...draft, reminderMinutes: opt.v })}
                  style={{
                    fontSize: 11.5,
                    color: on ? '#FFFFFF' : 'var(--fg-3)',
                    background: on ? 'var(--fg-1)' : 'var(--bg-sunken)',
                    padding: '4px 10px', borderRadius: 6,
                    border: 'none', cursor: 'pointer',
                  }}
                >{opt.label}</button>
              );
            })}
          </div>
        </PField>
      </div>
    </PModal>
  );
};

// ------------------------------------------------------------------
// Single-item editor (text-only)
// ------------------------------------------------------------------
const ItemEditor = ({ initial, groupId, onClose, onSave }) => {
  const [draft, setDraft] = useState(() => initial || { id: null, groupId, name: '' });
  return (
    <PModal open onClose={onClose} title={initial ? 'Edit item' : 'New item'} width={460} footer={
      <>
        <PBtn variant="secondary" onClick={onClose}>Cancel</PBtn>
        <PBtn variant="primary" onClick={() => onSave(draft)} disabled={!draft.name.trim()}>
          {initial ? 'Save' : 'Add item'}
        </PBtn>
      </>
    }>
      <div style={{ padding: '14px 18px' }}>
        <PField label="Task">
          <input
            className="portal-input"
            value={draft.name}
            placeholder="e.g. Wipe down line, Restock napkins"
            onChange={e => setDraft({ ...draft, name: e.target.value })}
            style={{ height: 36 }}
            autoFocus
          />
        </PField>
      </div>
    </PModal>
  );
};

// `Field` is the shared `PField` atom in portal-shared.jsx (see HANDBOOK §9).

// ------------------------------------------------------------------
// Helpers
// ------------------------------------------------------------------
function formatTime12(hhmm) {
  // hhmm = "HH:MM"
  if (!hhmm) return '';
  const [h, m] = hhmm.split(':').map(Number);
  const ampm = h >= 12 ? 'PM' : 'AM';
  const h12 = ((h + 11) % 12) + 1;
  return `${h12}:${String(m).padStart(2, '0')} ${ampm}`;
}

window.ChecklistTemplate = ChecklistTemplate;
window.formatChecklistTime12 = formatTime12;
window.CHECKLIST_WEEKDAY_LABELS = WEEKDAY_LABELS;
