/* global React */

// =====================================================================
// SAMPLE DATA — Dallas County vocabulary (Sheriff, HHS, Jury, Constables,
// JPs, Treasurer, Clerks). Fake numbers, real-feeling names.
// =====================================================================

const SOURCES = [
  { code: '505O', dept: 'Sheriff',     name: 'Main bond fund (Peachtree/Sage) — paused w/ AP Auto', ingest: 'system', auto_ack: false, recipients: 4, paused: true },
  { code: '505B', dept: 'Sheriff',     name: 'Out-of-county bond receipts (QB)', ingest: 'system', auto_ack: false, recipients: 4 },
  { code: 'HHS-RNT', dept: 'HHS',      name: 'Rent assistance (KineTech + Access) — paused w/ AP Auto', ingest: 'system', auto_ack: true, recipients: 6, paused: true },
  { code: 'HHS-GRT', dept: 'HHS',      name: 'Grant disbursements', ingest: 'system', auto_ack: true, recipients: 6 },
  { code: 'JURY',  dept: 'Treasurer',  name: 'Jury daily payouts (Tyler JMS + Adobe)', ingest: 'system', auto_ack: false, recipients: 3 },
  { code: '502',   dept: 'County Clerk', name: 'Cash bonds 502', ingest: 'human', auto_ack: false, recipients: 3 },
  { code: '504B',  dept: 'District Clerk', name: 'Cash bonds 504B', ingest: 'human', auto_ack: false, recipients: 3 },
  { code: 'CON-1', dept: 'Constable',  name: 'Constable Pct 1 — service fees', ingest: 'human', auto_ack: false, recipients: 2 },
  { code: 'JP-3',  dept: 'JP',         name: 'Justice of Peace Pct 3 — refunds', ingest: 'human', auto_ack: false, recipients: 2 },
  { code: 'SF-12',   dept: 'Special Funds', category: 'Legacy Macro',    name: 'Special Fund 12 — printing vendor macro',     ingest: 'human', auto_ack: false, recipients: 2 },
  { code: 'SF-REST', dept: 'Special Funds', category: 'Court Business',  name: 'Restitution disbursements (victim payouts)',  ingest: 'human', auto_ack: false, recipients: 3 },
  { code: 'SF-CB',   dept: 'Special Funds', category: 'Court Business',  name: 'Court business — sequestered juror, witness, interpreter fees', ingest: 'human', auto_ack: false, recipients: 3 },
  { code: 'SF-CHAP', dept: 'Special Funds', category: 'Chapter 19',      name: 'Chapter 19 voter registrar reimbursements',   ingest: 'human', auto_ack: false, recipients: 2 },
  { code: 'SF-LAW',  dept: 'Special Funds', category: 'Law Library',     name: 'Law library subscriptions & maintenance',     ingest: 'human', auto_ack: false, recipients: 2 },
  { code: 'DA-SEZ',  dept: 'DA',            name: 'DA seizure fund', ingest: 'human', auto_ack: false, recipients: 2 },
];

