/* ============================================================
   Albion Financial Group — Agentic Operations Cockpit
   DATA LAYER: agents, connector geometry, scenario timeline, documents
   ============================================================ */

/* ---- Map coordinate space (fixed pixel design space) ---- */
const MAP_W = 1340, MAP_H = 862;
const NODE_W = 206, NODE_H = 94, HW = NODE_W / 2, HH = NODE_H / 2;

/* ---- Agents (9) ---- */
const AGENTS = [
  { id: 'board',      name: 'CEO & Board',            role: 'Governance',     code: 'AGT-BRD-00', x: 670,  y: 78,  tier: 'governance' },
  { id: 'secretary',  name: 'Company Secretary',      role: 'Orchestrator',   code: 'AGT-CSO-01', x: 670,  y: 268, tier: 'orchestrator' },
  { id: 'compliance', name: 'Chief Compliance Officer', role: 'Compliance',   code: 'AGT-CMP-02', x: 172,  y: 524, tier: 'function' },
  { id: 'legal',      name: 'General Counsel',        role: 'Legal',          code: 'AGT-LGL-03', x: 504,  y: 524, tier: 'function' },
  { id: 'product',    name: 'Head of Product',        role: 'Product',        code: 'AGT-PRD-04', x: 836,  y: 524, tier: 'function' },
  { id: 'audit',      name: 'Head of Internal Audit', role: 'Internal Audit', code: 'AGT-AUD-05', x: 1168, y: 524, tier: 'function' },
  { id: 'risk',       name: 'Chief Risk Officer',     role: 'Risk',           code: 'AGT-RSK-06', x: 172,  y: 766, tier: 'support' },
  { id: 'ops',        name: 'Head of Operations',     role: 'Operations',     code: 'AGT-OPS-07', x: 504,  y: 766, tier: 'support' },
  { id: 'cfo',        name: 'Chief Financial Officer', role: 'Finance',       code: 'AGT-CFO-08', x: 836,  y: 766, tier: 'support' },
];
const NODE = Object.fromEntries(AGENTS.map(a => [a.id, a]));

/* ---- Connector path builders ---- */
function edgeH(a, b) { return `M ${a.x + HW} ${a.y} L ${b.x - HW} ${b.y}`; }
function vLink(below, above) { return `M ${below.x} ${below.y - HH} L ${above.x} ${above.y + HH}`; }
function orch(a, b) {
  const sy = a.y + HH, ey = b.y - HH, my = (sy + ey) / 2;
  return `M ${a.x} ${sy} C ${a.x} ${my}, ${b.x} ${my}, ${b.x} ${ey}`;
}
function auditToBoard(a, b) {
  const sx = a.x, sy = a.y - HH, ex = b.x + HW * 0.55, ey = b.y + HH;
  return `M ${sx} ${sy} C ${sx} ${sy - 210}, ${ex + 220} ${ey + 150}, ${ex} ${ey}`;
}
function escalate(a, b) {
  const sy = a.y + HH - 8, ey = b.y + HH - 8, my = Math.max(sy, ey) + 132;
  return `M ${a.x} ${sy} C ${(a.x + b.x) / 2} ${my}, ${(a.x + b.x) / 2} ${my}, ${b.x} ${ey}`;
}

