// Mock data for the Rate Repository prototype
const TERMINALS = [
  { code: "CNSHA", name: "Shanghai (Yangshan)", country: "CN", region: "North Asia", area: "East China", currency: "CNY" },
  { code: "CNNGB", name: "Ningbo Zhoushan", country: "CN", region: "North Asia", area: "East China", currency: "CNY" },
  { code: "CNTAO", name: "Qingdao Qianwan", country: "CN", region: "North Asia", area: "North China", currency: "CNY" },
  { code: "CNTSN", name: "Tianjin Xingang", country: "CN", region: "North Asia", area: "North China", currency: "CNY" },
  { code: "HKHKG", name: "Hong Kong (Kwai Tsing)", country: "HK", region: "North Asia", area: "South China", currency: "HKD" },
  { code: "CNYTN", name: "Shenzhen Yantian", country: "CN", region: "North Asia", area: "South China", currency: "CNY" },
  { code: "KRPUS", name: "Busan New Port", country: "KR", region: "North Asia", area: "Korea", currency: "KRW" },
  { code: "JPYOK", name: "Yokohama", country: "JP", region: "North Asia", area: "Japan", currency: "JPY" },
  { code: "SGSIN", name: "Singapore (PSA)", country: "SG", region: "Southeast Asia", area: "Singapore", currency: "SGD" },
  { code: "MYPKG", name: "Port Klang Westport", country: "MY", region: "Southeast Asia", area: "Malaysia", currency: "MYR" },
  { code: "MYTPP", name: "Tanjung Pelepas", country: "MY", region: "Southeast Asia", area: "Malaysia", currency: "MYR" },
  { code: "VNSGN", name: "Cat Lai (Ho Chi Minh)", country: "VN", region: "Southeast Asia", area: "Vietnam", currency: "VND" },
  { code: "THLCH", name: "Laem Chabang", country: "TH", region: "Southeast Asia", area: "Thailand", currency: "THB" },
  { code: "IDJKT", name: "Tanjung Priok", country: "ID", region: "Southeast Asia", area: "Indonesia", currency: "IDR" },
  { code: "INNSA", name: "Nhava Sheva (JNPT)", country: "IN", region: "South Asia Sub-Continent", area: "West India", currency: "INR" },
  { code: "INMUN", name: "Mundra", country: "IN", region: "South Asia Sub-Continent", area: "West India", currency: "INR" },
  { code: "BDCGP", name: "Chittagong", country: "BD", region: "South Asia Sub-Continent", area: "Bangladesh", currency: "BDT" },
  { code: "AUSYD", name: "Sydney (Port Botany)", country: "AU", region: "Oceania", area: "Australia East", currency: "AUD" },
  { code: "AUMEL", name: "Melbourne (Webb Dock)", country: "AU", region: "Oceania", area: "Australia East", currency: "AUD" },
  { code: "NZAKL", name: "Auckland", country: "NZ", region: "Oceania", area: "New Zealand", currency: "NZD" },
];

const COST_TYPES = [
  { code: "CY_HANDLING", name: "CY Handling", category: "CY" },
  { code: "STORAGE", name: "Storage", category: "Behavior" },
  { code: "REEFER_POWER", name: "Reefer Power", category: "Behavior" },
  { code: "REEFER_PLUG", name: "Reefer Plug In/Out", category: "Behavior" },
  { code: "EXTRA_YARD", name: "Extra Yard Work", category: "Behavior" },
  { code: "SHIFTING", name: "Shifting", category: "Behavior" },
  { code: "VGM_WEIGH", name: "VGM Weighing", category: "Behavior" },
  { code: "GATE_MOVE", name: "Gate Move", category: "CY" },
];

const CHARGE_UNITS = [
  { code: "PER_TEU", name: "Per TEU", applicable: ["CY_HANDLING","SHIFTING","GATE_MOVE"] },
  { code: "PER_FEU", name: "Per FEU", applicable: ["CY_HANDLING","SHIFTING","GATE_MOVE"] },
  { code: "PER_BOX", name: "Per Box", applicable: ["CY_HANDLING","VGM_WEIGH","SHIFTING","GATE_MOVE"] },
  { code: "PER_DAY", name: "Per Day", applicable: ["STORAGE","REEFER_POWER"] },
  { code: "PER_MOVE", name: "Per Move", applicable: ["REEFER_PLUG","EXTRA_YARD","SHIFTING"] },
  { code: "PER_KWH", name: "Per kWh", applicable: ["REEFER_POWER"] },
];

