/* Table view — sortable, inline-edit on every cell.
   v2: Project → Product (conditional on Category=Products),
       colored product tag, prominent stage chip, optional sub-product col.
*/

const { useState: useStateT, useMemo: useMemoT } = React;
const UT = window.mcalUtils;

function TableView({ events, options, today, openEvent, update, remove, selectedId }) {
  // Default to sorting by date, latest first.
  const [sort, setSort] = useStateT({ col: 'start', dir: 'desc' });
  const [expanded, setExpanded] = useStateT(() => new Set());

  const toggleExpand = id => {
    setExpanded(prev => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id); else next.add(id);
      return next;
    });
  };

  const sorted = useMemoT(() => {
    const list = [...events];
    list.sort((a, b) => {
      const aa = getCol(a, sort.col, options);
      const bb = getCol(b, sort.col, options);
      const c = aa < bb ? -1 : aa > bb ? 1 : 0;
      return sort.dir === 'asc' ? c : -c;
    });
    return list;
  }, [events, sort]);

  const headers = [
    { id: 'title',    label: 'Title' },
    { id: 'start',    label: 'Dates' },
    { id: 'stage',    label: 'Stage' },
    { id: 'channel',  label: 'Channel' },
    { id: 'owner',    label: 'Owner' },
    { id: 'category', label: 'Category' },
    { id: 'product',  label: 'Product' },
    { id: 'format',   label: 'Format' },
    { id: 'subtasks', label: 'Subs' },
    { id: 'notes',    label: 'Notes' },
    { id: 'url',      label: 'URL' },
    { id: 'media',    label: 'Media' },
  ];

  const onSort = id => {
    if (sort.col === id) setSort({ col: id, dir: sort.dir === 'asc' ? 'desc' : 'asc' });
    // Dates default to latest-first when first selected; other columns ascending.
    else setSort({ col: id, dir: id === 'start' ? 'desc' : 'asc' });
  };

  return (
    <div className="table-wrap">
      <table className="tbl">
        <thead>
          <tr>
            <th style={{ width: 12 }}></th>
            {headers.map(h => (
              <th key={h.id} onClick={() => onSort(h.id)}>
                {h.label}
                {sort.col === h.id && <span className="sortcaret">{sort.dir === 'asc' ? '↑' : '↓'}</span>}
              </th>
            ))}
            <th style={{ width: 40 }}></th>
          </tr>
        </thead>
        <tbody>
          {sorted.map(ev => {
            const hasSubs = (ev.subtasks || []).length > 0;
            const isExpanded = expanded.has(ev.id);
            return (
              <React.Fragment key={ev.id}>
                <Row ev={ev} options={options} today={today}
                  selected={ev.id === selectedId}
                  hasSubs={hasSubs}
                  isExpanded={isExpanded}
                  onToggleExpand={() => toggleExpand(ev.id)}
                  onOpen={() => openEvent(ev.id)}
                  onUpdate={p => update(ev.id, p)}
                  onRemove={() => remove(ev.id)}
                />
                {isExpanded && hasSubs && (ev.subtasks || [])
                  .slice()
                  .sort((a, b) => a.date < b.date ? -1 : a.date > b.date ? 1 : 0)
                  .map(st => (
                    <SubtaskRow
                      key={st.id}
                      parent={ev}
                      st={st}
                      options={options}
                      onUpdate={patch => update(ev.id, {
                        subtasks: ev.subtasks.map(s => s.id === st.id ? { ...s, ...patch } : s)
                      })}
                      onRemove={() => update(ev.id, {
                        subtasks: ev.subtasks.filter(s => s.id !== st.id)
                      })}
                      onOpen={() => openEvent(ev.id)}
                    />
                ))}
                {isExpanded && (
                  <AddSubtaskRow
                    parent={ev}
                    options={options}
                    onAdd={st => update(ev.id, { subtasks: [...(ev.subtasks || []), st] })}
                  />
                )}
              </React.Fragment>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

function getCol(ev, col, options) {
  if (col === 'channel') return UT.nameOf(options, 'channels', ev.channel);
  if (col === 'owner') {
    // Sort key for multi-owner: first owner's name, falling back to empty.
    const ids = UT.ownerIdsOf(ev);
    return ids.length ? UT.nameOf(options, 'owners', ids[0]) : '';
  }
  if (col === 'category') return UT.nameOf(options, 'categories', ev.category);
  if (col === 'product') return UT.nameOf(options, 'products', ev.product);
  if (col === 'format') return UT.nameOf(options, 'formats', ev.format);
  if (col === 'stage') return UT.stageOrder(options, ev.stage);
  if (col === 'subtasks') return (ev.subtasks || []).length;
  if (col === 'media') return (ev.media || []).length;
  return ev[col] || '';
}

function Row({ ev, options, today, selected, hasSubs, isExpanded, onToggleExpand, onOpen, onUpdate, onRemove }) {
  const isPastDue = !ev.tbd && ev.end < today && UT.stageOrder(options, ev.stage) < 2;
  const catColor = UT.colorOf(options, 'categories', ev.category);
  const appsForCategory = UT.subproductsFor(options, ev.category);
  const showAppCell = appsForCategory.length > 0;
  const showProductCell = !showAppCell;

  return (
    <tr className={(selected ? 'selected' : '') + (isExpanded ? ' is-expanded' : '')}>
      <td className="colordot" style={{ background: catColor }}></td>
      <td style={{ minWidth: 360 }}>
        <div style={{ display: 'flex', alignItems: 'flex-start', gap: 8 }}>
          {hasSubs ? (
            <button className="tbl-caret" onClick={onToggleExpand} title={isExpanded ? 'Collapse sub-tasks' : 'Expand sub-tasks'}>
              <svg width="10" height="10" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" style={{ transform: isExpanded ? 'rotate(90deg)' : 'none', transition: 'transform 160ms cubic-bezier(0.16,1,0.3,1)' }}>
                <path d="M4 2l4 4-4 4" />
              </svg>
            </button>
          ) : (
            <span className="tbl-caret-spacer" aria-hidden="true"></span>
          )}
          <div style={{ flex: 1, minWidth: 0 }}>
            <EditableMultiline
              value={ev.title}
              onChange={v => onUpdate({ title: v })}
              placeholder="Untitled"
              lines={2}
              weight={600}
            />
            {isPastDue && (
              <span className="row-flag" style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
                <svg width="9" height="9" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                  <path d="M6 2v4.5" />
                  <circle cx="6" cy="9" r="0.6" fill="currentColor" stroke="none" />
                </svg>
                PAST DUE
              </span>
            )}
            {ev.tbd && <span className="row-tbd">TBD</span>}
            {ev.needsReview && ev.stage !== 'done' && <span className="row-needs-review">NEEDS REVIEW</span>}
          </div>
        </div>
      </td>
      <td>
        <DateRange ev={ev} onUpdate={onUpdate} />
      </td>
      <td>
        <window.mcalStageChip stageId={ev.stage} options={options} full />
      </td>
      <td><CellSelect type="channels" value={ev.channel} options={options} onChange={v => onUpdate({ channel: v })} /></td>
      <td><CellOwners ev={ev} options={options} onChange={ids => onUpdate({ owners: ids, owner: undefined })} /></td>
      <td><CellSelect type="categories" value={ev.category} options={options}
        onChange={v => {
          const np = { category: v };
          if (v !== 'products') { np.product = ''; np.subproduct = ''; }
          onUpdate(np);
        }} /></td>
      <td>
        {showProductCell && <ProductCell ev={ev} options={options} onUpdate={onUpdate} />}
        {showAppCell && (
          <AppCell ev={ev} options={options} appsForCategory={appsForCategory} onUpdate={onUpdate} />
        )}
      </td>
      <td><CellSelect type="formats" value={ev.format} options={options} onChange={v => onUpdate({ format: v })} /></td>
      <td style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-2)' }}>
        {hasSubs
          ? <button className="tbl-subs-count" onClick={onToggleExpand} title={isExpanded ? 'Collapse' : 'Expand'}>{ev.subtasks.length} {isExpanded ? '▴' : '▾'}</button>
          : <span style={{ color: 'var(--fg-4)' }}>—</span>}
      </td>
      <td style={{ maxWidth: 320, minWidth: 200 }}>
        <EditableMultiline
          value={ev.notes || ''}
          onChange={v => onUpdate({ notes: v })}
          placeholder="—"
          lines={2}
          muted
        />
      </td>
      <td style={{ maxWidth: 200 }}>
        {ev.url
          ? <a href={ev.url} target="_blank" rel="noopener" style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--accent)' }}
              onClick={e => e.stopPropagation()}>
              {(safeHost(ev.url) || '').slice(0, 24)}…
            </a>
          : <input className="editable" placeholder="add URL…" onChange={e => onUpdate({ url: e.target.value })} value="" style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-3)' }} />}
      </td>
      <td style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-2)' }}>
        {(ev.media || []).length > 0 ? `${(ev.media || []).length} ↗` : <span style={{ color: 'var(--fg-4)' }}>—</span>}
      </td>
      <td>
        <button className="iconbtn sm" onClick={onOpen} title="Open detail">↗</button>
      </td>
    </tr>
  );
}

function safeHost(u) {
  try { return new URL(u).hostname.replace(/^www\./, ''); } catch { return ''; }
}

function ProductCell({ ev, options, onUpdate }) {
  // Plain product selector (categories with apps use AppCell instead).
  const list = options.products || [];
  const CustomSelect = window.mcalSelect.CustomSelect;
  return (
    <CustomSelect
      className="cell"
      value={ev.product || ''}
      options={list}
      onChange={v => onUpdate({ product: v })}
      placeholder="—"
      allowClear
      style={{ maxWidth: 140 }}
    />
  );
}

function AppCell({ ev, options, appsForCategory, onUpdate }) {
  const CustomSelect = window.mcalSelect.CustomSelect;
  const cat = options.categories.find(c => c.id === ev.category);
  return (
    <CustomSelect
      className="cell"
      value={ev.subproduct || ''}
      options={appsForCategory}
      onChange={v => onUpdate({ subproduct: v })}
      placeholder={cat ? `${cat.name} app…` : 'app…'}
      allowClear
      style={{ maxWidth: 160 }}
    />
  );
}

function DateRange({ ev, onUpdate }) {
  const isRange = ev.isRange || ev.start !== ev.end;
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontFamily: 'var(--font-mono)', fontSize: 12 }}>
      <input type="date" className="editable" value={ev.start} style={{ width: 130, padding: '2px 4px' }}
        onChange={e => {
          const s = e.target.value;
          if (!s) return;
          onUpdate({ start: s, end: isRange && ev.end > s ? ev.end : s });
        }} />
      {isRange ? (
        <>
          <span style={{ color: 'var(--fg-3)' }}>→</span>
          <input type="date" className="editable" value={ev.end} min={ev.start} style={{ width: 130, padding: '2px 4px' }}
            onChange={e => onUpdate({ end: e.target.value || ev.start })} />
          <button
            title="Remove range (collapse to single day)"
            className="iconbtn sm"
            style={{ height: 20, width: 20, fontSize: 11, opacity: 0.6 }}
            onClick={() => onUpdate({ end: ev.start, isRange: false })}
          >×</button>
        </>
      ) : (
        <button
          title="Make this a date range"
          className="iconbtn sm"
          style={{ height: 20, width: 20, fontSize: 10, opacity: 0.6 }}
          onClick={() => onUpdate({ end: UT.addDays(ev.start, 2), isRange: true })}
        >+→</button>
      )}
    </div>
  );
}