// payments: across queue states
const PAYMENTS = [
  { id: 'PMT-50412', source: '505B', payee: 'Lone Star Bail Bonds', amount: 1500.00, status: 'PaymentAckPending', batch: null,        date: '2026-05-06', desc: 'Bond refund — case 24-CR-1188', critical: true },
  { id: 'PMT-50415', source: '505B', payee: 'Aabbott Surety Co.',  amount: 750.00,  status: 'BatchAckPending',   batch: 'B-3041',     date: '2026-05-06', desc: 'Bond refund — case 25-CR-0042' },
  { id: 'PMT-50418', source: '505O', payee: 'Texas Surety Group',  amount: 4250.00, status: 'Validating',        batch: null,        date: '2026-05-07', desc: 'Bond refund — case 25-CR-2210', critical: true },
  { id: 'PMT-50420', source: '505O', payee: 'Pickens & Co Bail',   amount: 1200.00, status: 'Pending',           batch: null,        date: '2026-05-07', desc: 'Bond refund — multi-leg' },
  { id: 'PMT-50422', source: 'HHS-RNT', payee: 'Bluebonnet Apts LLC', amount: 1145.00, status: 'Acknowledged',  batch: 'B-3038',     date: '2026-05-05', desc: 'Rent assist · case mgr K.Lee · 04/26' },
  { id: 'PMT-50423', source: 'HHS-RNT', payee: 'Live Oak Properties', amount: 980.00,  status: 'Acknowledged',  batch: 'B-3038',     date: '2026-05-05', desc: 'Rent assist · case mgr K.Lee · 04/26' },
  { id: 'PMT-50425', source: 'HHS-GRT', payee: 'United Way Dallas',  amount: 25000.00, status: 'Transmitted',   batch: 'B-3037',     date: '2026-05-04', desc: 'Q2 grant disbursement' },
  { id: 'PMT-50428', source: 'JURY',    payee: 'Maria Hernandez',    amount: 40.00,    status: 'Posted',        batch: 'B-3035',     date: '2026-05-03', desc: 'Juror per diem 2026-05-03' },
  { id: 'PMT-50429', source: 'JURY',    payee: 'Brandon Park',        amount: 40.00,   status: 'Posted',        batch: 'B-3035',     date: '2026-05-03', desc: 'Juror per diem 2026-05-03' },
  { id: 'PMT-50431', source: 'JP-3',    payee: 'Aaron Whitaker',      amount: 285.00,  status: 'Failed',        batch: null,        date: '2026-05-07', desc: 'Court fee refund — duplicate?', critical: true },
  { id: 'PMT-50432', source: 'CON-1',   payee: 'Donna Estrada',       amount: 75.00,   status: 'Pending',       batch: null,        date: '2026-05-07', desc: 'Service of writ — case 25-CV-0900' },
  { id: 'PMT-50434', source: '502',     payee: 'Hassan Mehdi',        amount: 500.00,  status: 'Paid',          batch: 'B-3030',     date: '2026-04-29', desc: 'Cash bond refund — case 25-CR-1108' },
  { id: 'PMT-50436', source: 'SF-12',   payee: 'Trinity Press Co.',   amount: 4150.00, status: 'PayeeAckPending', batch: null,      date: '2026-05-07', desc: 'Printing services — Special Fund 12', critical: true },
  { id: 'PMT-50451', source: 'SF-REST', payee: 'Elena Vasquez',       amount: 2400.00, status: 'BatchAckPending', batch: 'B-3045', date: '2026-05-07', desc: 'Restitution · case 24-CR-3380 · victim payout' },
  { id: 'PMT-50452', source: 'SF-REST', payee: 'Marcus Webb',         amount: 850.00,  status: 'Validated',       batch: null,     date: '2026-05-07', desc: 'Restitution · case 25-CR-0117 · 6th installment' },
  { id: 'PMT-50453', source: 'SF-CB',   payee: 'Hilda Romero',        amount: 320.00,  status: 'Pending',         batch: null,     date: '2026-05-07', desc: 'Court interpreter — Spanish · 3 sessions' },
  { id: 'PMT-50454', source: 'SF-CB',   payee: 'David Park',          amount: 75.00,   status: 'Posted',          batch: 'B-3036', date: '2026-05-03', desc: 'Material witness · case 25-CR-1820' },
  { id: 'PMT-50455', source: 'SF-LAW',  payee: 'Thomson Reuters',     amount: 12400.00,status: 'Acknowledged',    batch: 'B-3044', date: '2026-05-06', desc: 'Westlaw subscription Q3 renewal' },
  { id: 'PMT-50438', source: 'DA-SEZ',  payee: 'CryptoTrace LLC',     amount: 8800.00, status: 'BatchAckPending', batch: 'B-3041',  date: '2026-05-06', desc: 'Forensics retainer' },
  { id: 'PMT-50441', source: 'HHS-RNT', payee: 'Casa Bella Apts',     amount: 1100.00, status: 'Cleared',       batch: 'B-3025',    date: '2026-04-22', desc: 'Rent assist · case mgr R.Ortiz · 04/22' },
];