const ROE = {
  CNY: 7.254, HKD: 7.819, KRW: 1342.1, JPY: 152.4, SGD: 1.346,
  MYR: 4.682, VND: 25410, THB: 35.8, IDR: 15780, INR: 83.42,
  BDT: 117.8, AUD: 1.512, NZD: 1.668, USD: 1.0,
};

// Build a realistic-sized rate dataset
const RATES = (() => {
  const rows = [];
  let id = 10000;
  const dates = ["2025-01-01","2024-07-01","2024-01-01","2023-07-01","2025-03-15"];
  // Heavily Active-weighted so the calculator and lists always find live data.
  // We sprinkle in a few Draft/Superseded for realism.
  const focals = ["L. Tanaka","M. Chen","R. Singh","P. Wijaya","K. Park","S. Nguyen","A. Patel"];

  function emit(t, ct, u, opts = {}) {
    const eff = opts.eff || dates[id % dates.length];
    const status = opts.status || ((id % 23 === 0) ? "Draft" : (id % 37 === 0) ? "Superseded" : "Active");
    let base = ({CY_HANDLING:120, STORAGE:8, REEFER_POWER:14, REEFER_PLUG:35, EXTRA_YARD:90, SHIFTING:55, VGM_WEIGH:25, GATE_MOVE:18}[ct.code] || 50);
    if (u.code === "PER_FEU") base *= 1.7;
    if (u.code === "PER_KWH") base = base / 8;
    if (opts.tierMul) base *= opts.tierMul;
    const rate = +(base * ROE[t.currency] / ROE.USD * (0.85 + ((id*13)%30)/100)).toFixed(2);
    rows.push({
      id: `R-${id++}`,
      terminal: t.code,
      terminalName: t.name,
      region: t.region,
      area: t.area,
      costType: ct.code,
      costTypeName: ct.name,
      chargeUnit: u.code,
      chargeUnitName: u.name,
      rateLocal: rate,
      currency: t.currency,
      effective: eff,
      expiry: "2025-12-31",
      contractRef: `CTR-APA-2025-${(id%900)+100}`,
      tier: opts.tier || null,
      status,
      modifiedBy: focals[id % focals.length],
      modifiedAt: "2025-04-" + String((id%28)+1).padStart(2,"0") + " 14:" + String((id%59)).padStart(2,"0"),
    });
  }

  TERMINALS.forEach(t => {
    COST_TYPES.forEach(ct => {
      const units = CHARGE_UNITS.filter(u => u.applicable.includes(ct.code));
      if (ct.code === "STORAGE") {
        // Always emit two ACTIVE storage tier rows (Day 1–3 and Day 4+)
        const u = units.find(x => x.code === "PER_DAY") || units[0];
        emit(t, ct, u, { tier: "Day 1–3", tierMul: 1.0, status: "Active" });
        emit(t, ct, u, { tier: "Day 4+", tierMul: 2.2, status: "Active" });
      } else {
        // One Active rate per cost type · primary unit
        const u = units[0];
        if (u) emit(t, ct, u, { status: "Active" });
        // Sometimes add a second unit variant (e.g. PER_FEU alongside PER_TEU)
        if (units[1] && (id % 3 === 0)) emit(t, ct, units[1], { status: "Active" });
      }
    });
  });
  return rows;
})();

const REGIONS = ["North Asia","Southeast Asia","South Asia Sub-Continent","Oceania"];

