/* Kanban / progress board view. Events grouped into 4 stage columns:
   Ideation → Creation → Ready → Done. Click a card to open the detail
   panel; drag a card between columns to change its stage. Per-column +
   pre-fills the new draft's stage. */

const { useState: useStateK, useMemo: useMemoK } = React;
const UK = window.mcalUtils;

const STAGE_ORDER = ['ideation', 'creation', 'ready', 'done'];

function KanbanView({ today, events, options, colorBy, openEvent, addEventAt, update }) {
  const [dragId, setDragId] = useStateK(null);
  const [hoverStage, setHoverStage] = useStateK(null);

  // Group events AND sub-tasks by stage. Each row in a column is an
  // "item" with kind 'event' or 'subtask' — sub-tasks are placed by
  // their OWN stage (not the parent's) so a parent in CREATION can
  // have a sub-task in READY.
  // Holidays/conferences are excluded — they're calendar markers,
  // not workflow items.
  const byStage = useMemoK(() => {
    const groups = Object.fromEntries(STAGE_ORDER.map(s => [s, []]));
    events.forEach(ev => {
      if (ev.isHoliday || ev.isConference) return;
      const stage = STAGE_ORDER.includes(ev.stage) ? ev.stage : 'ideation';
      groups[stage].push({ kind: 'event', id: ev.id, ev, sortDate: ev.start });
      (ev.subtasks || []).forEach(st => {
        const sStage = STAGE_ORDER.includes(st.stage) ? st.stage : 'ideation';
        groups[sStage].push({
          kind: 'subtask',
          id: 'subtask:' + ev.id + ':' + st.id,
          st,
          parent: ev,
          sortDate: st.date || ev.start,
        });
      });
    });
    // Within a column: earliest date first, then title — except Done, which
    // shows the latest dates first (most recently completed at the top).
    Object.entries(groups).forEach(([stageId, arr]) => {
      const dateDir = stageId === 'done' ? -1 : 1;
      arr.sort((a, b) => {
        if (a.sortDate !== b.sortDate) return (a.sortDate < b.sortDate ? -1 : 1) * dateDir;
        const at = a.kind === 'event' ? (a.ev.title || '') : (a.st.title || '');
        const bt = b.kind === 'event' ? (b.ev.title || '') : (b.st.title || '');
        return at.localeCompare(bt);
      });
    });
    return groups;
  }, [events]);

  const onCardDragStart = (e, payloadId) => {
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.setData('text/plain', payloadId);
    setDragId(payloadId);
    window.mcalSetHoverDisabled && window.mcalSetHoverDisabled(true);
  };
  const onCardDragEnd = () => {
    setDragId(null);
    setHoverStage(null);
    window.mcalSetHoverDisabled && window.mcalSetHoverDisabled(false);
  };
  const onColumnDragOver = (e, stageId) => {
    if (!dragId && !(e.dataTransfer.types && e.dataTransfer.types.indexOf('text/plain') >= 0)) return;
    e.preventDefault();
    e.dataTransfer.dropEffect = 'move';
    if (hoverStage !== stageId) setHoverStage(stageId);
  };
  const onColumnDrop = (e, stageId) => {
    e.preventDefault();
    const raw = e.dataTransfer.getData('text/plain') || (dragId || '');
    setDragId(null);
    setHoverStage(null);
    if (!raw) return;
    if (raw.startsWith('subtask:')) {
      // Subtask drop → re-stage the subtask under its parent.
      const [, parentId, subId] = raw.split(':');
      const parent = events.find(x => x.id === parentId);
      if (!parent) return;
      const sub = (parent.subtasks || []).find(s => s.id === subId);
      if (!sub || sub.stage === stageId) return;
      const nextSubs = parent.subtasks.map(s => s.id === subId ? { ...s, stage: stageId } : s);
      update && update(parentId, { subtasks: nextSubs });
      return;
    }
    const ev = events.find(x => x.id === raw);
    if (!ev || ev.stage === stageId) return;
    update && update(ev.id, { stage: stageId });
  };

  return (
    <div className="kanban">
      {STAGE_ORDER.map(stageId => {
        const stage = UK.stageById(options, stageId);
        const items = byStage[stageId] || [];
        const cls = ['kb-col'];
        if (hoverStage === stageId) cls.push('drop-target');
        return (
          <div
            key={stageId}
            className={cls.join(' ')}
            onDragOver={e => onColumnDragOver(e, stageId)}
            onDragLeave={e => {
              if (e.currentTarget.contains(e.relatedTarget)) return;
              if (hoverStage === stageId) setHoverStage(null);
            }}
            onDrop={e => onColumnDrop(e, stageId)}
          >
            <div className="kb-col-head">
              <span className="kb-col-glyph" style={{ color: stage.color || 'var(--fg-3)' }}>
                {window.mcalStageGlyph ? <window.mcalStageGlyph pct={stage.fillPct != null ? stage.fillPct : ((stage.order + 1) / 4) * 100} size={12} /> : stage.glyph}
              </span>
              <span className="kb-col-name">{stage.name}</span>
              <span className="kb-col-count">{items.length}</span>
              {addEventAt && (
                <button
                  className="kb-col-add"
                  onClick={() => addEventAt({ start: today, end: today, stage: stageId })}
                  title="Add event"
                >+</button>
              )}
            </div>
            <div className="kb-col-body">
              {items.length === 0 && (
                <div className="kb-empty">no items</div>
              )}
              {items.map(item => (
                item.kind === 'event' ? (
                  <KanbanCard
                    key={item.id}
                    ev={item.ev}
                    options={options}
                    colorBy={colorBy}
                    today={today}
                    isDragging={dragId === item.id}
                    payloadId={item.ev.id}
                    onDragStart={onCardDragStart}
                    onDragEnd={onCardDragEnd}
                    onOpen={() => openEvent(item.ev.id)}
                  />
                ) : (
                  <KanbanSubCard
                    key={item.id}
                    st={item.st}
                    parent={item.parent}
                    options={options}
                    colorBy={colorBy}
                    today={today}
                    isDragging={dragId === item.id}
                    payloadId={item.id}
                    onDragStart={onCardDragStart}
                    onDragEnd={onCardDragEnd}
                    onOpen={() => openEvent(item.parent.id, item.st.id)}
                  />
                )
              ))}
            </div>
          </div>
        );
      })}
    </div>
  );
}