const PAYEES = [
  { id: 'PAY-00102', name: 'Lone Star Bail Bonds',  type: 'SUPPLIER', status: 'Acknowledged',     tin: '74-***1188', addr: '4400 Ross Ave, Dallas, TX 75204', recent: 12 },
  { id: 'PAY-00118', name: 'Aabbott Surety Co.',    type: 'SUPPLIER', status: 'Acknowledged',     tin: '76-***0421', addr: '1212 Main St, Dallas, TX 75202', recent: 7 },
  { id: 'PAY-00127', name: 'Texas Surety Group',    type: 'SUPPLIER', status: 'Acknowledged',     tin: '74-***2210', addr: '900 Jackson, Dallas, TX 75202', recent: 4 },
  { id: 'PAY-00203', name: 'Bluebonnet Apts LLC',   type: 'SUPPLIER', status: 'Acknowledged',     tin: '47-***5511', addr: '8800 Park Ln, Dallas, TX 75231', recent: 3 },
  { id: 'PAY-00208', name: 'Live Oak Properties',   type: 'PARTY',    status: 'PayeeAckPending',  tin: '47-***6620', addr: '1450 Live Oak St, Dallas, TX 75204', recent: 0, ackBlocker: true },
  { id: 'PAY-00301', name: 'United Way Dallas',     type: 'SUPPLIER', status: 'Acknowledged',     tin: '75-***0001', addr: '1800 N Lamar, Dallas, TX 75202', recent: 14 },
  { id: 'PAY-00404', name: 'Maria Hernandez',       type: 'PARTY',    status: 'Acknowledged',     tin: '***-**-4421', addr: '5022 Live Oak, Dallas, TX 75206', recent: 1, individual: true },
  { id: 'PAY-00405', name: 'Brandon Park',          type: 'PARTY',    status: 'Acknowledged',     tin: '***-**-7711', addr: '203 Hill St, Mesquite, TX 75150', recent: 1, individual: true },
  { id: 'PAY-00501', name: 'Aaron Whitaker',        type: 'PARTY',    status: 'Acknowledged',     tin: '***-**-9931', addr: '1010 Belmont, Dallas, TX 75206', recent: 2, individual: true },
  { id: 'PAY-00608', name: 'Trinity Press Co.',     type: 'PARTY',    status: 'PayeeAckPending',  tin: '74-***0009', addr: '700 N Stemmons, Dallas, TX 75207', recent: 0, ackBlocker: true, isNew: true },
];

const BATCHES = [
  { id: 'B-3041', source: '505B + DA-SEZ', count: 2, total: 9550.00, status: 'BatchAckPending',  preparer: 'k.lee',  date: '2026-05-06', critical: 1 },
  { id: 'B-3038', source: 'HHS-RNT',       count: 2, total: 2125.00, status: 'Acknowledged',     preparer: 'auto',   date: '2026-05-05', critical: 0 },
  { id: 'B-3037', source: 'HHS-GRT',       count: 1, total: 25000.00, status: 'Transmitted',     preparer: 'r.ortiz', date: '2026-05-04', critical: 0 },
  { id: 'B-3035', source: 'JURY',          count: 142, total: 5680.00, status: 'Posted',          preparer: 'd.brooks', date: '2026-05-03', critical: 0 },
  { id: 'B-3030', source: '502',           count: 8, total: 4500.00, status: 'Paid',              preparer: 'k.lee',   date: '2026-04-29', critical: 0 },
  { id: 'B-3025', source: 'HHS-RNT',       count: 38, total: 41100.00, status: 'Cleared',         preparer: 'auto',    date: '2026-04-22', critical: 0 },
  { id: 'B-3045', source: 'SF-REST',       count: 7,  total: 14250.00, status: 'BatchAckPending', preparer: 'j.miles', date: '2026-05-07', critical: 0 },
  { id: 'B-3044', source: 'SF-LAW',        count: 1,  total: 12400.00, status: 'Acknowledged',    preparer: 'j.miles', date: '2026-05-06', critical: 0 },
  { id: 'B-3036', source: 'SF-CB',         count: 4,  total: 1180.00,  status: 'Posted',          preparer: 'j.miles', date: '2026-05-03', critical: 0 },
];