const PERSONAS = {
  rate_calculator: {
    name: "Aiko Tanaka", title: "Ops Coordinator, North Asia",
    role: "rate_calculator", regions: ["North Asia"], areas: ["East China","North China"],
    avatar: "AT", color: "#7a8fa6",
  },
  read: {
    name: "Marcus Chen", title: "Trade Lane Analyst, Intra-Asia",
    role: "read", regions: ["North Asia","Southeast Asia"], areas: ["—"],
    avatar: "MC", color: "#3d6e8e",
  },
  edit: {
    name: "Priya Wijaya", title: "Rate Focal, SE Asia",
    role: "edit", regions: ["Southeast Asia"], areas: ["Singapore","Malaysia"],
    avatar: "PW", color: "#1f6f5c",
  },
  fbp: {
    name: "Ravi Singh", title: "Finance Business Partner, APA",
    role: "fbp", regions: ["North Asia","Southeast Asia","South Asia Sub-Continent","Oceania"], areas: ["—"],
    avatar: "RS", color: "#8a4d2e",
  },
  procurement: {
    name: "Sofia Lindqvist", title: "Procurement Manager, APA",
    role: "procurement", regions: ["North Asia","Southeast Asia","South Asia Sub-Continent","Oceania"], areas: ["—"],
    avatar: "SL", color: "#6b3f8a",
  },
  admin: {
    name: "Daniel Park", title: "System Administrator, Ocean Finance",
    role: "admin", regions: ["Global"], areas: ["—"],
    avatar: "DP", color: "#1f3a5c",
  },
  unknown: {
    name: "Guest User", title: "Pending Access",
    role: "unknown", regions: [], areas: [],
    avatar: "?", color: "#6b7280",
  },
};

const PERMS = {
  //                  viewRates  rateHealth  editRates  importRates  export  aiAssistant  rebateMonitor  volumeTracker  tcoAnalysis  roeTable  admin  accessOnly
  unknown:         { viewRates: false, rateHealth: false, editRates: false, importRates: false, export: false, aiAssistant: false, rebateMonitor: false, volumeTracker: false, tcoAnalysis: false, roeTable: false, admin: false, accessOnly: true },
  rate_calculator: { viewRates: false, rateHealth: false, editRates: false, importRates: false, export: false, aiAssistant: false, rebateMonitor: false, volumeTracker: false, tcoAnalysis: false, roeTable: false, admin: false },
  read:            { viewRates: true,  rateHealth: true,  editRates: false, importRates: false, export: false, aiAssistant: false, rebateMonitor: false, volumeTracker: false, tcoAnalysis: false, roeTable: true,  admin: false },
  edit:            { viewRates: true,  rateHealth: true,  editRates: true,  importRates: true,  export: false, aiAssistant: false, rebateMonitor: false, volumeTracker: true,  tcoAnalysis: false, roeTable: true,  admin: false },
  fbp:             { viewRates: true,  rateHealth: true,  editRates: false, importRates: false, export: true,  aiAssistant: true,  rebateMonitor: true,  volumeTracker: true,  tcoAnalysis: true,  roeTable: true,  admin: false },
  procurement:     { viewRates: true,  rateHealth: true,  editRates: false, importRates: true,  export: true,  aiAssistant: true,  rebateMonitor: true,  volumeTracker: true,  tcoAnalysis: true,  roeTable: true,  admin: false },
  admin:           { viewRates: true,  rateHealth: true,  editRates: true,  importRates: true,  export: true,  aiAssistant: true,  rebateMonitor: true,  volumeTracker: true,  tcoAnalysis: true,  roeTable: true,  admin: true  },
};