function CellSelect({ type, value, options, onChange }) {
  const list = options[type] || [];
  const CustomSelect = window.mcalSelect.CustomSelect;
  return (
    <CustomSelect
      className="cell"
      value={value || ''}
      options={list}
      onChange={onChange}
      placeholder="—"
      allowClear
    />
  );
}

/* Compact owner multi-select for table cells. Click to toggle owners
   from the popover; the cell collapses owner chips to fit. */
function CellOwners({ ev, options, onChange }) {
  const [open, setOpen] = useStateT(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const onDoc = e => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [open]);
  const allOwners = options.owners || [];
  const ids = UT.ownerIdsOf(ev);
  const gtmTeam = options.gtmTeam || [];
  // Same GTM-Team scoping the detail panel uses; existing tags remain
  // togglable even if not currently in the team.
  const list = gtmTeam.length > 0
    ? allOwners.filter(o => gtmTeam.includes(o.id) || ids.includes(o.id))
    : allOwners;
  const selected = new Set(ids);
  const toggle = id => {
    const next = new Set(selected);
    if (next.has(id)) next.delete(id); else next.add(id);
    onChange([...next]);
  };
  const currentOwners = ids.map(id => allOwners.find(o => o.id === id)).filter(Boolean);
  const summary = ids.length === 0 ? '—'
    : currentOwners.map(o => o.name).join(', ');
  return (
    <div className={'mcal-select cell' + (open ? ' open' : '')} ref={ref} style={{ position: 'relative' }}>
      <button type="button" className="mcs-trigger" onClick={() => setOpen(o => !o)}>
        {currentOwners.length === 0 ? (
          <span className="mcs-swatch" style={{ background: 'transparent', borderStyle: 'dashed' }}></span>
        ) : currentOwners.length === 1 ? (
          <span className="mcs-swatch" style={{ background: currentOwners[0].color }}></span>
        ) : (
          <span className="mcs-swatch-stack">
            {currentOwners.slice(0, 3).map(o => (
              <span key={o.id} className="mcs-swatch" style={{ background: o.color }}></span>
            ))}
          </span>
        )}
        <span className={'mcs-label' + (ids.length === 0 ? ' empty' : '')}>{summary}</span>
        <span className="mcs-caret">▾</span>
      </button>
      {open && (
        <div className="popover owners-popover">
          {list.length === 0 ? (
            <div style={{ padding: 10, fontSize: 12, color: 'var(--fg-3)' }}>No teammates signed in yet.</div>
          ) : list.map(o => (
            <div key={o.id} className={'po-item' + (selected.has(o.id) ? ' on' : '')} onClick={() => toggle(o.id)}>
              <span className="swatch" style={{ background: o.color }}></span>
              <span style={{ flex: 1 }}>{o.name}</span>
              <span className="check">{selected.has(o.id) ? '✓' : ''}</span>
            </div>
          ))}
          {ids.length > 0 && (
            <>
              <div className="po-divider"></div>
              <div className="po-clear" onClick={() => onChange([])}>Clear all</div>
            </>
          )}
        </div>
      )}
    </div>
  );
}

