// HQ Action Center (gap #3)
// Centralized task tracking — every alert, AI insight, PO, compliance flag,
// vendor issue and campaign approval can be converted to a task here and
// tracked through to resolution. Status pipeline: New → Assigned → In Progress
// → Waiting on Franchisee → Resolved (or Escalated).

const ACTIONS = [
  {
    id:'ACT-1042', source:'CASL', sourceLabel:'CASL incident',
    title:'Scarborough CASL violation — INC-2026-031',
    detail:'12 non-consenting recipients on "Back to School Kids Cut" campaign. Notice of Default issued under §12.3.',
    location:'HB010', loc:'Scarborough',
    priority:'critical', status:'In Progress',
    owner:'M. Diaz (Compliance)', assignedAt:'2026-09-12 14:02', due:'2026-10-11', age:'2d',
    sla:'30d cure', linkedTo:['INC-2026-031','NoD-§12.3'],
    comments: 3,
    lastUpdate: { actor:'M. Diaz', when:'4h ago', note:'Field Ops on-site review scheduled Sep 13 14:00 EDT.' },
  },
  {
    id:'ACT-1041', source:'AI', sourceLabel:'AI insight',
    title:'Scarborough — Recommend HQ review',
    detail:'Pattern resembles 4/4 prior franchisee escalations. Requires human review before any contract action.',
    location:'HB010', loc:'Scarborough',
    priority:'critical', status:'Assigned',
    owner:'Y. Templeton (Managing Director)', assignedAt:'2026-09-13 09:38', due:'2026-09-20', age:'<1d',
    sla:'7d', linkedTo:['ACT-1042'],
    comments: 0,
    lastUpdate: { actor:'System', when:'just now', note:'AI surfaced this insight; auto-routed to franchise owner.' },
  },
  {
    id:'ACT-1040', source:'PO', sourceLabel:'PO approval',
    title:'PO-00154 — Scarborough / Discount Barber Depot',
    detail:'$1,560 PO routed to an unapproved vendor. Requires HQ exception to proceed.',
    location:'HB010', loc:'Scarborough',
    priority:'high', status:'Waiting on Franchisee',
    owner:'D. Owens (Procurement)', assignedAt:'2026-09-10 10:14', due:'2026-09-15', age:'3d',
    sla:'5d', linkedTo:['PO-00154'],
    comments: 2,
    lastUpdate: { actor:'D. Owens', when:'1d ago', note:'Requested alt-vendor quote from K. Manderson.' },
  },
  {
    id:'ACT-1039', source:'Vendor', sourceLabel:'Vendor SLA',
    title:'Northbridge — Beard Balm SLA breach',
    detail:'14-day cover commitment missed; 4 shops impacted. Diversification opportunity to ProEdge.',
    location:null, loc:'Network',
    priority:'high', status:'In Progress',
    owner:'D. Owens (Procurement)', assignedAt:'2026-09-09 09:00', due:'2026-09-19', age:'4d',
    sla:'10d', linkedTo:['VENDOR-NORTHBRIDGE'],
    comments: 5,
    lastUpdate: { actor:'D. Owens', when:'8h ago', note:'Sent diversification proposal to brand team.' },
  },
  {
    id:'ACT-1038', source:'Royalty', sourceLabel:'Royalty',
    title:'Richmond Hill royalty 11d overdue',
    detail:'$3,853 outstanding. Auto-debit failed twice (NSF). Manual collection in progress.',
    location:'HB009', loc:'Richmond Hill',
    priority:'high', status:'In Progress',
    owner:'R. Cao (Finance)', assignedAt:'2026-09-02 11:30', due:'2026-09-16', age:'11d',
    sla:'14d', linkedTo:['INV-2026-Q1-Q'],
    comments: 4,
    lastUpdate: { actor:'R. Cao', when:'2d ago', note:'Operator confirmed payment by wire Sep 14.' },
  },
  {
    id:'ACT-1037', source:'Royalty', sourceLabel:'Royalty',
    title:'Scarborough royalty — $2,248 disputed',
    detail:'Operator disputing "training day discount" exclusion. Review §8.2 with HQ Legal.',
    location:'HB010', loc:'Scarborough',
    priority:'medium', status:'New',
    owner:null, assignedAt:null, due:'2026-09-20', age:'1d',
    sla:'7d', linkedTo:['INV-2026-Q1-W'],
    comments: 0,
    lastUpdate: { actor:'System', when:'1d ago', note:'Flagged by finance reconciliation.' },
  },
  {
    id:'ACT-1036', source:'Campaign', sourceLabel:'Campaign approval',
    title:'Hamilton — reopening campaign translation fix',
    detail:'Operator resubmitted French translation. Compliance review needed before send.',
    location:'HB005', loc:'Hamilton',
    priority:'standard', status:'Assigned',
    owner:'M. Diaz (Compliance)', assignedAt:'2026-09-11 16:00', due:'2026-09-15', age:'2d',
    sla:'5d', linkedTo:['CAMP-2026-PLAT-01'],
    comments: 1,
    lastUpdate: { actor:'W. Underhill', when:'1d ago', note:'Translation fixed; ready for review.' },
  },
  {
    id:'ACT-1035', source:'Reputation', sourceLabel:'Reputation',
    title:'Richmond Hill NPS coaching plan — A. Russell',
    detail:'Three detractor reviews citing same provider. NPS dropped 12pts WoW.',
    location:'HB009', loc:'Richmond Hill',
    priority:'medium', status:'In Progress',
    owner:'L. Tran (Operations)', assignedAt:'2026-09-11 09:30', due:'2026-09-25', age:'2d',
    sla:'14d', linkedTo:[],
    comments: 2,
    lastUpdate: { actor:'G. Latham', when:'1h ago', note:'Plan attached. Reviewing with team Friday.' },
  },
  {
    id:'ACT-1034', source:'Compliance', sourceLabel:'Brand standards',
    title:'Scarborough audit score 62% — below threshold',
    detail:'Auto-flagged by brand-standards audit. Cleanliness + signage scoring below 70%.',
    location:'HB010', loc:'Scarborough',
    priority:'high', status:'Escalated',
    owner:'M. Diaz (Compliance)', assignedAt:'2026-09-08 10:14', due:'2026-09-22', age:'5d',
    sla:'14d', linkedTo:['AUDIT-Q2-2026-W'],
    comments: 6,
    lastUpdate: { actor:'M. Diaz', when:'3h ago', note:'Escalated alongside CASL incident.' },
  },
  {
    id:'ACT-1033', source:'AI', sourceLabel:'AI insight',
    title:'Loyalty redemption gap — 3 shops below 15%',
    detail:'Aligning the 3 lagging shops to network avg unlocks ~$34K/mo.',
    location:null, loc:'Network',
    priority:'medium', status:'New',
    owner:null, assignedAt:null, due:null, age:'1d',
    sla:'14d', linkedTo:[],
    comments: 0,
    lastUpdate: { actor:'System', when:'1d ago', note:'AI surfaced this opportunity.' },
  },
  {
    id:'ACT-1032', source:'Compliance', sourceLabel:'CASL',
    title:'Richmond Hill CASL — 8 opted-out recipients',
    detail:'Resolved with warning. Operator completed CASL recertification training.',
    location:'HB009', loc:'Richmond Hill',
    priority:'medium', status:'Resolved',
    owner:'M. Diaz (Compliance)', assignedAt:'2026-08-18 09:00', due:'2026-08-25', age:'25d',
    sla:'7d', linkedTo:[], resolvedAt:'2026-08-22',
    comments: 4,
    resolution:'Warning issued; CASL training completed. Closed Aug 22.',
    lastUpdate: { actor:'M. Diaz', when:'21d ago', note:'Closed with warning + training completion proof.' },
  },
];