const AUDIT = [
  { ts: "2025-05-12 16:42", user: "P. Wijaya", event: "Rate Updated", target: "R-10043 · SGSIN · Storage", detail: "180.00 SGD → 195.00 SGD", ip: "10.42.18.7" },
  { ts: "2025-05-12 15:08", user: "S. Lindqvist", event: "Contract Uploaded (DIFY)", target: "CTR-APA-2025-217.pdf", detail: "12 rows extracted, 11 imported", ip: "10.42.18.91" },
  { ts: "2025-05-12 14:51", user: "R. Singh", event: "Rate Sheet Exported", target: "North Asia · Q2 2025", detail: "1,284 rows · .xlsx", ip: "10.42.18.40" },
  { ts: "2025-05-12 12:13", user: "D. Park", event: "Access Approved", target: "marcus.chen@…", detail: "read · North Asia, SE Asia", ip: "10.42.18.2" },
  { ts: "2025-05-12 11:02", user: "P. Wijaya", event: "Rate Created", target: "R-10841 · MYPKG · Reefer Power", detail: "14.80 MYR / day", ip: "10.42.18.7" },
  { ts: "2025-05-12 10:30", user: "L. Tanaka", event: "Calculator Used", target: "CNSHA · CY Handling × 4,200 TEU", detail: "Result: USD 504,840", ip: "10.42.18.55" },
  { ts: "2025-05-12 09:14", user: "D. Park", event: "Metadata Updated", target: "Terminal · CNYTN", detail: "Area: South China → South China", ip: "10.42.18.2" },
  { ts: "2025-05-11 17:48", user: "M. Chen", event: "User Login", target: "marcus.chen@…", detail: "SSO · Azure AD", ip: "10.42.18.40" },
  { ts: "2025-05-11 16:22", user: "D. Park", event: "ROE Updated", target: "CNY/USD", detail: "0.13751 → 0.13784", ip: "10.42.18.2" },
];

const ACCESS_REQUESTS = [
  { id: "AR-2041", requester: "Hana Watanabe", email: "hana.watanabe@…", role: "read", regions: ["North Asia"], areas: ["Japan"], justification: "Need visibility into JP terminal rates for monthly variance reporting.", submitted: "2025-05-12 09:14", status: "Pending", sla: 1, manager: "K. Park" },
  { id: "AR-2040", requester: "Diego Alvarez", email: "diego.alvarez@…", role: "fbp", regions: ["Oceania"], areas: ["—"], justification: "FBP rotation to APA Oceania — analytical access required for FY26 budget cycle.", submitted: "2025-05-09 11:30", status: "Pending", sla: 4, manager: "S. Lindqvist" },
  { id: "AR-2039", requester: "Yuki Sato", email: "yuki.sato@…", role: "edit", regions: ["North Asia"], areas: ["Japan"], justification: "Designated Rate Focal for Japan terminals starting May.", submitted: "2025-05-12 08:02", status: "Pending", sla: 1, manager: "K. Park" },
  { id: "AR-2038", requester: "Lakshmi Iyer", email: "lakshmi.iyer@…", role: "read", regions: ["South Asia Sub-Continent"], areas: ["West India"], justification: "Trade lane analyst, requires read access for cost modelling.", submitted: "2025-05-08 14:22", status: "Approved", sla: 0, manager: "R. Singh" },
  { id: "AR-2037", requester: "Olga Petrov", email: "olga.petrov@…", role: "procurement", regions: ["Southeast Asia"], areas: ["—"], justification: "New procurement hire covering SEA terminal contracts.", submitted: "2025-05-07 10:11", status: "Rejected", sla: 0, manager: "S. Lindqvist" },
];

const TERMINAL_BY_CODE = Object.fromEntries(TERMINALS.map(t => [t.code, t]));

// ============================================================
// v1.1 additions — Equipment, Cargo, Volume, Rebate, MVC, TCO
// ============================================================

const EQUIPMENT = ["20GP", "40GP", "40HC", "45HC", "20RF", "40RF"];
const CARGO_TYPES = ["Dry", "Reefer", "Dangerous", "OOG"];
const MOVE_TYPES = ["Import", "Export", "Transship", "Repositioning"];

// Monthly volume (last 12 months) per terminal — aggregated TEU
const VOLUME = (() => {
  const months = [];
  // 2024-06 → 2025-05
  for (let i = 11; i >= 0; i--) {
    const d = new Date(2025, 4 - i, 1);
    months.push(`${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}`);
  }
  const rows = [];
  TERMINALS.forEach((t, ti) => {
    const baseMonthly = 2000 + (ti % 7) * 800 + (ti * 311 % 1500);
    months.forEach((m, mi) => {
      // seasonal sine + slight YoY growth + noise
      const seasonal = 1 + 0.15 * Math.sin((mi / 12) * Math.PI * 2 - 0.5);
      const trend = 1 + (mi - 6) * 0.005;
      const noise = 0.92 + ((ti * 13 + mi * 37) % 16) / 100;
      const teu = Math.round(baseMonthly * seasonal * trend * noise);
      const moves = Math.round(teu * 0.62);
      rows.push({ terminal: t.code, terminalName: t.name, region: t.region, period: m, teu, moves });
    });
  });
  return { months, rows };
})();