function KanbanCard({ ev, options, colorBy, today, isDragging, payloadId, onDragStart, onDragEnd, onOpen }) {
  const color = colorForEventK(ev, options, colorBy);
  const isPastDue = isPastDueEventK(ev, today, options);
  const cls = ['kb-card'];
  if (ev.tbd && ev.stage !== 'done') cls.push('tbd');
  if (ev.needsReview && ev.stage !== 'done') cls.push('needs-review');
  if (isPastDue) cls.push('past-due');
  if (isDragging) cls.push('dragging');
  return (
    <window.mcalHoverCard.HoverWrap event={ev} options={options} onEdit={onOpen}>
      {tp => (
        <div
          className={cls.join(' ')}
          style={{ borderLeftColor: color }}
          draggable={!ev.isHoliday && !ev.isConference}
          onDragStart={e => onDragStart(e, payloadId)}
          onDragEnd={() => onDragEnd()}
          onClick={onOpen}
          {...tp}
        >
          <div className="kb-card-top">
            <window.mcalProductTag event={ev} options={options} />
            <span className="kb-card-date">
              {UK.shortDate(ev.start)}
              {ev.end !== ev.start && <><span className="dr-arrow">→</span>{UK.shortDate(ev.end)}</>}
            </span>
          </div>
          <div className="kb-card-title">{ev.title ? (window.mcalRichText ? window.mcalRichText(ev.title, options) : ev.title) : 'Untitled'}</div>
          <div className="kb-card-meta">
            <span>{UK.nameOf(options, 'channels', ev.channel)}</span>
            <span>·</span>
            <span>{ownerNamesFor(ev, options)}</span>
            {(ev.subtasks || []).length > 0 && (
              <>
                <span>·</span>
                <span title={`${ev.subtasks.length} sub-tasks`}>+{ev.subtasks.length} sub</span>
              </>
            )}
          </div>
        </div>
      )}
    </window.mcalHoverCard.HoverWrap>
  );
}