// status -> short label + which queue tab it belongs in (per 1.10)
const STATUS = {
  // unified lexicon: noun-state, lowercase, no "?" suffixes, no jargon
  Pending:            { label: 'new',                queue: 'today' },
  Validating:         { label: 'checking',           queue: 'today' },
  Validated:          { label: 'ready to review',    queue: 'today' },
  Failed:             { label: 'has errors',         queue: 'needsAttention', tone: 'red' },
  PayeeAckPending:    { label: 'awaiting payee review',   queue: 'verification', tone: 'hl' },
  PaymentAckPending:  { label: 'awaiting payment review', queue: 'verification', tone: 'hl' },
  BatchAckPending:    { label: 'awaiting batch review',   queue: 'verification', tone: 'hl' },
  Acknowledged:       { label: 'reviewed',           queue: 'apReview' },
  Transmitting:       { label: 'sending',            queue: 'apReview' },
  Transmitted:        { label: 'sent to fusion',     queue: 'apReview' },
  Received:           { label: 'received by fusion', queue: 'apReview' },
  Posted:             { label: 'posted',             queue: 'apReview' },
  Paid:               { label: 'paid',               queue: 'settled' },
  CheckPrinted:       { label: 'check printed',      queue: 'settled' },
  Mailed:             { label: 'mailed',             queue: 'settled' },
  Cleared:            { label: 'escheated',          queue: 'settled' },
  OnHold:             { label: 'on hold',            queue: 'needsAttention', tone: 'red' },
};

const fmtMoney = (n) => '$' + n.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });

// =====================================================================
// Department filter helpers
// =====================================================================
// Maps the dept-switcher value (id) -> SOURCES.dept value(s).
const DEPT_TO_SOURCE_DEPTS = {
  sheriff:      ['Sheriff'],
  hhs:          ['HHS'],
  treasurer:    ['Treasurer'],
  constables:   ['Constable'],
  jp:           ['JP'],
  specialFunds: ['Special Funds'],
  // 'all' returns true for everything
};

const DEPT_LABEL = {
  sheriff:      "Sheriff's Office",
  hhs:          'Health & Human Services',
  treasurer:    "Treasurer's Office",
  constables:   'Constables (Pcts 1–5)',
  jp:           'Justices of the Peace',
  specialFunds: 'Special Funds',
  all:          'all departments',
};

// short pill labels (used on chips/badges)
const DEPT_SHORT = {
  Sheriff:        { id: 'sheriff',     short: 'Sheriff',     color: '#a64b0a' },
  HHS:            { id: 'hhs',         short: 'HHS',         color: '#2b6cb0' },
  Treasurer:      { id: 'treasurer',   short: 'Treasurer',   color: '#0f766e' },
  'County Clerk': { id: 'countyClerk', short: 'County Clerk',color: '#7c2d12' },
  'District Clerk': { id: 'distClerk', short: 'Dist Clerk',  color: '#7c2d12' },
  Constable:      { id: 'constable',   short: 'Constable',   color: '#7c3aed' },
  JP:             { id: 'jp',          short: 'JP',          color: '#9333ea' },
  'Special Funds':{ id: 'specialFunds',short: 'Special Funds', color: '#475569' },
  DA:             { id: 'da',          short: "DA's Office", color: '#a16207' },
};

// turn a source code into its dept descriptor (label + color)
function deptForSource(code) {
  if (!code) return null;
  // batches sometimes carry a combined source like '505B + DA-SEZ' — pick first
  const c = String(code).split(/[\s+/,]/)[0].trim();
  const src = (window.SOURCES || []).find(s => s.code === c);
  if (!src) return null;
  return DEPT_SHORT[src.dept] || { id: src.dept.toLowerCase().replace(/\s/g,''), short: src.dept, color: '#5a5246' };
}

function sourceCodesForDept(dept) {
  if (!dept || dept === 'all') return null; // null = no filter
  const deptList = DEPT_TO_SOURCE_DEPTS[dept];
  if (!deptList) return null;
  return new Set(SOURCES.filter(s => deptList.includes(s.dept)).map(s => s.code));
}

function filterPaymentsByDept(payments, dept) {
  const codes = sourceCodesForDept(dept);
  if (!codes) return payments;
  return payments.filter(p => codes.has(p.source));
}