// MVC (Minimum Volume Commitment) per terminal — only some terminals have it
const MVC = {
  CNSHA: { annual: 120000, penaltyRate: 28, focal: "L. Tanaka" },
  CNNGB: { annual: 72000, penaltyRate: 25, focal: "L. Tanaka" },
  CNTAO: { annual: 60000, penaltyRate: 30, focal: "M. Chen" },
  CNTSN: { annual: 48000, penaltyRate: 26, focal: "M. Chen" },
  SGSIN: { annual: 96000, penaltyRate: 38, focal: "P. Wijaya" },
  MYPKG: { annual: 54000, penaltyRate: 22, focal: "P. Wijaya" },
  INNSA: { annual: 36000, penaltyRate: 18, focal: "R. Singh" },
};

// Year-to-date volume per terminal (Jan–May 2025)
const YTD_VOLUME = (() => {
  const out = {};
  TERMINALS.forEach(t => {
    const ytd = VOLUME.rows.filter(v => v.terminal === t.code && v.period >= "2025-01").reduce((s, v) => s + v.teu, 0);
    out[t.code] = ytd;
  });
  return out;
})();

// Rebate contracts
const REBATES = [
  {
    id: "RB-2025-001",
    terminal: "CNSHA",
    contractRef: "CTR-APA-2025-104",
    type: "Tiered Rebate",
    scope: "CY Handling",
    period: "Annual",
    settlement: "Credit Note",
    deadline: 60,
    currency: "CNY",
    effective: "2025-01-01", expiry: "2025-12-31",
    status: "Active",
    accruedYTD: 184650, accruedYTDLocal: 1339450,
    tiers: [
      { name: "Tier 1 (Base)", min: 0,      max: 19999,    rate: 0,    type: "Incremental" },
      { name: "Tier 2",        min: 20000,  max: 49999,    rate: 1.5,  type: "Incremental" },
      { name: "Tier 3",        min: 50000,  max: 99999,    rate: 2.5,  type: "Retroactive" },
      { name: "Tier 4 (Elite)",min: 100000, max: null,     rate: 3.5,  type: "Retroactive" },
    ],
    currentTier: 3,
  },
  {
    id: "RB-2025-002",
    terminal: "SGSIN",
    contractRef: "CTR-APA-2025-217",
    type: "Volume Rebate",
    scope: "All Cost Types",
    period: "Quarterly",
    settlement: "Cash",
    deadline: 45,
    currency: "SGD",
    effective: "2025-01-01", expiry: "2026-12-31",
    status: "Active",
    accruedYTD: 92480, accruedYTDLocal: 124460,
    tiers: [
      { name: "Tier 1 (Base)", min: 0,      max: 14999,    rate: 0,    type: "Incremental" },
      { name: "Tier 2",        min: 15000,  max: 29999,    rate: 1.0,  type: "Incremental" },
      { name: "Tier 3",        min: 30000,  max: null,     rate: 2.0,  type: "Retroactive" },
    ],
    currentTier: 2,
  },
  {
    id: "RB-2025-003",
    terminal: "CNNGB",
    contractRef: "CTR-APA-2025-118",
    type: "Tiered Rebate",
    scope: "CY Handling, Storage",
    period: "Annual",
    settlement: "Rate Offset",
    deadline: 30,
    currency: "CNY",
    effective: "2025-01-01", expiry: "2025-12-31",
    status: "Active",
    accruedYTD: 67200, accruedYTDLocal: 487490,
    tiers: [
      { name: "Tier 1 (Base)", min: 0,      max: 24999,    rate: 0,    type: "Incremental" },
      { name: "Tier 2",        min: 25000,  max: 59999,    rate: 1.2,  type: "Incremental" },
      { name: "Tier 3",        min: 60000,  max: null,     rate: 2.2,  type: "Retroactive" },
    ],
    currentTier: 2,
  },
  {
    id: "RB-2025-004",
    terminal: "CNYTN",
    contractRef: "CTR-APA-2025-141",
    type: "Performance Bonus",
    scope: "All Cost Types",
    period: "Annual",
    settlement: "Cash",
    deadline: 90,
    currency: "CNY",
    effective: "2025-01-01", expiry: "2025-12-31",
    status: "Active",
    accruedYTD: 0, accruedYTDLocal: 0,
    tiers: [
      { name: "Bonus threshold", min: 80000, max: null, rate: 1.8, type: "Retroactive" },
    ],
    currentTier: 0,
    atRisk: true,
  },
  {
    id: "RB-2025-005",
    terminal: "KRPUS",
    contractRef: "CTR-APA-2025-061",
    type: "Tiered Rebate",
    scope: "CY Handling",
    period: "Quarterly",
    settlement: "Credit Note",
    deadline: 60,
    currency: "KRW",
    effective: "2025-01-01", expiry: "2025-12-31",
    status: "Active",
    accruedYTD: 41250, accruedYTDLocal: 55378125,
    tiers: [
      { name: "Tier 1 (Base)", min: 0,      max: 9999,     rate: 0,    type: "Incremental" },
      { name: "Tier 2",        min: 10000,  max: 19999,    rate: 1.0,  type: "Incremental" },
      { name: "Tier 3",        min: 20000,  max: null,     rate: 2.0,  type: "Retroactive" },
    ],
    currentTier: 2,
  },
  {
    id: "RB-2025-006",
    terminal: "INNSA",
    contractRef: "CTR-APA-2025-088",
    type: "Lump Sum",
    scope: "All Cost Types",
    period: "Annual",
    settlement: "Credit Note",
    deadline: 60,
    currency: "INR",
    effective: "2025-01-01", expiry: "2025-12-31",
    status: "Active",
    accruedYTD: 18200, accruedYTDLocal: 1518244,
    tiers: [
      { name: "Achievement bonus", min: 30000, max: null, rate: 0.8, type: "Retroactive" },
    ],
    currentTier: 1,
  },
];