/* ─── Sub-task row in table view ───
   Renders a sub-task with the same column structure as a parent row.
   Each field shows the effective value (sub-task override → parent inherit)
   and is inline-editable. Setting a field on a sub-task overrides parent
   inheritance for that field; clearing it falls back to parent.
*/
function SubtaskRow({ parent, st, options, onUpdate, onRemove, onOpen }) {
  const ef = key => (st[key] !== undefined && st[key] !== null && st[key] !== '') ? st[key] : parent[key];
  const effCategory = ef('category');
  const effCatColor = UT.colorOf(options, 'categories', effCategory);
  const appsForCategory = UT.subproductsFor(options, effCategory);
  const showAppCell = appsForCategory.length > 0;
  const showProductCell = !showAppCell;
  const isOverride = key => st[key] !== undefined && st[key] !== null && st[key] !== '';

  // For the date cell we use a minimal inline date input clamped to parent range.
  return (
    <tr className="subtask-tr">
      <td className="colordot subtask-dot" style={{ background: effCatColor }}></td>
      <td>
        <div style={{ display: 'flex', alignItems: 'flex-start', gap: 8, paddingLeft: 20, position: 'relative' }}>
          <span className="subtask-rail" aria-hidden="true">↳</span>
          <div style={{ flex: 1, minWidth: 0 }}>
            <EditableMultiline
              value={st.title}
              onChange={v => onUpdate({ title: v })}
              placeholder="Sub-task title"
              lines={1}
              weight={500}
            />
          </div>
        </div>
      </td>
      <td>
        <input
          type="date"
          className="editable st-date-inline"
          value={st.date}
          min={parent.start}
          max={parent.end}
          onChange={e => onUpdate({ date: e.target.value })}
          style={{ fontFamily: 'var(--font-mono)', fontSize: 12, width: 130, padding: '2px 4px' }}
        />
      </td>
      <td>
        <window.mcalStageChip stageId={st.stage || 'ideation'} options={options} full />
      </td>
      <td><SubCell overridden={isOverride('channel')}  onReset={() => onUpdate({ channel: undefined })}>
        <CellSelect type="channels" value={ef('channel')} options={options} onChange={v => onUpdate({ channel: v })} />
      </SubCell></td>
      <td><SubCell overridden={Array.isArray(st.owners) || isOverride('owner')} onReset={() => onUpdate({ owners: undefined, owner: undefined })}>
        <CellOwners
          ev={{ owners: UT.ownerIdsOf(st, UT.ownerIdsOf(parent)) }}
          options={options}
          onChange={ids => onUpdate({ owners: ids, owner: undefined })}
        />
      </SubCell></td>
      <td><SubCell overridden={isOverride('category')} onReset={() => onUpdate({ category: undefined, product: undefined, subproduct: undefined })}>
        <CellSelect type="categories" value={ef('category')} options={options}
          onChange={v => {
            const np = { category: v };
            if (UT.subproductsFor(options, v).length === 0) np.subproduct = '';
            if (UT.subproductsFor(options, v).length > 0) np.product = '';
            onUpdate(np);
          }} />
      </SubCell></td>
      <td>
        {showProductCell && (
          <SubCell overridden={isOverride('product')} onReset={() => onUpdate({ product: undefined })}>
            <window.mcalSelect.CustomSelect
              className="cell"
              value={ef('product') || ''}
              options={options.products || []}
              onChange={v => onUpdate({ product: v })}
              placeholder="—"
              allowClear
              style={{ maxWidth: 140 }}
            />
          </SubCell>
        )}
        {showAppCell && (
          <SubCell overridden={isOverride('subproduct')} onReset={() => onUpdate({ subproduct: undefined })}>
            <window.mcalSelect.CustomSelect
              className="cell"
              value={ef('subproduct') || ''}
              options={appsForCategory}
              onChange={v => onUpdate({ subproduct: v })}
              placeholder="app…"
              allowClear
              style={{ maxWidth: 160 }}
            />
          </SubCell>
        )}
      </td>
      <td>
        <SubCell overridden={isOverride('format')} onReset={() => onUpdate({ format: undefined })}>
          <CellSelect type="formats" value={ef('format')} options={options} onChange={v => onUpdate({ format: v })} />
        </SubCell>
      </td>
      <td style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-4)' }}>—</td>
      <td style={{ maxWidth: 320, minWidth: 200 }}>
        <EditableMultiline
          value={st.notes || ''}
          onChange={v => onUpdate({ notes: v })}
          placeholder="—"
          lines={2}
          muted
        />
      </td>
      <td style={{ maxWidth: 200 }}>
        {st.url
          ? <a href={st.url} target="_blank" rel="noopener" style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--accent)' }}
              onClick={e => e.stopPropagation()}>
              {(safeHost(st.url) || '').slice(0, 24)}…
            </a>
          : <input className="editable" placeholder="add URL…" onChange={e => onUpdate({ url: e.target.value })} value="" style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-3)' }} />}
      </td>
      <td style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-2)' }}>
        {(st.media || []).length > 0 ? `${(st.media || []).length} ↗` : <span style={{ color: 'var(--fg-4)' }}>—</span>}
      </td>
      <td>
        <button className="iconbtn sm" onClick={onRemove} title="Remove sub-task">×</button>
      </td>
    </tr>
  );
}