const CONNECTORS = [
  // structural orchestration (faint, always on)
  { id: 'sec-board', kind: 'spine',     d: vLink(NODE.secretary, NODE.board) },
  { id: 'sec-comp',  kind: 'structure', d: orch(NODE.secretary, NODE.compliance) },
  { id: 'sec-legal', kind: 'structure', d: orch(NODE.secretary, NODE.legal) },
  { id: 'sec-prod',  kind: 'structure', d: orch(NODE.secretary, NODE.product) },
  { id: 'sec-audit', kind: 'structure', d: orch(NODE.secretary, NODE.audit) },
  { id: 'sec-risk',  kind: 'structure', d: orch(NODE.secretary, NODE.risk) },
  { id: 'sec-ops',   kind: 'structure', d: orch(NODE.secretary, NODE.ops) },
  { id: 'sec-cfo',   kind: 'structure', d: orch(NODE.secretary, NODE.cfo) },
  // work pipeline (visible handoff arrows)
  { id: 'comp-legal', kind: 'flow', arrow: true, d: edgeH(NODE.compliance, NODE.legal) },
  { id: 'legal-prod', kind: 'flow', arrow: true, d: edgeH(NODE.legal, NODE.product) },
  { id: 'prod-audit', kind: 'flow', arrow: true, d: edgeH(NODE.product, NODE.audit) },
  { id: 'audit-board', kind: 'flow', arrow: true, d: auditToBoard(NODE.audit, NODE.board) },
  // escalation (hidden until fired)
  { id: 'audit-prod-esc', kind: 'escalation', arrow: true, d: escalate(NODE.audit, NODE.product) },
];

/* ---- Simulated calendar helpers ---- */
const YEAR = 2026;
const MONTHS = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
function dayToDate(day) {
  const d = new Date(Date.UTC(YEAR, 0, 1) + day * 86400000);
  return { dd: d.getUTCDate(), mon: MONTHS[d.getUTCMonth()], q: 'Q' + (Math.floor(d.getUTCMonth() / 3) + 1), monIdx: d.getUTCMonth() };
}
function stamp(day) {
  const dt = dayToDate(day);
  const hh = String(8 + (day * 7) % 9).padStart(2, '0');
  const mm = String((day * 37) % 60).padStart(2, '0');
  return `${String(dt.dd).padStart(2,'0')} ${dt.mon} · ${hh}:${mm}`;
}

/* ============================================================
   EVENT TIMELINE
   feedType: mandate | handoff | produce | escalation | resolve | ambient | inject
   ============================================================ */