const STATUS_META = {
  'New':                   { color:'#475569', bg:'#F1F5F9' },
  'Assigned':              { color:'#1E40AF', bg:'#DBEAFE' },
  'In Progress':           { color:'#92400E', bg:'#FEF3C7' },
  'Waiting on Franchisee': { color:'#9A3412', bg:'#FFEDD5' },
  'Resolved':              { color:'#166534', bg:'#DCFCE7' },
  'Escalated':             { color:'#B91C1C', bg:'#FEE2E2' },
};

const PRIORITY_META = {
  'critical': { color:'#B91C1C', bg:'#FEE2E2', label:'CRITICAL' },
  'high':     { color:'#9A3412', bg:'#FFEDD5', label:'HIGH' },
  'medium':   { color:'#1E40AF', bg:'#DBEAFE', label:'MEDIUM' },
  'standard': { color:'#475569', bg:'#F1F5F9', label:'STANDARD' },
};

const ActionsPage = ({ onOpenLoc, onOpenCasl }) => {
  const [tasks, setTasks] = React.useState(ACTIONS);
  const [newOpen, setNewOpen] = React.useState(false);
  const [draft, setDraft] = React.useState({ title:'', loc:'Network', priority:'medium', owner:'M. Diaz (Compliance)', due:'2026-09-21' });
  const setD = (k, v) => setDraft(d => ({ ...d, [k]: v }));
  const createTask = () => {
    if (!draft.title.trim()) { hbToast('Task needs a title', 'Add a short title before creating'); return; }
    const id = 'ACT-' + (1043 + tasks.filter(t => t.source === 'Manual').length);
    const locEntry = window.FRANCHISE_DATA.LOCATIONS.find(l => l.name.indexOf(draft.loc) >= 0);
    setTasks(ts => [{
      id, source:'Manual', sourceLabel:'Manual task',
      title: draft.title.trim(), detail:'Created from the HQ Action Center.',
      location: locEntry ? locEntry.id : null, loc: draft.loc,
      priority: draft.priority, status:'New',
      owner: draft.owner, assignedAt:'2026-09-14', due: draft.due, age:'<1h',
      sla:'7d', linkedTo:[], comments: 0,
      lastUpdate: { actor:'You', when:'just now', note:'Task created manually.' },
    }, ...ts]);
    setNewOpen(false);
    setDraft(d => ({ ...d, title:'' }));
    hbToast('Task ' + id + ' created', 'Assigned to ' + draft.owner);
  };
  const resolveTask = (task) => {
    setTasks(ts => ts.map(t => t.id === task.id ? { ...t, status:'Resolved', resolvedAt:'2026-09-14', resolution:'Resolved from the HQ Action Center.' } : t));
    setOpenAction(null);
    hbToast('Task resolved', task.id + ' moved to Resolved');
  };
  const [statusFilter, setStatusFilter] = React.useState('all');
  const [sourceFilter, setSourceFilter] = React.useState('all');
  const [openAction, setOpenAction] = React.useState(null);

  const rows = tasks.filter(a => {
    if (statusFilter === 'open') return a.status !== 'Resolved';
    if (statusFilter !== 'all' && statusFilter !== 'open') return a.status === statusFilter;
    return true;
  }).filter(a => sourceFilter === 'all' ? true : a.source === sourceFilter);

  const byStatus = (s) => tasks.filter(a => a.status === s).length;
  const openCount = tasks.filter(a => a.status !== 'Resolved').length;

  return (
    <div className="page">
      <div className="pageheader">
        <div>
          <h1 className="pageheader-title">HQ Action Center</h1>
          <p className="pageheader-sub">Every alert, AI insight, PO, compliance flag, campaign approval and vendor issue — convertible to a tracked task with an owner, due date and audit trail.</p>
        </div>
        <div className="pageheader-tools">
          <button className="ghost-btn"><Icon name="filter" size={12} stroke={2.2}/> Saved views</button>
          <button className="primary-btn" data-live="1" onClick={() => setNewOpen(true)}><Icon name="plus" size={12} stroke={2.4}/> New task</button>
        </div>
      </div>

      <div className="cat-kpis">
        <div className="cat-kpi cat-kpi-urgent">
          <div className="cat-kpi-l">Open tasks <InfoDot tip="Tasks not yet resolved. Pulled from every system: AI, alerts, POs, compliance, vendor SLAs, campaign approvals."/></div>
          <div className="cat-kpi-v">{openCount}</div>
          <div className="cat-kpi-sub">{byStatus('Escalated')} escalated · {tasks.filter(a => a.priority === 'critical').length} critical</div>
        </div>
        <div className="cat-kpi"><div className="cat-kpi-l">New <InfoDot tip="Just-created tasks awaiting an owner."/></div><div className="cat-kpi-v">{byStatus('New')}</div><div className="cat-kpi-sub">{tasks.filter(a => a.status === 'New' && !a.owner).length} unassigned</div></div>
        <div className="cat-kpi"><div className="cat-kpi-l">In progress <InfoDot tip="Tasks an HQ user has started working on."/></div><div className="cat-kpi-v">{byStatus('In Progress')}</div><div className="cat-kpi-sub">Across {new Set(tasks.filter(a => a.status === 'In Progress').map(a => a.owner)).size} owners</div></div>
        <div className="cat-kpi cat-kpi-warn"><div className="cat-kpi-l">Waiting on franchisee <InfoDot tip="Tasks blocked on an action by the operator. HQ has done its part."/></div><div className="cat-kpi-v">{byStatus('Waiting on Franchisee')}</div><div className="cat-kpi-sub">Avg 3.4d waiting</div></div>
        <div className="cat-kpi"><div className="cat-kpi-l">Resolved this week <InfoDot tip="Tasks closed in the last 7 days. Resolution notes attached for audit."/></div><div className="cat-kpi-v">{byStatus('Resolved')}</div><div className="cat-kpi-sub">+ 4 last week</div></div>
      </div>

      <div className="action-filters">
        <div className="seg-group small">
          {[['open','Open ' + openCount],['all','All ' + tasks.length],['New','New'],['Assigned','Assigned'],['In Progress','In progress'],['Waiting on Franchisee','Waiting'],['Resolved','Resolved'],['Escalated','Escalated']].map(([k, lbl]) => (
            <button key={k} className={'seg' + (statusFilter === k ? ' is-on' : '')} onClick={() => setStatusFilter(k)}>{lbl}</button>
          ))}
        </div>
        <div className="seg-group small">
          {[['all','All sources'],['AI','AI'],['CASL','CASL'],['PO','PO'],['Royalty','Royalty'],['Vendor','Vendor'],['Compliance','Compliance'],['Campaign','Campaign'],['Reputation','Reputation']].map(([k, lbl]) => (
            <button key={k} className={'seg' + (sourceFilter === k ? ' is-on' : '')} onClick={() => setSourceFilter(k)}>{lbl}</button>
          ))}
        </div>
      </div>

      <section className="card">
        <header className="card-head">
          <div className="card-head-left">
            <Icon name="check" size={16} stroke={2}/>
            <h2>Action queue</h2>
            <span className="card-head-count">{rows.length} tasks</span>
          </div>
          <div className="card-head-right">
            <button className="ghost-btn small">Bulk reassign</button>
            <button className="ghost-btn small">Export</button>
          </div>
        </header>
        <div className="lb-table-wrap">
          <table className="lb-table cat-table">
            <thead>
              <tr>
                <th>Task</th>
                <th>Source</th>
                <th>Location</th>
                <th>Priority</th>
                <th>Status</th>
                <th>Owner</th>
                <th>Due / SLA</th>
                <th>Last update</th>
              </tr>
            </thead>
            <tbody>
              {rows.map(a => {
                const sm = STATUS_META[a.status];
                const pm = PRIORITY_META[a.priority];
                return (
                  <tr key={a.id} className="lb-row" onClick={() => setOpenAction(a)}>
                    <td>
                      <div className="lb-name">{a.title}</div>
                      <div className="lb-sub">{a.id} · {a.detail.length > 70 ? a.detail.slice(0,70) + '…' : a.detail}</div>
                    </td>
                    <td><span className="pill" style={{ background:'#F1F5F9', color:'#475569' }}>{a.sourceLabel}</span></td>
                    <td>{a.location ? <span className="lb-name" style={{ fontSize: 12.5 }}>{a.loc}</span> : <span className="muted">Network</span>}</td>
                    <td><span className="pill" style={{ background: pm.bg, color: pm.color }}>{pm.label}</span></td>
                    <td><span className="pill" style={{ background: sm.bg, color: sm.color }}><span className="pill-dot" style={{ background: sm.color }}/>{a.status}</span></td>
                    <td>{a.owner ? <span style={{ fontSize: 12.5 }}>{a.owner}</span> : <span className="muted">Unassigned</span>}</td>
                    <td>
                      {a.due
                        ? <div><div style={{ fontSize: 12.5, fontWeight: 600 }}>{a.due}</div><div className="lb-sub">{a.sla} SLA · {a.age} old</div></div>
                        : <span className="muted">—</span>
                      }
                    </td>
                    <td>
                      <div style={{ fontSize: 11.5 }}><b>{a.lastUpdate.actor}</b> · {a.lastUpdate.when}</div>
                      <div className="lb-sub" style={{ marginTop: 2 }}>{a.lastUpdate.note}</div>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </section>

      {openAction && (
        <div className="overlay" onClick={() => setOpenAction(null)}>
          <aside className="detail" onClick={(e) => e.stopPropagation()}>
            <header className="detail-head">
              <div>
                <button className="detail-back" onClick={() => setOpenAction(null)}>
                  <Icon name="arrow-right" size={12} style={{ transform: 'rotate(180deg)' }}/> Back to Action Center
                </button>
                <div className="detail-title-row">
                  <div className="detail-shop-mark"><Icon name="check" size={20} stroke={2}/></div>
                  <div>
                    <h2>{openAction.title}</h2>
                    <div className="detail-shop-meta">
                      <span><b>{openAction.id}</b></span>
                      <span>Source · {openAction.sourceLabel}</span>
                      <span>SLA · {openAction.sla}</span>
                      <span><span className="pill" style={{ background: PRIORITY_META[openAction.priority].bg, color: PRIORITY_META[openAction.priority].color }}>{PRIORITY_META[openAction.priority].label}</span></span>
                      <span><span className="pill" style={{ background: STATUS_META[openAction.status].bg, color: STATUS_META[openAction.status].color }}><span className="pill-dot" style={{ background: STATUS_META[openAction.status].color }}/>{openAction.status}</span></span>
                    </div>
                  </div>
                </div>
              </div>
              <div className="detail-head-right">
                <button className="ghost-btn small">Reassign</button>
                <button className="ghost-btn small">Change status</button>
                <button className="primary-btn" data-live="1" onClick={() => resolveTask(openAction)}>Resolve</button>
                <button className="icon-btn" onClick={() => setOpenAction(null)}><Icon name="close" size={16}/></button>
              </div>
            </header>
            <div className="detail-body">
              <div className="detail-kpis">
                <div className="dk"><div className="dk-l">Owner</div><div className="dk-v" style={{ fontSize: 14 }}>{openAction.owner || 'Unassigned'}</div><div className="dk-sub">{openAction.assignedAt ? 'Assigned ' + openAction.assignedAt : '—'}</div></div>
                <div className="dk"><div className="dk-l">Due</div><div className="dk-v" style={{ fontSize: 14 }}>{openAction.due || '—'}</div><div className="dk-sub">{openAction.age} old · {openAction.sla} SLA</div></div>
                <div className="dk"><div className="dk-l">Location</div><div className="dk-v" style={{ fontSize: 14 }}>{openAction.loc}</div><div className="dk-sub">{openAction.location || 'Network-wide'}</div></div>
                <div className="dk"><div className="dk-l">Comments</div><div className="dk-v">{openAction.comments}</div><div className="dk-sub">Resolution notes appended on close</div></div>
              </div>

              <div className="detail-grid">
                <section className="detail-block detail-block-wide">
                  <h3>Description</h3>
                  <p style={{ margin: 0, fontSize: 13, lineHeight: 1.55, color: '#1E293B' }}>{openAction.detail}</p>
                  {openAction.linkedTo && openAction.linkedTo.length > 0 && (
                    <div style={{ marginTop: 14 }}>
                      <div className="health-weight" style={{ marginBottom: 6 }}>Linked records</div>
                      {openAction.linkedTo.map(l => <span key={l} className="pill" style={{ background:'#E0E7FF', color:'#3730A3', marginRight: 6 }}>{l}</span>)}
                    </div>
                  )}
                  {openAction.resolution && (
                    <div style={{ marginTop: 16, padding: 12, background:'#DCFCE7', borderRadius: 8, fontSize: 12.5, color:'#166534' }}>
                      <b>Resolution ({openAction.resolvedAt}):</b> {openAction.resolution}
                    </div>
                  )}
                </section>

                <section className="detail-block detail-block-wide">
                  <h3>Activity & audit trail</h3>
                  <ul className="casl-audit">
                    <li>
                      <span className="casl-audit-ts">{openAction.lastUpdate.when}</span>
                      <span className="casl-audit-actor">{openAction.lastUpdate.actor}</span>
                      <span className="casl-audit-action">{openAction.lastUpdate.note}</span>
                    </li>
                    {openAction.assignedAt && (
                      <li>
                        <span className="casl-audit-ts">{openAction.assignedAt}</span>
                        <span className="casl-audit-actor">{openAction.owner || 'System'}</span>
                        <span className="casl-audit-action">Task assigned</span>
                      </li>
                    )}
                    <li>
                      <span className="casl-audit-ts">{openAction.assignedAt || '—'}</span>
                      <span className="casl-audit-actor">System · {openAction.sourceLabel}</span>
                      <span className="casl-audit-action">Auto-created from {openAction.sourceLabel} source</span>
                    </li>
                  </ul>
                  <div style={{ marginTop: 12, display:'flex', gap: 8 }}>
                    <input placeholder="Add a comment…" style={{ flex: 1, height: 36, padding: '0 12px', border:'1px solid #E2E8F0', borderRadius: 8, font: 'inherit', fontSize: 13 }}/>
                    <button className="primary-btn">Post</button>
                  </div>
                </section>
              </div>
            </div>
          </aside>
        </div>
      )}
      {newOpen && (
        <HBModal
          title="New task"
          sub="Creates a tracked task with an owner, due date and audit trail."
          onClose={() => setNewOpen(false)}
          footer={<>
            <button className="ghost-btn" onClick={() => setNewOpen(false)}>Cancel</button>
            <button className="primary-btn" onClick={createTask}><Icon name="check" size={12} stroke={2.4}/> Create task</button>
          </>}
        >
          <HBField label="Title"><input autoFocus placeholder="e.g. Follow up on Scarborough remediation plan" value={draft.title} onChange={e => setD('title', e.target.value)}/></HBField>
          <div className="hb-row-2">
            <HBField label="Location">
              <select value={draft.loc} onChange={e => setD('loc', e.target.value)}>
                {['Network','Toronto Downtown','Mississauga','Oakville','Burlington','Hamilton','Vaughan','Markham','Brampton','Richmond Hill','Scarborough'].map(o => <option key={o}>{o}</option>)}
              </select>
            </HBField>
            <HBField label="Priority">
              <select value={draft.priority} onChange={e => setD('priority', e.target.value)}>
                {['critical','high','medium','standard'].map(o => <option key={o}>{o}</option>)}
              </select>
            </HBField>
          </div>
          <div className="hb-row-2">
            <HBField label="Owner">
              <select value={draft.owner} onChange={e => setD('owner', e.target.value)}>
                {['M. Diaz (Compliance)','Y. Templeton (Managing Director)','D. Owens (Procurement)','R. Cao (Finance)','L. Tran (Operations)'].map(o => <option key={o}>{o}</option>)}
              </select>
            </HBField>
            <HBField label="Due date"><input type="date" value={draft.due} onChange={e => setD('due', e.target.value)}/></HBField>
          </div>
        </HBModal>
      )}

    </div>
  );
};

Object.assign(window, { ActionsPage });