// Settlements
const SETTLEMENTS = [
  { id: "SET-2025-031", rebate: "RB-2025-002", period: "Q1 2025", claimed: 24200, accrued: 24850, ccy: "SGD", status: "Settled", claimedDate: "2025-04-15", settledDate: "2025-04-28", ref: "CRN-SG-78114", variance: -2.6 },
  { id: "SET-2025-024", rebate: "RB-2025-001", period: "Q1 2025", claimed: 312800, accrued: 312800, ccy: "CNY", status: "Settled", claimedDate: "2025-04-10", settledDate: "2025-04-22", ref: "CRN-CN-91082", variance: 0 },
  { id: "SET-2025-038", rebate: "RB-2025-005", period: "Q1 2025", claimed: 14210000, accrued: 14210000, ccy: "KRW", status: "Awaiting Credit", claimedDate: "2025-05-03", settledDate: null, ref: "CL-2025-014", variance: 0 },
  { id: "SET-2025-041", rebate: "RB-2025-003", period: "Q1 2025", claimed: 168200, accrued: 178200, ccy: "CNY", status: "In Review", claimedDate: "2025-05-08", settledDate: null, ref: "DRAFT", variance: -5.6 },
  { id: "SET-2025-019", rebate: "RB-2025-006", period: "Q4 2024", claimed: 1230000, accrued: 1230000, ccy: "INR", status: "Overdue", claimedDate: "2025-03-15", settledDate: null, ref: "CL-2024-Q4", variance: 0, daysOverdue: 14 },
];