const EVENTS = [
  /* ---------- HERO: FCA Fair Value (savings) ---------- */
  { id:'h1', day:1, actor:'secretary', set:{secretary:'active'}, feedType:'mandate',
    from:'Regulatory Intelligence', to:'Company Secretary',
    title:'FCA PS26/4 — Fair Value (savings) ingested & triaged',
    detail:'New on-sale vs back-book pricing expectations under Consumer Duty. Mandate FV-26-0093 opened.' },

  { id:'h2', day:3, token:{c:'sec-comp', tone:'work', label:'Mandate'}, set:{compliance:'active'}, feedType:'handoff',
    from:'Company Secretary', to:'Compliance',
    title:'Fair Value Gap Assessment commissioned',
    detail:'Compliance instructed to assess Retail savings back-book against on-sale rates.' },

  { id:'h3', day:6, artifact:'gap', set:{compliance:'active'}, feedType:'produce', mark:'compliance',
    from:'Compliance', to:'—',
    title:'Gap Assessment: 487,000 customers on 0.75% vs 4.10% on-sale',
    detail:'335bps differential across £3.84bn of Heritage Saver balances. Potential customer detriment quantified.' },

  { id:'h4', day:8, token:{c:'comp-legal', tone:'work', label:'Gap Assessment'}, set:{compliance:'done', legal:'active'}, feedType:'handoff',
    from:'Compliance', to:'Legal', artifact:'gap',
    title:'Gap Assessment referred for regulatory opinion',
    detail:'Counsel asked to confirm the redress obligation and limitation period.' },

  { id:'h5', day:11, artifact:'legal', set:{legal:'active'}, feedType:'produce', mark:'legal',
    from:'Legal', to:'—',
    title:'Counsel\u2019s Opinion: remediation obligation confirmed (PRIN 2A)',
    detail:'Redress period assessed; preliminary exposure £41.2m. Skilled-persons (s166) risk flagged.' },

  { id:'h6', day:13, token:{c:'legal-prod', tone:'work', label:'Opinion'}, set:{legal:'done', product:'active'}, feedType:'handoff',
    from:'Legal', to:'Product', artifact:'legal',
    title:'Opinion handed to Product for remediation design',
    detail:'Product to build customer migration, redress and communications plan.' },

  { id:'h7', day:16, set:{product:'active'}, feedType:'produce',
    from:'Product', to:'—',
    title:'Remediation plan drafted — auto-uplift to 3.85% AER',
    detail:'487k accounts migrated in tranches; redress calc engine specified.' },

  { id:'h8', day:18, token:{c:'prod-audit', tone:'work', label:'Plan v1'}, set:{product:'done', audit:'active'}, feedType:'handoff',
    from:'Product', to:'Internal Audit',
    title:'Remediation plan submitted for assurance',
    detail:'Audit to test scope, redress methodology and completeness.' },

  { id:'h9', day:21, token:{c:'audit-prod-esc', tone:'escalation', label:'REJECTED', dur:1350},
    set:{audit:'done', product:'escalate'}, feedType:'escalation',
    from:'Internal Audit', to:'Product',
    title:'SIGN-OFF REJECTED — redress period understated (24mo \u2192 60mo)',
    detail:'Back-book detriment must run from product inception, not rule date. Plan returned for revision.' },

  { id:'h10', day:24, token:{c:'prod-audit', tone:'work', label:'Plan v2'}, set:{product:'done', audit:'active'}, feedType:'handoff',
    from:'Product', to:'Internal Audit',
    title:'Plan rev.2 resubmitted — redress 60mo, exposure £41.2m \u2192 £58.9m',
    detail:'Scope widened to full back-book inception. Calculation re-run and reconciled.' },

  { id:'h11', day:27, set:{audit:'active'}, feedType:'produce',
    from:'Internal Audit', to:'—',
    title:'Reasonable-assurance opinion issued — plan adequate & complete',
    detail:'No high-priority findings remaining. Cleared for Board.' },

  { id:'h12', day:29, token:{c:'audit-board', tone:'sign', label:'Board pack'}, set:{audit:'done', board:'active'}, feedType:'handoff',
    from:'Internal Audit', to:'CEO & Board',
    title:'Fair Value remediation pack tabled for resolution',
    detail:'Gap Assessment, Counsel\u2019s Opinion and Audit Opinion bundled for the Board.' },

  { id:'h13', day:32, artifact:'board', set:{board:'done'}, feedType:'resolve', mark:'board',
    from:'CEO & Board', to:'—',
    title:'Resolution 2026-14 PASSED — £58.9m remediation approved',
    detail:'Rate uplift effective 01 Jul; FCA notification authorised; execution delegated to Product.' },

  { id:'h14', day:34, token:{c:'sec-board', tone:'work', label:'Close'}, set:{secretary:'done'}, feedType:'mandate',
    from:'Company Secretary', to:'—',
    title:'Mandate FV-26-0093 closed — FCA notification filed',
    detail:'End-to-end cycle: 34 days, 5 agents, 1 escalation, 3 governing artifacts.' },

  /* ---------- BACKGROUND: ambient living-bank activity ---------- */
  { id:'b1', day:42, pulse:['risk'], feedType:'ambient', from:'Chief Risk Officer', to:'—',
    title:'APP fraud model v4 recalibrated — false positives \u221218%', detail:'Live across all payment rails.' },
  { id:'b2', day:63, pulse:['cfo'], feedType:'ambient', from:'Chief Financial Officer', to:'—',
    title:'PRA regulatory return (COREP) prepared & validated', detail:'Submitted ahead of deadline.' },
  { id:'b3', day:88, pulse:['ops'], feedType:'ambient', from:'Head of Operations', to:'—',
    title:'Faster Payments incident #4471 — root cause closed', detail:'SLA restored within 41 minutes.' },
  { id:'b4', day:121, pulse:['compliance'], feedType:'ambient', from:'Compliance', to:'—',
    title:'Vulnerable Customers policy refresh published to all agents', detail:'Aligned to FG21/1 guidance.' },
  { id:'b5', day:149, pulse:['product'], feedType:'ambient', from:'Head of Product', to:'—',
    title:'Overdraft representative APR review — no fair-value breach', detail:'Annual benchmark complete.' },
  { id:'b6', day:178, pulse:['risk','audit'], feedType:'ambient', from:'Chief Risk Officer', to:'Internal Audit',
    title:'Climate stress-test ICAAP inputs handed off', detail:'2026 PRA scenario, ready for assurance.' },
  { id:'b7', day:206, pulse:['audit'], feedType:'ambient', from:'Internal Audit', to:'—',
    title:'H1 audit plan complete — 0 high findings', detail:'12 of 21 reviews closed YTD.' },
  { id:'b8', day:238, pulse:['cfo','board'], feedType:'ambient', from:'Chief Financial Officer', to:'Board',
    title:'Consumer Duty annual board report submitted', detail:'Outcomes monitoring across 4 duties.' },
  { id:'b9', day:271, pulse:['secretary'], feedType:'ambient', from:'Company Secretary', to:'—',
    title:'AGM 2026 notice & resolutions circulated', detail:'Statutory 21-day period observed.' },
  { id:'b10', day:301, pulse:['compliance'], feedType:'ambient', from:'Compliance', to:'—',
    title:'FCA Dear CEO letter (motor finance) — applicability NIL', detail:'No relevant book held.' },
  { id:'b11', day:331, pulse:['ops'], feedType:'ambient', from:'Head of Operations', to:'—',
    title:'Year-end change freeze enacted across all systems', detail:'Effective to 05 Jan 2027.' },
  { id:'b12', day:356, pulse:['board'], feedType:'ambient', from:'CEO & Board', to:'—',
    title:'FY26 strategy review — agentic operating model ratified', detail:'Coverage extended to Wholesale.' },
];