/* Small override-state indicator wrapper for sub-task cells.
   Shows a subtle dot when the field overrides the parent, with a click-to-reset
   action that restores inheritance. */
function SubCell({ overridden, onReset, children }) {
  return (
    <div className={'subtask-cell' + (overridden ? ' is-override' : '')}>
      <div className="subtask-cell-content">{children}</div>
      {overridden && (
        <button className="subtask-reset" title="Reset to inherit from parent" onClick={onReset}>↺</button>
      )}
    </div>
  );
}

function AddSubtaskRow({ parent, options, onAdd }) {
  const [draft, setDraft] = React.useState('');
  const commit = () => {
    const title = draft.trim();
    if (!title) return;
    onAdd({
      id: 'st_' + Math.random().toString(36).slice(2, 7),
      title,
      date: parent.start,
      stage: 'ideation',
      channel: parent.channel,
      owners: UT.ownerIdsOf(parent),
      category: parent.category,
      product: parent.product || '',
      subproduct: parent.subproduct || '',
      format: parent.format,
      notes: '',
      url: '',
      media: [],
    });
    setDraft('');
  };
  return (
    <tr className="subtask-tr subtask-add">
      <td></td>
      <td colSpan={13}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, paddingLeft: 20 }}>
          <span style={{ color: 'var(--fg-4)', fontFamily: 'var(--font-mono)', fontSize: 11 }}>+ sub-task</span>
          <input
            className="editable"
            placeholder="Add a sub-task title and press Enter…"
            value={draft}
            onChange={e => setDraft(e.target.value)}
            onKeyDown={e => { if (e.key === 'Enter') commit(); }}
            style={{ flex: 1, minWidth: 0, fontSize: 12, fontFamily: 'var(--font-mono)' }}
          />
          <button
            className="iconbtn sm"
            onClick={commit}
            disabled={!draft.trim()}
            title="Add sub-task"
            style={{ height: 22 }}
          >+</button>
        </div>
      </td>
    </tr>
  );
}