function filterBatchesByDept(batches, dept) {
  const codes = sourceCodesForDept(dept);
  if (!codes) return batches;
  // batches.source can be combo like '505B + DA-SEZ' — match if any token in
  return batches.filter(b => {
    const toks = String(b.source).split(/\s*\+\s*|\s*,\s*/).map(s => s.trim());
    return toks.some(t => codes.has(t));
  });
}

function filterPayeesByDept(payees, dept) {
  const codes = sourceCodesForDept(dept);
  if (!codes) return payees;
  // a payee belongs to a dept if any of their PAYMENTS have a source in that dept
  const ids = new Set(
    PAYMENTS
      .filter(p => codes.has(p.source))
      .map(p => {
        const py = PAYEES.find(x => x.name === p.payee);
        return py ? py.id : null;
      })
      .filter(Boolean)
  );
  return payees.filter(p => ids.has(p.id));
}

// =====================================================================
// APPROVAL CHAIN — given a batch, compute the chain of stops it passes
// through. Some stops are optional based on source / amount / flags.
// Exposed on window so multiple screens can render the same chain.
// =====================================================================
const AUDIT_SOURCE_CODES = new Set(['HHS-GRT', 'DA-SEZ', 'SF-12', '502', '504B']);
function buildBatchChain(b) {
  const needs2L  = b.total > 25000 || (b.critical || 0) > 0;
  const firstSrc = String(b.source || '').split(/[\s+]/)[0];
  const needsAud = !!(b.auditorReview || AUDIT_SOURCE_CODES.has(firstSrc) || b.total > 10000);
  const needsTre = b.source && /HHS-GRT|DA-SEZ|JURY|505O|505B/.test(b.source);
  const s = b.status;
  const inSet = (set) => set.has(s);
  const afterDeptAck = inSet(new Set(['Acknowledged','AuditorHold','Transmitted','Received','Posted','Paid','Cleared']));
  const afterAuditor = inSet(new Set(['Acknowledged','Transmitted','Received','Posted','Paid','Cleared']));
  const afterTreasurer = afterAuditor;
  const afterAP = inSet(new Set(['Transmitted','Received','Posted','Paid','Cleared']));

  return [
    { id: 'dept', label: 'Prepared & Acknowledged',
      actor: b.preparer === 'auto' ? 'auto-ack' : b.preparer,
      when: b.date,
      state: afterDeptAck ? 'done' : (b.status === 'BatchAckPending' || b.status === 'Pending' ? 'current' : 'future') },
    { id: '2nd', label: '2nd Level Acknowledged',
      actor: needs2L ? 'm.harper' : null,
      when: needs2L && afterDeptAck ? b.date : null,
      state: !needs2L ? 'skipped' : (afterDeptAck ? 'done' : 'future') },
    { id: 'auditor', label: 'Auditor',
      actor: needsAud && afterAuditor ? 'j.cole · auditor' : null,
      when: needsAud && afterAuditor ? b.date : null,
      note: b.auditorReason,
      state: !needsAud ? 'skipped' : (afterAuditor ? 'done' : (b.status === 'AuditorHold' || (b.status === 'Acknowledged' && b.apQueue === 'auditor') ? 'current' : 'future')) },
    { id: 'treasurer', label: 'Treasurer',
      actor: needsTre && afterTreasurer ? 'p.singh · treasurer' : null,
      when: needsTre && afterTreasurer ? b.date : null,
      state: !needsTre ? 'skipped' : (afterTreasurer ? 'done' : 'future') },
    { id: 'ap', label: 'Accounts Payable',
      actor: afterAP ? 'm.tran · AP' : null,
      when: afterAP ? b.date : null,
      state: afterAP ? 'done' : (b.status === 'Acknowledged' ? 'current' : 'future') },
  ];
}

Object.assign(window, { SOURCES, PAYMENTS, PAYEES, BATCHES, STATUS, fmtMoney,
  DEPT_TO_SOURCE_DEPTS, DEPT_LABEL, DEPT_SHORT, sourceCodesForDept, deptForSource,
  filterPaymentsByDept, filterBatchesByDept, filterPayeesByDept,
  buildBatchChain });