/* ---- Inject (presenter) events — fire at current sim day ---- */
const INJECTS = [
  { id:'inj-dearceo', label:'FCA \u201cDear CEO\u201d letter', sub:'Motor finance commissions',
    token:{c:'sec-comp', tone:'work', label:'Dear CEO'}, set:{secretary:'active', compliance:'active'}, feedType:'inject',
    from:'PRESENTER INJECT', to:'Compliance',
    title:'FCA \u201cDear CEO\u201d letter received — applicability assessment opened',
    detail:'Company Secretary triages; Compliance to scope exposure within 5 working days.' },
  { id:'inj-outage', label:'Operational incident', sub:'Card payments outage',
    token:{c:'sec-ops', tone:'escalation', label:'P1 INCIDENT'}, set:{ops:'escalate', risk:'active'}, feedType:'inject',
    from:'PRESENTER INJECT', to:'Operations',
    title:'P1 incident — card authorisations failing (Region: South)',
    detail:'Operations invokes major-incident protocol; Risk assessing customer harm.' },
  { id:'inj-rate', label:'BoE base rate move', sub:'+25bps to 4.50%',
    token:{c:'sec-cfo', tone:'work', label:'Rate +25bps'}, set:{cfo:'active', product:'active'}, feedType:'inject',
    from:'PRESENTER INJECT', to:'Finance',
    title:'Bank of England base rate +25bps — repricing impact modelled',
    detail:'Finance runs NIM model; Product reviews on-sale and back-book rates for fair-value drift.' },
  { id:'inj-whistle', label:'Whistleblower report', sub:'Routed to Internal Audit',
    token:{c:'audit-prod-esc', tone:'escalation', label:'CONFIDENTIAL', reverse:false}, set:{audit:'escalate'}, feedType:'inject',
    from:'PRESENTER INJECT', to:'Internal Audit',
    title:'Whistleblowing disclosure received — independent review launched',
    detail:'Routed confidentially to Internal Audit under the Speak-Up policy. Ring-fenced workstream.' },
];

window.AlbionData = {
  MAP_W, MAP_H, NODE_W, NODE_H, AGENTS, NODE, CONNECTORS,
  EVENTS, INJECTS, dayToDate, stamp, MONTHS, YEAR,
};