window.mcalTable = { TableView: React.memo(TableView) };

function EditableMultiline({ value, onChange, placeholder, lines = 2, weight, muted }) {
  const [editing, setEditing] = React.useState(false);
  const [draft, setDraft] = React.useState(value || '');
  const taRef = React.useRef(null);

  React.useEffect(() => { if (!editing) setDraft(value || ''); }, [value, editing]);
  React.useEffect(() => {
    if (editing && taRef.current) {
      taRef.current.focus();
      // place cursor at end
      const v = taRef.current.value;
      taRef.current.setSelectionRange(v.length, v.length);
    }
  }, [editing]);

  const commit = () => {
    if (draft !== (value || '')) onChange(draft);
    setEditing(false);
  };
  const cancel = () => {
    setDraft(value || '');
    setEditing(false);
  };

  if (editing) {
    return (
      <textarea
        ref={taRef}
        className="tbl-multi-edit"
        value={draft}
        onChange={e => setDraft(e.target.value)}
        onBlur={commit}
        onKeyDown={e => {
          if (e.key === 'Escape') { e.preventDefault(); cancel(); }
          if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) { e.preventDefault(); commit(); }
        }}
        style={{
          fontWeight: weight || 400,
          color: muted ? 'var(--fg-2)' : 'var(--fg)',
        }}
      />
    );
  }

  const display = value || '';
  return (
    <div
      className={'tbl-multi' + (display ? '' : ' empty')}
      style={{
        WebkitLineClamp: lines,
        fontWeight: weight || 400,
        color: muted ? 'var(--fg-2)' : 'var(--fg)',
      }}
      onClick={() => setEditing(true)}
      title={display}
    >
      {display || placeholder || '\u00a0'}
    </div>
  );
}