/* Sub-task card. Inherits classification from parent when the sub-task
   field is unset (mirror of SubtaskItem.eff in detail.jsx). Carries a
   "SUBTASK" badge so it's visually distinct from a parent card in the
   same column. */
function KanbanSubCard({ st, parent, options, colorBy, today, isDragging, payloadId, onDragStart, onDragEnd, onOpen }) {
  const eff = key => (st[key] !== undefined && st[key] !== null && st[key] !== '') ? st[key] : parent[key];
  const effectiveEv = {
    ...parent,
    channel:  eff('channel'),
    owners:   UK.ownerIdsOf(st, UK.ownerIdsOf(parent)),
    category: eff('category'),
    product:  eff('product'),
    format:   eff('format'),
  };
  const color = colorForEventK(effectiveEv, options, colorBy);
  const cls = ['kb-card', 'is-subtask'];
  if (st.needsReview && (st.stage || 'ideation') !== 'done') cls.push('needs-review');
  if (isDragging) cls.push('dragging');
  return (
    <window.mcalHoverCard.HoverWrap event={parent} subtask={st} options={options} onEdit={onOpen}>
      {tp => (
        <div
          className={cls.join(' ')}
          style={{ borderLeftColor: color }}
          draggable
          onDragStart={e => onDragStart(e, payloadId)}
          onDragEnd={() => onDragEnd()}
          onClick={onOpen}
          {...tp}
        >
          <div className="kb-card-top">
            <span className="kb-subtask-badge">SUBTASK</span>
            <span className="kb-card-date">{UK.shortDate(st.date)}</span>
          </div>
          <div className="kb-card-title">{st.title ? (window.mcalRichText ? window.mcalRichText(st.title, options) : st.title) : 'Untitled'}</div>
          <div className="kb-card-meta">
            <span style={{ color: 'var(--fg-4)' }}>↳ {parent.title ? (window.mcalRichText ? window.mcalRichText(parent.title, options) : parent.title) : 'Untitled'}</span>
            <span>·</span>
            <span>{UK.nameOf(options, 'channels', effectiveEv.channel)}</span>
          </div>
        </div>
      )}
    </window.mcalHoverCard.HoverWrap>
  );
}

function singularForK(plural) {
  return plural === 'channels' ? 'channel'
    : plural === 'categories' ? 'category'
    : plural === 'owners' ? 'owner'
    : plural === 'products' ? 'product'
    : plural === 'stages' ? 'stage'
    : 'category';
}
function colorForEventK(ev, options, colorBy) {
  if (colorBy === 'owners') {
    const ids = UK.ownerIdsOf(ev);
    return UK.colorOf(options, 'owners', ids[0] || '');
  }
  return UK.colorOf(options, colorBy, ev[singularForK(colorBy)]);
}
function ownerNamesFor(ev, options) {
  const ids = UK.ownerIdsOf(ev);
  if (ids.length === 0) return '—';
  if (ids.length === 1) return UK.nameOf(options, 'owners', ids[0]);
  return `${ids.length} owners`;
}

function isPastDueEventK(ev, today, options) {
  if (ev.tbd) return false;
  if (ev.end >= today) return false;
  const order = UK.stageOrder(options, ev.stage);
  return order < 2;
}

window.mcalKanban = { KanbanView: React.memo(KanbanView) };