// Health Dashboard — Completeness Matrix
const COMPLETENESS = (() => {
  const expected = [];
  // For 5 sample terminals, expand the expected coverage matrix
  ["CNSHA", "CNNGB", "CNTAO", "CNYTN", "SGSIN"].forEach(tc => {
    ["CY_HANDLING", "STORAGE", "REEFER_POWER", "REEFER_PLUG", "EXTRA_YARD"].forEach(ct => {
      ["20GP", "40HC", "40RF", "45HC"].forEach(eq => {
        const cg = eq === "40RF" ? "Reefer" : eq === "45HC" ? "Dry" : "Dry";
        // Simulate coverage status
        const h = (tc.charCodeAt(2) + ct.charCodeAt(0) + eq.charCodeAt(0)) % 10;
        let status;
        if (h < 7) status = "Present";
        else if (h < 9) status = "Missing";
        else status = "Expiring";
        expected.push({
          terminal: tc, costType: ct, equipment: eq, cargo: cg, status,
          lastUpdated: status === "Missing" ? null : "2025-0" + ((h%4)+1) + "-1" + h,
          expiryDays: status === "Expiring" ? (h * 3 + 7) : null,
        });
      });
    });
  });
  return expected;
})();

const COMPLETENESS_SUMMARY = (() => {
  const out = {};
  COMPLETENESS.forEach(r => {
    if (!out[r.terminal]) out[r.terminal] = { total: 0, present: 0, missing: 0, expiring: 0 };
    out[r.terminal].total++;
    out[r.terminal][r.status.toLowerCase()]++;
  });
  return out;
})();

// Expiry Alerts (within 60 days)
const EXPIRY_ALERTS = [
  { id: "R-10103", terminal: "CNTSN", terminalName: "Tianjin Xingang", costType: "Storage", equipment: "All", cargo: "Dry", rate: 28, ccy: "CNY", expiry: "2025-06-01", days: 18, focal: "Wang Lei" },
  { id: "R-10218", terminal: "CNNGB", terminalName: "Ningbo Zhoushan", costType: "Reefer Plug In/Out", equipment: "40RF", cargo: "Reefer", rate: 120, ccy: "CNY", expiry: "2025-06-08", days: 25, focal: "Li Ming" },
  { id: "R-10412", terminal: "CNSHA", terminalName: "Shanghai (Yangshan)", costType: "Extra Yard Work", equipment: "45HC", cargo: "Dry", rate: 350, ccy: "CNY", expiry: "2025-06-14", days: 31, focal: "Wang Lei" },
  { id: "R-10501", terminal: "HKHKG", terminalName: "Hong Kong (Kwai Tsing)", costType: "CY Handling", equipment: "20GP", cargo: "Dry", rate: 310, ccy: "HKD", expiry: "2025-07-01", days: 48, focal: "Zhang Fang" },
  { id: "R-10677", terminal: "SGSIN", terminalName: "Singapore (PSA)", costType: "Reefer Power", equipment: "40RF", cargo: "Reefer", rate: 48, ccy: "SGD", expiry: "2025-05-22", days: 8, focal: "P. Wijaya" },
  { id: "R-10822", terminal: "MYPKG", terminalName: "Port Klang Westport", costType: "Storage", equipment: "All", cargo: "Dry", rate: 18, ccy: "MYR", expiry: "2025-06-05", days: 22, focal: "P. Wijaya" },
];

// Quality Validation findings
const VALIDATION_RESULTS = [
  { rule: "QV-02", name: "Date Range Overlap", severity: "Error", terminal: "CNTAO", target: "R-10089 / R-10135 · CY Handling · 20GP", detail: "R-10089 effective 2025-01-01→2025-12-31 overlaps R-10135 effective 2025-06-01→2026-05-31" },
  { rule: "QV-01", name: "Duplicate Rate", severity: "Error", terminal: "MYPKG", target: "R-10822 / R-10823 · Storage", detail: "Two active records with identical Terminal + Cost Type + Unit" },
  { rule: "QV-07", name: "ROE Missing for Currency", severity: "Error", terminal: "IDJKT", target: "IDR/USD ROE", detail: "No active ROE record covers 2025-05-01 → 2025-12-31" },
  { rule: "QV-03", name: "Date Gap", severity: "Warning", terminal: "VNSGN", target: "R-10412 · Reefer Power", detail: "Gap between 2025-03-31 expiry and 2025-05-01 successor — no active rate Apr 1–30" },
  { rule: "QV-05", name: "Zero / Negative Rate", severity: "Warning", terminal: "BDCGP", target: "R-10918 · VGM Weighing", detail: "Rate value = 0.00 BDT — likely data entry error" },
  { rule: "QV-06", name: "Missing Mandatory Tier", severity: "Warning", terminal: "NZAKL", target: "Storage · Day 4+ tier", detail: "Storage tier 'Day 1–3' present but no successor tier defined" },
  { rule: "QV-08", name: "Orphan Terminal", severity: "Warning", terminal: "—", target: "R-09988 · references CNXMG", detail: "Terminal code CNXMG was deactivated 2025-02-14; orphan rate exists" },
];

const VALIDATION_RULES = [
  { id: "QV-01", name: "Duplicate Rate", severity: "Error", desc: "Two or more active rate records with identical Terminal + Cost Type + Equipment + Cargo + Unit within overlapping date ranges." },
  { id: "QV-02", name: "Date Range Overlap", severity: "Error", desc: "Same combination has two records where one effective date falls within another record's effective–expiry window." },
  { id: "QV-03", name: "Date Gap", severity: "Warning", desc: "A gap exists between the expiry of one record and the effective date of its successor for the same combination." },
  { id: "QV-04", name: "Inverted Dates", severity: "Error", desc: "Expiry date is earlier than or equal to the effective date on the same record." },
  { id: "QV-05", name: "Zero / Negative Rate", severity: "Warning", desc: "Rate value is zero or negative (likely a data entry error)." },
  { id: "QV-06", name: "Missing Mandatory Tier", severity: "Warning", desc: "A tiered cost type has a Day 1 tier but is missing subsequent tier definitions." },
  { id: "QV-07", name: "ROE Missing for Currency", severity: "Error", desc: "The rate's currency has no active ROE record covering the rate's effective date range." },
  { id: "QV-08", name: "Orphan Terminal", severity: "Warning", desc: "Rate record references a terminal code that is no longer active in the terminal metadata." },
];

// TCO data — per-terminal cost breakdown for current month
const TCO = (() => {
  const out = [];
  TERMINALS.forEach((t, ti) => {
    const monthlyTEU = VOLUME.rows.filter(v => v.terminal === t.code && v.period === "2025-05")[0]?.teu || 2000;
    // Cost type breakdown (% allocation)
    const allocation = {
      "CY Handling": 0.62,
      "Storage": 0.14,
      "Reefer": 0.09,
      "Other Behavior": 0.15,
    };
    const baseUsdPerTeu = 88 + ((ti * 47) % 35);
    const gross = monthlyTEU * baseUsdPerTeu;
    const reb = REBATES.find(r => r.terminal === t.code);
    const rebateMonthly = reb ? reb.accruedYTD / 5 : 0;
    const net = gross - rebateMonthly;
    const breakdown = Object.fromEntries(Object.entries(allocation).map(([k, v]) => [k, gross * v]));
    out.push({
      terminal: t.code, terminalName: t.name, region: t.region, area: t.area,
      monthlyTEU,
      gross,
      grossPerTEU: gross / monthlyTEU,
      rebate: rebateMonthly,
      rebateYield: rebateMonthly ? (rebateMonthly / gross) * 100 : 0,
      net,
      netPerTEU: net / monthlyTEU,
      breakdown,
      momChange: -1.5 + ((ti * 19) % 50) / 10,
    });
  });
  return out.sort((a, b) => a.netPerTEU - b.netPerTEU);
})();

Object.assign(window, {
  TERMINALS, COST_TYPES, CHARGE_UNITS, ROE, RATES, REGIONS,
  PERSONAS, PERMS, AUDIT, ACCESS_REQUESTS, TERMINAL_BY_CODE,
  EQUIPMENT, CARGO_TYPES, MOVE_TYPES,
  VOLUME, MVC, YTD_VOLUME,
  REBATES, SETTLEMENTS,
  COMPLETENESS, COMPLETENESS_SUMMARY, EXPIRY_ALERTS, VALIDATION_RESULTS, VALIDATION_RULES,
  TCO,
});
