<?php
/**
 * AR / Collections — reports & analytics (Phase 5). Role-scoped, mirroring coding-reports.php.
 *   Tabs: Production · Quality · Team (supervisor/manager) · Inventory pivots (supervisor/manager).
 *   Scope: AR user = own worked visits · auditor = audits they did · supervisor = their team ·
 *          manager = their supervisors + teams (reports_to tree) · sysadmin = everyone.
 *   Production = COUNT(worked visit rows). Quality = DPO over ar_visit_audit (opp/def).
 *   Inventory pivots run over the LIVE collection_raw of a chosen AR process (carrier · patient+visits · ±dollar · high→low).
 */
require_once __DIR__ . '/../includes/config.php';
$user = require_login('internal');
$pdo  = db();
$uid  = (int) $user['id'];

$isTeam    = can('ar.supervise');
$isAuditor = !$isTeam && can('ar.audit');
$isManager = user_has_role($uid, 'ar_manager');
$role      = $isTeam ? 'team' : ($isAuditor ? 'auditor' : 'user');
$teamIds   = ar_team_scope($pdo, $uid);                                   // null = sysadmin (everyone)

$tabs = ['production' => 'Production', 'quality' => 'Quality'];
if ($isTeam) { $tabs['team'] = 'Team'; $tabs['inventory'] = 'Open inventory'; }
if (!$isAuditor) { $tabs['allocation'] = $isTeam ? 'Team allocation' : 'My allocation';   // role-scoped allocated-inventory analysis
                   $tabs['progress']   = 'Allocated vs worked'; }                          // allocated vs worked by process/supervisor/user/carrier
if ($isAuditor) unset($tabs['production']);                               // auditors have no production of their own
$report = in_array($_GET['report'] ?? '', array_keys($tabs), true) ? $_GET['report'] : ($isAuditor ? 'quality' : 'production');

$to   = preg_match('/^\d{4}-\d{2}-\d{2}$/', (string) ($_GET['to'] ?? ''))   ? $_GET['to']   : date('Y-m-d');
$from = preg_match('/^\d{4}-\d{2}-\d{2}$/', (string) ($_GET['from'] ?? '')) ? $_GET['from'] : date('Y-m-d', strtotime('-29 days'));
$toExcl = date('Y-m-d', strtotime($to . ' +1 day'));

$acc    = fn($opp, $def) => $opp > 0 ? round(100.0 * ($opp - $def) / $opp, 1) : null;
$accCls = fn($q) => $q === null ? 'secondary' : ($q >= 95 ? 'success' : ($q >= 90 ? 'warning' : 'danger'));
$rate   = fn($n, $d) => $d > 0 ? round(100.0 * $n / $d, 1) . '%' : '—';

/* ---------- AR vertical + process filter (AR-only, robust to dedup-suffixed codes) ---------- */
$arVerticals = array_values(array_filter(
    $pdo->query("SELECT id, code, name FROM verticals WHERE deleted_at IS NULL AND status='active' ORDER BY name")->fetchAll(),
    fn($v) => app_vertical_group_canonical($v) === 'ar'
));
$arVertIds = array_map(fn($v) => (int) $v['id'], $arVerticals);
$fVertical = (int) ($_GET['vertical_id'] ?? 0);
if ($fVertical && !in_array($fVertical, $arVertIds, true)) $fVertical = 0;
if (!$fVertical && count($arVerticals) === 1) $fVertical = (int) $arVerticals[0]['id'];
$processes = [];
if ($fVertical) {
    $st = $pdo->prepare("SELECT p.id, p.name, c.name client_name FROM processes p JOIN clients c ON c.id=p.client_id
        WHERE c.vertical_id=? AND p.deleted_at IS NULL AND c.deleted_at IS NULL ORDER BY c.name, p.name");
    $st->execute([$fVertical]); $processes = $st->fetchAll();
}
$procIds = array_map(fn($p) => (int) $p['id'], $processes);
$fProcess = (int) ($_GET['process_id'] ?? 0);
if ($fProcess && $procIds && !in_array($fProcess, $procIds, true)) $fProcess = 0;
if ($fProcess && !ar_process_in_ar_vertical($pdo, $fProcess)) $fProcess = 0;   // never read a non-AR process
$procProd = $fProcess ? ' AND vw.process_id=' . $fProcess : '';
$procQual = $fProcess ? ' AND a.process_id='  . $fProcess : '';

/* allocation-tab filters: a worker can never widen past themselves; a team viewer can only narrow within their team */
$fWorker = (int) ($_GET['worker_id'] ?? 0);
if ($role === 'user')                                                         $fWorker = 0;
elseif ($fWorker && $teamIds !== null && !in_array($fWorker, $teamIds, true)) $fWorker = 0;
$fCarrier = trim((string) ($_GET['carrier'] ?? ''));
/* role scope for the ALLOCATION tab (ar_visit_work.allocated_user): own / team / all(sysadmin) — integer ids only */
$allocScope = $role === 'user' ? ' AND vw.allocated_user=' . $uid : coding_team_in_sql($teamIds, 'vw.allocated_user');

/* ---------- role-scope SQL fragments ---------- */
$prodScope = $role === 'user' ? ' AND vw.worked_by=' . $uid
           : ($role === 'auditor' ? ' AND 1=0' : coding_team_in_sql($teamIds, 'vw.worked_by'));
$qualScope = $role === 'user' ? ' AND a.worker_id=' . $uid
           : ($role === 'auditor' ? ' AND a.auditor_id=' . $uid : coding_team_in_sql($teamIds, 'a.worker_id'));
/* a supervisor/manager may DRILL into one team member ($fWorker, already fenced to the team) on Production/Quality */
if ($fWorker) { $prodScope .= ' AND vw.worked_by=' . $fWorker; $qualScope .= ' AND a.worker_id=' . $fWorker; }
/* team-member list for the member filter (people in scope who have AR visits) */
$teamMembers = $isTeam ? $pdo->query("SELECT DISTINCT u.id, u.name FROM users u
        JOIN ar_visit_work vw ON vw.allocated_user=u.id WHERE 1=1" . coding_team_in_sql($teamIds, 'vw.allocated_user') . " ORDER BY u.name")->fetchAll() : [];
/* carrier options for the allocation / progress tabs (scoped) */
$scopeCarriers = in_array($report, ['allocation', 'progress'], true)
    ? $pdo->query("SELECT DISTINCT carrier_name FROM ar_visit_work vw WHERE COALESCE(carrier_name,'')<>''" . $allocScope . " ORDER BY carrier_name")->fetchAll(PDO::FETCH_COLUMN)
    : [];

/* ---------- Excel export of the PRODUCTION detail (worked visits) — current range + role scope + process ---------- */
if (($_GET['export'] ?? '') === 'production' && $role !== 'auditor') {
    require_once __DIR__ . '/../includes/xlsx.php';
    $bkt = ['sent_to_coding' => 'Sent to coding', 'escalated_to_client' => 'Escalated to client'];
    $ex = $pdo->prepare("SELECT vw.worked_at, vw.chart_number, vw.visit_id, c.name cname, p.name pname,
            vw.carrier_name, vw.claim_status, vw.action_taken, vw.bucket, vw.next_follow_up_date, u.name worker, vw.notes
        FROM ar_visit_work vw
        JOIN processes p ON p.id=vw.process_id
        JOIN clients c ON c.id=p.client_id
        LEFT JOIN users u ON u.id=vw.worked_by
        WHERE vw.inventory_status='worked' AND vw.worked_at>=? AND vw.worked_at<? $prodScope $procProd
        ORDER BY vw.worked_at DESC LIMIT 20000");
    $ex->execute([$from, $toExcl]);
    $out = [];
    foreach ($ex->fetchAll() as $r) $out[] = [
        disp_dt($r['worked_at']),
        $r['chart_number'], $r['visit_id'], $r['cname'], $r['pname'],
        $r['carrier_name'] ?: '', $r['claim_status'] ?: '', $r['action_taken'] ?: '',
        $bkt[$r['bucket']] ?? ($r['bucket'] ?: ''),
        !empty($r['next_follow_up_date']) ? date('Y-m-d', strtotime($r['next_follow_up_date'])) : '',
        $r['worker'] ?: '', $r['notes'] ?: '',
    ];
    $x = new SimpleXlsx();
    $x->addSheet('AR production', ['Worked at','Patient account #','Visit ID','Client','Process','Carrier','Claim status','Action taken','Bucket','Next follow-up','Worker','Notes'], $out);
    audit_log('ar.reports.export_production', 'scope', null, null, ['from'=>$from, 'to'=>$to, 'rows'=>count($out), 'worker'=>$fWorker, 'process'=>$fProcess]);
    $x->download('ar-production-' . $from . '_' . $to . '.xlsx');
    exit;
}

/* ---------- PRODUCTION aggregates (worked visits) ---------- */
$pst = $pdo->prepare("SELECT COUNT(*) worked,
        COUNT(DISTINCT CONCAT(vw.process_id,'|',vw.chart_number)) accounts,
        COALESCE(SUM(vw.bucket='sent_to_coding'),0) sent_coding,
        COALESCE(SUM(vw.bucket='escalated_to_client'),0) escalated,
        COALESCE(SUM(vw.next_follow_up_date IS NOT NULL),0) followups,
        COALESCE(SUM(vw.in_sample=1),0) sampled
    FROM ar_visit_work vw WHERE vw.inventory_status='worked' AND vw.worked_at>=? AND vw.worked_at<? $prodScope $procProd");
$pst->execute([$from, $toExcl]); $P = $pst->fetch();

/* ---------- QUALITY aggregates (audited visits) ---------- */
$qst = $pdo->prepare("SELECT COUNT(*) audited, COALESCE(SUM(a.opportunities),0) opp, COALESCE(SUM(a.defects),0) def,
        COALESCE(SUM(a.result='error'),0) err,
        COALESCE(SUM(a.rebuttal_status IN('raised','accepted','rejected')),0) rebuttals,
        COALESCE(SUM(a.rebuttal_status='raised'),0) reb_open
    FROM ar_visit_audit a WHERE a.audited_at>=? AND a.audited_at<? $qualScope $procQual");
$qst->execute([$from, $toExcl]); $Q = $qst->fetch();
$overallQ = $acc((int) $Q['opp'], (int) $Q['def']);

/* ---------- daily activity (worked / audited / accuracy) ---------- */
$daily = [];
for ($d = $from; $d <= $to; $d = date('Y-m-d', strtotime($d . ' +1 day'))) $daily[$d] = ['worked' => 0, 'audited' => 0, 'opp' => 0, 'def' => 0];
if ($role !== 'auditor') {
    $st = $pdo->prepare("SELECT DATE(vw.worked_at) d, COUNT(*) n FROM ar_visit_work vw
        WHERE vw.inventory_status='worked' AND vw.worked_at>=? AND vw.worked_at<? $prodScope $procProd GROUP BY DATE(vw.worked_at)");
    $st->execute([$from, $toExcl]);
    foreach ($st->fetchAll() as $r) if (isset($daily[$r['d']])) $daily[$r['d']]['worked'] = (int) $r['n'];
}
$st = $pdo->prepare("SELECT DATE(a.audited_at) d, COUNT(*) n, SUM(a.opportunities) opp, SUM(a.defects) def
    FROM ar_visit_audit a WHERE a.audited_at>=? AND a.audited_at<? $qualScope $procQual GROUP BY DATE(a.audited_at)");
$st->execute([$from, $toExcl]);
foreach ($st->fetchAll() as $r) if (isset($daily[$r['d']])) { $daily[$r['d']]['audited'] = (int) $r['n']; $daily[$r['d']]['opp'] = (int) $r['opp']; $daily[$r['d']]['def'] = (int) $r['def']; }
$dailyActive = array_reverse(array_filter($daily, fn($v) => $v['worked'] || $v['audited']), true);
$prodActiveDays = count(array_filter($daily, fn($v) => $v['worked'] > 0));
$qualActiveDays = count(array_filter($daily, fn($v) => $v['audited'] > 0));

/* Production detail (worked visits) for the Daily-activity "Production details" dropdown — capped; full set via Excel. */
$prodDetail = [];
if ($report === 'production' && $role !== 'auditor') {
    $pd = $pdo->prepare("SELECT vw.worked_at, vw.chart_number, vw.visit_id, vw.carrier_name, vw.claim_status, vw.action_taken, vw.bucket, u.name worker, vw.notes
        FROM ar_visit_work vw LEFT JOIN users u ON u.id=vw.worked_by
        WHERE vw.inventory_status='worked' AND vw.worked_at>=? AND vw.worked_at<? $prodScope $procProd
        ORDER BY vw.worked_at DESC LIMIT 500");
    $pd->execute([$from, $toExcl]); $prodDetail = $pd->fetchAll();
}
$prodExportUrl = url('/admin/ar-reports.php?' . http_build_query(array_filter([
    'report'=>'production', 'from'=>$from, 'to'=>$to, 'vertical_id'=>$fVertical ?: null,
    'process_id'=>$fProcess ?: null, 'worker_id'=>$fWorker ?: null, 'export'=>'production',
], fn($v) => $v !== null && $v !== '')));

/* ---------- BREAKDOWN tables (production by bucket/carrier/action; quality by carrier/param) ---------- */
$prodBreak = $qualBreak = []; $paramBreak = [];
if ($report === 'production' && $role !== 'auditor') {
    $st = $pdo->prepare("SELECT COALESCE(NULLIF(vw.carrier_name,''),'(no carrier)') grp, COUNT(*) worked,
            COUNT(DISTINCT vw.chart_number) accounts, COALESCE(SUM(vw.bucket='sent_to_coding'),0) coding, COALESCE(SUM(vw.bucket='escalated_to_client'),0) client
        FROM ar_visit_work vw WHERE vw.inventory_status='worked' AND vw.worked_at>=? AND vw.worked_at<? $prodScope $procProd
        GROUP BY grp ORDER BY worked DESC LIMIT 100");
    $st->execute([$from, $toExcl]); $prodBreak = $st->fetchAll();
}
if ($report === 'quality') {
    $st = $pdo->prepare("SELECT COALESCE(NULLIF(a.visit_id,''),'(visit)') x, a.process_id pid FROM ar_visit_audit a WHERE 1=0"); // placeholder (unused)
    // per-parameter defect breakdown (which of the 5 fails most)
    $st = $pdo->prepare("SELECT ap.param_key, COUNT(*) fails FROM ar_audit_param ap JOIN ar_visit_audit a ON a.id=ap.audit_id
        WHERE ap.result='fail' AND a.audited_at>=? AND a.audited_at<? $qualScope $procQual GROUP BY ap.param_key ORDER BY fails DESC");
    $st->execute([$from, $toExcl]); $paramBreak = $st->fetchAll();
    // quality by carrier
    $st = $pdo->prepare("SELECT COALESCE(NULLIF(vw.carrier_name,''),'(no carrier)') grp, COUNT(*) audited,
            SUM(a.opportunities) opp, SUM(a.defects) def, SUM(a.result='error') err
        FROM ar_visit_audit a JOIN ar_visit_work vw ON vw.id=a.visit_work_id
        WHERE a.audited_at>=? AND a.audited_at<? $qualScope $procQual GROUP BY grp ORDER BY audited DESC LIMIT 100");
    $st->execute([$from, $toExcl]); $qualBreak = $st->fetchAll();
}

/* ---------- TEAM roster + per-member roll-up (supervisor / manager) ----------
   reports_to tree: a supervisor sees direct reports; a manager sees supervisors → their teams. */
$teamNodes = []; $teamChildren = []; $teamRootIds = []; $teamProdU = []; $teamQualU = [];
$teamTot = ['worked' => 0, 'accounts' => 0, 'opp' => 0, 'def' => 0, 'audited' => 0, 'members' => 0, 'active' => 0, 'idle' => 0];
$teamFlat = false;
if ($isTeam && $report === 'team') {
    $rosterIds = coding_managed_user_ids($pdo, $uid);                       // reports_to subtree (primary)
    if (!$rosterIds) {
        // No reports_to tree under this viewer (e.g. SysAdmin, or a lead with "Reports to" unset) → fall back to a
        // FLAT list of AR workers in scope: sysadmin = all AR workers, else the team-scope members (minus self).
        $teamFlat  = true;
        $rosterIds = $teamIds === null ? ar_allocatable_user_ids($pdo) : array_values(array_diff(array_map('intval', $teamIds), [$uid]));
    }
    if ($rosterIds) {
        $in = implode(',', array_map('intval', $rosterIds));
        foreach ($pdo->query("SELECT u.id, u.name, u.reports_to,
                    MAX(r.code IN('ar_supervisor','ar_manager')) is_lead,
                    COALESCE(GROUP_CONCAT(DISTINCT r.name ORDER BY r.name SEPARATOR ', '),'') roles
                FROM users u LEFT JOIN user_roles ur ON ur.user_id=u.id LEFT JOIN roles r ON r.id=ur.role_id
                WHERE u.id IN ($in) GROUP BY u.id, u.name, u.reports_to") as $r) {
            $id = (int) $r['id']; $teamNodes[$id] = $r; $teamChildren[(int) $r['reports_to']][] = $id;
        }
        // tree mode → render the viewer's direct reports (recursion shows the sub-tree); flat fallback → render all.
        $teamRootIds = $teamFlat ? array_keys($teamNodes) : ($teamChildren[$uid] ?? []);
        if (!$teamFlat && !$teamRootIds) { $teamRootIds = array_keys($teamNodes); $teamChildren = []; }   // managed users but not direct reports → flat
        if ($teamFlat) $teamChildren = [];
        $ps = $pdo->prepare("SELECT vw.worked_by uid, COUNT(*) worked, COUNT(DISTINCT vw.chart_number) accounts,
                COALESCE(SUM(vw.bucket='sent_to_coding'),0) coding, COALESCE(SUM(vw.bucket='escalated_to_client'),0) client
            FROM ar_visit_work vw WHERE vw.inventory_status='worked' AND vw.worked_by IN ($in) AND vw.worked_at>=? AND vw.worked_at<? $procProd GROUP BY vw.worked_by");
        $ps->execute([$from, $toExcl]); foreach ($ps->fetchAll() as $r) $teamProdU[(int) $r['uid']] = $r;
        $qs = $pdo->prepare("SELECT a.worker_id uid, COUNT(*) audited, SUM(a.opportunities) opp, SUM(a.defects) def, SUM(a.result='error') err
            FROM ar_visit_audit a WHERE a.worker_id IN ($in) AND a.audited_at>=? AND a.audited_at<? $procQual GROUP BY a.worker_id");
        $qs->execute([$from, $toExcl]); foreach ($qs->fetchAll() as $r) $teamQualU[(int) $r['uid']] = $r;
        foreach ($teamNodes as $id => $n) {
            $w = (int) ($teamProdU[$id]['worked'] ?? 0);
            $teamTot['worked'] += $w; $teamTot['accounts'] += (int) ($teamProdU[$id]['accounts'] ?? 0);
            $teamTot['opp'] += (int) ($teamQualU[$id]['opp'] ?? 0); $teamTot['def'] += (int) ($teamQualU[$id]['def'] ?? 0);
            $teamTot['audited'] += (int) ($teamQualU[$id]['audited'] ?? 0);
            if (!(int) $n['is_lead']) { $teamTot['members']++; $w > 0 ? $teamTot['active']++ : $teamTot['idle']++; }
        }
    }
}
$teamAcc = $acc($teamTot['opp'], $teamTot['def']);

/* ---------- INVENTORY PIVOTS (live collection_raw of the chosen AR process) ---------- */
$pivCarrier = $pivPatient = $pivDollar = $pivHigh = []; $pivTot = null;
if ($report === 'inventory' && $isTeam && $fProcess) {   // pivots expose account-level financials → supervisor/manager only
    $rids = ar_process_report_ids($pdo, $fProcess);
    if ($rids) {
        $in = implode(',', $rids);
        // 1) Carrier-wise
        $pivCarrier = $pdo->query("SELECT COALESCE(NULLIF(carrier1_name,''),'(no carrier)') carrier,
                COUNT(DISTINCT visit_id) visits, COUNT(DISTINCT chart_number) patients,
                ROUND(SUM(insurance_balance),2) ins_bal, ROUND(SUM(patient_balance),2) pat_bal
            FROM collection_raw WHERE report_id IN ($in) GROUP BY carrier ORDER BY ins_bal DESC LIMIT 200")->fetchAll();
        // 2) Patient + visits-wise (most visits first)
        $pivPatient = $pdo->query("SELECT chart_number,
                MAX(CONCAT(COALESCE(patient_first_name,''),' ',COALESCE(patient_last_name,''))) patient,
                MAX(carrier1_name) carrier, COUNT(DISTINCT visit_id) visits,
                ROUND(SUM(insurance_balance),2) ins_bal, ROUND(SUM(patient_balance),2) pat_bal
            FROM collection_raw WHERE report_id IN ($in) AND COALESCE(chart_number,'')<>''
            GROUP BY chart_number ORDER BY visits DESC, ins_bal DESC LIMIT 100")->fetchAll();
        // 3) ±dollar — signed insurance-balance bands (surfaces credit/overpaid balances)
        $pivDollar = $pdo->query("SELECT band, COUNT(*) visits, ROUND(SUM(ib),2) ins_bal FROM (
                SELECT visit_id, SUM(insurance_balance) ib,
                    CASE
                        WHEN SUM(insurance_balance) <  0       THEN '1· Credit (< \$0)'
                        WHEN SUM(insurance_balance) =  0       THEN '2· Zero'
                        WHEN SUM(insurance_balance) <= 100     THEN '3· \$0–100'
                        WHEN SUM(insurance_balance) <= 500     THEN '4· \$100–500'
                        WHEN SUM(insurance_balance) <= 1000    THEN '5· \$500–1k'
                        WHEN SUM(insurance_balance) <= 5000    THEN '6· \$1k–5k'
                        ELSE '7· \$5k+'
                    END band
                FROM collection_raw WHERE report_id IN ($in) GROUP BY visit_id
            ) t GROUP BY band ORDER BY band")->fetchAll();
        // 4) High→low — biggest-balance accounts to prioritise
        $pivHigh = $pdo->query("SELECT chart_number, MAX(carrier1_name) carrier, COUNT(DISTINCT visit_id) visits,
                ROUND(SUM(insurance_balance),2) ins_bal
            FROM collection_raw WHERE report_id IN ($in) AND COALESCE(chart_number,'')<>''
            GROUP BY chart_number HAVING ins_bal <> 0 ORDER BY ins_bal DESC LIMIT 50")->fetchAll();
        $pivTot = $pdo->query("SELECT COUNT(DISTINCT chart_number) patients, COUNT(DISTINCT visit_id) visits,
                ROUND(SUM(insurance_balance),2) ins_bal, ROUND(SUM(patient_balance),2) pat_bal
            FROM collection_raw WHERE report_id IN ($in)")->fetch();
    }
}

/* ---------- ALLOCATION analysis (the ALLOCATED inventory, role-scoped: worker=own · team=their team · sysadmin=all) ---------- */
$alc = ['carrier' => [], 'patient' => [], 'tot' => null, 'names' => [], 'workers' => [], 'carriers' => [], 'production' => []];
if ($report === 'allocation') {
    $w = ['vw.allocated_user IS NOT NULL']; $p = [];
    if ($fVertical)        { $w[] = 'c.vertical_id=?';     $p[] = $fVertical; }
    if ($fProcess)         { $w[] = 'vw.process_id=?';     $p[] = $fProcess; }
    if ($fWorker)          { $w[] = 'vw.allocated_user=?'; $p[] = $fWorker; }
    if ($fCarrier !== '')  { $w[] = 'vw.carrier_name=?';   $p[] = $fCarrier; }
    $whereSql = implode(' AND ', $w) . $allocScope;                          // $allocScope = integer-id fence
    $fromSql  = "FROM ar_visit_work vw JOIN processes p ON p.id=vw.process_id JOIN clients c ON c.id=p.client_id";
    $st = $pdo->prepare("SELECT COALESCE(NULLIF(vw.carrier_name,''),'(no carrier)') carrier,
            COUNT(DISTINCT vw.chart_number) accounts, COUNT(*) visits, ROUND(SUM(vw.insurance_balance),2) ins_bal
        $fromSql WHERE $whereSql GROUP BY carrier ORDER BY ins_bal DESC");
    $st->execute($p); $alc['carrier'] = $st->fetchAll();
    $st = $pdo->prepare("SELECT vw.process_id, vw.chart_number, MAX(vw.carrier_name) carrier,
            COUNT(*) visits, ROUND(SUM(vw.insurance_balance),2) ins_bal
        $fromSql WHERE $whereSql GROUP BY vw.process_id, vw.chart_number ORDER BY visits DESC, ins_bal DESC LIMIT 500");
    $st->execute($p); $alc['patient'] = $st->fetchAll();
    $st = $pdo->prepare("SELECT COUNT(DISTINCT CONCAT(vw.process_id,'|',vw.chart_number)) accounts, COUNT(*) visits,
            ROUND(SUM(vw.insurance_balance),2) ins_bal $fromSql WHERE $whereSql");
    $st->execute($p); $alc['tot'] = $st->fetch();
    // a WORKER reviews what they've worked (production) instead of carrier analysis
    if ($role === 'user') {
        $st = $pdo->prepare("SELECT vw.process_id, vw.chart_number, vw.visit_id, vw.carrier_name, vw.claim_status, vw.action_taken, vw.bucket, vw.worked_at
            $fromSql WHERE $whereSql AND vw.inventory_status='worked' ORDER BY vw.worked_at DESC LIMIT 300");
        $st->execute($p); $alc['production'] = $st->fetchAll();
    }
    // patient NAMES for the patient pivot (per-process lookup against collection_raw), keyed "process|chart"
    $procCharts = [];
    foreach ($alc['patient'] as $r)    $procCharts[(int) $r['process_id']][(string) $r['chart_number']] = 1;
    foreach ($alc['production'] as $r) $procCharts[(int) $r['process_id']][(string) $r['chart_number']] = 1;
    foreach ($procCharts as $pidK => $set) {
        $rids = ar_process_report_ids($pdo, $pidK); if (!$rids) continue;
        $charts = array_keys($set); $inR = implode(',', array_map('intval', $rids)); $inC = implode(',', array_fill(0, count($charts), '?'));
        $nm = $pdo->prepare("SELECT chart_number, MAX(CONCAT(COALESCE(patient_last_name,''),', ',COALESCE(patient_first_name,''))) nm
            FROM collection_raw WHERE report_id IN ($inR) AND chart_number IN ($inC) GROUP BY chart_number");
        $nm->execute($charts);
        foreach ($nm->fetchAll() as $r) $alc['names'][$pidK . '|' . (string) $r['chart_number']] = trim((string) $r['nm'], ', ');
    }
    // filter options (scoped) — team viewers get a worker dropdown; everyone gets a carrier dropdown
    if ($isTeam) $alc['workers'] = $pdo->query("SELECT DISTINCT vw.allocated_user uid, u.name FROM ar_visit_work vw
        JOIN users u ON u.id=vw.allocated_user WHERE vw.allocated_user IS NOT NULL" . $allocScope . " ORDER BY u.name")->fetchAll();
    $alc['carriers'] = $pdo->query("SELECT DISTINCT carrier_name FROM ar_visit_work vw
        WHERE COALESCE(carrier_name,'')<>''" . $allocScope . " ORDER BY carrier_name")->fetchAll(PDO::FETCH_COLUMN);
}

/* ---------- ALLOCATED vs WORKED (role-scoped) — allocated / worked / pending / % by process · supervisor · user · carrier ---------- */
$prog = ['process' => [], 'supervisor' => [], 'user' => [], 'carrier' => [], 'tot' => null];
if ($report === 'progress') {
    $w = ['vw.allocated_user IS NOT NULL']; $p = [];
    if ($fVertical)       { $w[] = 'c.vertical_id=?';      $p[] = $fVertical; }
    if ($fProcess)        { $w[] = 'vw.process_id=?';      $p[] = $fProcess; }
    if ($fWorker)         { $w[] = 'vw.allocated_user=?';  $p[] = $fWorker; }
    if ($fCarrier !== '') { $w[] = 'vw.carrier_name=?';    $p[] = $fCarrier; }
    $whereSql = implode(' AND ', $w) . $allocScope;
    $fromSql  = "FROM ar_visit_work vw JOIN processes pr ON pr.id=vw.process_id JOIN clients c ON c.id=pr.client_id";
    $metric   = "COUNT(*) allocated, COALESCE(SUM(vw.inventory_status='worked'),0) worked";
    $st = $pdo->prepare("SELECT c.name cname, pr.name pname, $metric $fromSql WHERE $whereSql GROUP BY vw.process_id, c.name, pr.name ORDER BY allocated DESC");
    $st->execute($p); $prog['process'] = $st->fetchAll();
    $st = $pdo->prepare("SELECT COALESCE(NULLIF(vw.carrier_name,''),'(no carrier)') carrier, $metric $fromSql WHERE $whereSql GROUP BY carrier ORDER BY allocated DESC");
    $st->execute($p); $prog['carrier'] = $st->fetchAll();
    if ($isTeam) {   // user + supervisor breakdowns are team-viewer lenses
        $st = $pdo->prepare("SELECT u.name uname, $metric $fromSql JOIN users u ON u.id=vw.allocated_user WHERE $whereSql GROUP BY vw.allocated_user, u.name ORDER BY allocated DESC");
        $st->execute($p); $prog['user'] = $st->fetchAll();
        $st = $pdo->prepare("SELECT COALESCE(sup.name,'(no supervisor)') sname, $metric $fromSql JOIN users u ON u.id=vw.allocated_user LEFT JOIN users sup ON sup.id=u.reports_to WHERE $whereSql GROUP BY sup.id, sname ORDER BY allocated DESC");
        $st->execute($p); $prog['supervisor'] = $st->fetchAll();
    }
    $st = $pdo->prepare("SELECT $metric $fromSql WHERE $whereSql"); $st->execute($p); $prog['tot'] = $st->fetch();
}

/* ---------- KPI strips ---------- */
$qp = function (array $over = []) use ($report, $from, $to, $fVertical, $fProcess, $fWorker) {
    return http_build_query(array_merge(['report' => $report, 'from' => $from, 'to' => $to, 'vertical_id' => $fVertical, 'process_id' => $fProcess, 'worker_id' => $fWorker], $over));
};
$prodKpis = [
    ['Worked visits',    number_format((int) $P['worked']),  (int) $P['accounts'] . ' account(s)',           'primary'],
    ['Throughput / day', $prodActiveDays ? number_format(round((int) $P['worked'] / $prodActiveDays, 1)) : '0', $prodActiveDays . ' active day' . ($prodActiveDays == 1 ? '' : 's'), 'default'],
    ['Sent to coding',   number_format((int) $P['sent_coding']), $rate((int) $P['sent_coding'], (int) $P['worked']) . ' of worked', 'purple'],
    ['Escalated client', number_format((int) $P['escalated']),   $rate((int) $P['escalated'], (int) $P['worked']) . ' of worked', 'orange'],
    ['Follow-ups set',   number_format((int) $P['followups']),   $rate((int) $P['followups'], (int) $P['worked']) . ' of worked', 'default'],
    ['Sampled',          number_format((int) $P['sampled']),     $rate((int) $P['sampled'], (int) $P['worked']) . ' for audit', 'default'],
];
$qa = (int) $Q['audited']; $qErr = (int) $Q['err'];
$qualKpis = [
    ['Accuracy % (DPO)', $overallQ === null ? '—' : $overallQ . '%', (int) $Q['def'] . ' / ' . (int) $Q['opp'] . ' defects/opp', $accCls($overallQ)],
    ['Audited',          number_format($qa),                         $qualActiveDays . ' active day' . ($qualActiveDays == 1 ? '' : 's'), 'default'],
    ['Pass rate',        $rate($qa - $qErr, $qa),                    ($qa - $qErr) . ' clean of ' . $qa, 'success'],
    ['With error',       number_format($qErr),                      $rate($qErr, $qa) . ' of audited', 'danger'],
    ['Rebuttals',        number_format((int) $Q['rebuttals']),       (int) $Q['reb_open'] . ' still open', 'orange'],
];

$pageTitle = 'AR reports';
require __DIR__ . '/../includes/header.php';
?>
<div class="page-header"><div class="container-xl"><div class="row align-items-center">
    <div class="col"><h2 class="page-title"><i class="ti ti-chart-histogram me-2 text-primary"></i>AR reports &amp; analytics</h2>
        <div class="text-secondary small">
            <?= $role === 'user' ? 'Your production &amp; audit quality.' : ($role === 'auditor' ? 'The visits you audited.' : 'Your team’s production, quality &amp; inventory.') ?>
            <span class="badge bg-blue-lt ms-1"><?= e(ucfirst($role)) ?> view</span>
        </div></div>
</div></div></div>

<div class="page-body"><div class="container-xl">

    <!-- filter bar -->
    <form method="GET" class="card mb-3"><div class="card-body py-2">
        <input type="hidden" name="report" value="<?= e($report) ?>">
        <div class="row g-2 align-items-end">
            <div class="col-auto"><label class="form-label small mb-1">From</label><input type="date" name="from" value="<?= e($from) ?>" class="form-control form-control-sm"></div>
            <div class="col-auto"><label class="form-label small mb-1">To</label><input type="date" name="to" value="<?= e($to) ?>" class="form-control form-control-sm"></div>
            <?php if (count($arVerticals) > 1): ?>
            <div class="col-auto"><label class="form-label small mb-1">Vertical</label>
                <select name="vertical_id" class="form-select form-select-sm" onchange="this.form.submit()">
                    <option value="0">All AR</option>
                    <?php foreach ($arVerticals as $v): ?><option value="<?= (int)$v['id'] ?>" <?= $fVertical==(int)$v['id']?'selected':'' ?>><?= e($v['name']) ?></option><?php endforeach; ?>
                </select></div>
            <?php endif; ?>
            <div class="col-auto"><label class="form-label small mb-1">Process<?= $report==='inventory'?' <span class="text-danger">*</span>':'' ?></label>
                <select name="process_id" class="form-select form-select-sm" onchange="this.form.submit()" <?= $processes?'':'disabled' ?>>
                    <option value="0"><?= $report==='inventory'?'— choose a process —':'All processes' ?></option>
                    <?php foreach ($processes as $p): ?><option value="<?= (int)$p['id'] ?>" <?= $fProcess==(int)$p['id']?'selected':'' ?>><?= e($p['client_name'].' › '.$p['name']) ?></option><?php endforeach; ?>
                </select></div>
            <?php if ($isTeam && in_array($report, ['production', 'quality', 'allocation', 'progress'], true)): ?>
                <div class="col-auto"><label class="form-label small mb-1">Team member</label>
                    <select name="worker_id" class="form-select form-select-sm" onchange="this.form.submit()">
                        <option value="0">All my team</option>
                        <?php foreach ($teamMembers as $wu): ?><option value="<?= (int)$wu['id'] ?>" <?= $fWorker==(int)$wu['id']?'selected':'' ?>><?= e($wu['name']) ?></option><?php endforeach; ?>
                    </select></div>
            <?php endif; ?>
            <?php if (in_array($report, ['allocation', 'progress'], true)): ?>
                <div class="col-auto"><label class="form-label small mb-1">Carrier</label>
                    <select name="carrier" class="form-select form-select-sm" onchange="this.form.submit()">
                        <option value="">All carriers</option>
                        <?php foreach ($scopeCarriers as $cn): ?><option value="<?= e($cn) ?>" <?= $fCarrier===(string)$cn?'selected':'' ?>><?= e($cn) ?></option><?php endforeach; ?>
                    </select></div>
            <?php endif; ?>
            <div class="col-auto"><button class="btn btn-sm btn-primary"><i class="ti ti-filter me-1"></i>Apply</button></div>
            <div class="col-auto"><a href="<?= e(url('/admin/ar-reports.php?report='.$report)) ?>" class="btn btn-sm btn-link text-secondary">Reset</a></div>
        </div>
    </div></form>

    <!-- tabs -->
    <ul class="nav nav-tabs mb-3">
        <?php foreach ($tabs as $k => $lbl): ?>
            <li class="nav-item"><a class="nav-link <?= $report===$k?'active':'' ?>" href="<?= e(url('/admin/ar-reports.php?'.$qp(['report'=>$k]))) ?>"><?= e($lbl) ?></a></li>
        <?php endforeach; ?>
    </ul>

    <?php
    /* KPI strip renderer */
    $renderKpis = function (array $kpis) { ?>
        <div class="row row-cards mb-3">
            <?php foreach ($kpis as $k): ?>
                <div class="col-6 col-md"><div class="card card-sm"><div class="card-body">
                    <div class="text-secondary small text-uppercase"><?= e($k[0]) ?></div>
                    <div class="h1 m-0 text-<?= e($k[3]) ?>"><?= $k[1] ?></div>
                    <div class="text-secondary small"><?= e($k[2]) ?></div>
                </div></div></div>
            <?php endforeach; ?>
        </div>
    <?php };

    /* daily activity table */
    $renderDaily = function ($prod = null) use ($dailyActive, $acc) { ?>
        <div class="card mb-3"><div class="card-header py-2"><h3 class="card-title small"><i class="ti ti-calendar me-1"></i>Daily activity</h3>
            <?php if ($prod): ?><div class="card-actions">
                <button class="btn btn-sm btn-outline-primary py-0 px-2" type="button" data-bs-toggle="collapse" data-bs-target="#prodDetails" title="View the individual worked visits"><i class="ti ti-list-details me-1"></i>Production details</button>
                <a href="<?= e($prod['exportUrl']) ?>" class="btn btn-sm btn-outline-success py-0 px-2" title="Download the full production data as Excel"><i class="ti ti-file-spreadsheet me-1"></i>Excel</a>
            </div><?php endif; ?>
        </div>
            <div class="table-responsive"><table class="table table-vcenter card-table table-sm">
                <thead><tr><th>Date</th><th class="text-end">Worked</th><th class="text-end">Audited</th><th class="text-end">Accuracy</th></tr></thead>
                <tbody>
                <?php if (!$dailyActive): ?><tr><td colspan="4" class="text-center text-secondary py-3">No activity in this window.</td></tr>
                <?php else: foreach ($dailyActive as $d => $v): $q = $acc((int)$v['opp'], (int)$v['def']); ?>
                    <tr><td class="text-nowrap"><?= e(date('D, M j', strtotime($d))) ?></td>
                        <td class="text-end"><?= (int)$v['worked'] ?: '<span class="text-secondary">—</span>' ?></td>
                        <td class="text-end"><?= (int)$v['audited'] ?: '<span class="text-secondary">—</span>' ?></td>
                        <td class="text-end"><?= $q===null?'<span class="text-secondary">—</span>':'<span class="badge bg-'.($q>=95?'green':($q>=85?'yellow':'red')).'-lt">'.$q.'%</span>' ?></td></tr>
                <?php endforeach; endif; ?>
                </tbody>
            </table></div>
            <?php if ($prod): ?>
            <div class="collapse" id="prodDetails"><div class="border-top">
                <div class="table-responsive" style="max-height:440px;overflow:auto"><table class="table table-vcenter card-table table-sm mb-0" style="font-size:.78rem">
                    <thead><tr><th>Worked at</th><th>Patient acct #</th><th>Visit</th><th>Carrier</th><th>Claim status</th><th>Action taken</th><th>Worker</th><th>Notes</th></tr></thead>
                    <tbody>
                    <?php if (!$prod['details']): ?><tr><td colspan="8" class="text-center text-secondary py-3">No worked visits in this window.</td></tr>
                    <?php else: foreach ($prod['details'] as $r): ?>
                        <tr><td class="text-nowrap small"><?= e(disp_dt($r['worked_at'], 'M j, H:i')) ?></td>
                            <td class="font-mono small"><?= e($r['chart_number']) ?></td>
                            <td class="font-mono small"><?= e($r['visit_id']) ?></td>
                            <td class="small"><?= e($r['carrier_name'] ?: '—') ?></td>
                            <td class="small text-secondary"><?= e($r['claim_status'] ?: '—') ?></td>
                            <td class="small text-secondary"><?= e($r['action_taken'] ?: '—') ?></td>
                            <td class="small"><?= e($r['worker'] ?? '—') ?></td>
                            <td class="small text-secondary" style="max-width:22rem"><?= e($r['notes'] ?: '—') ?></td></tr>
                    <?php endforeach; endif; ?>
                    </tbody>
                </table></div>
                <?php if (count($prod['details']) >= 500): ?><div class="text-secondary small px-2 py-1">Showing the latest 500 worked visits — use <strong>Excel</strong> for the complete set.</div><?php endif; ?>
            </div></div>
            <?php endif; ?>
        </div>
    <?php };
    ?>

    <?php if ($report === 'production'): ?>
        <?php $renderKpis($prodKpis); ?>
        <div class="row"><div class="col-lg-7">
            <div class="card mb-3"><div class="card-header py-2"><h3 class="card-title small"><i class="ti ti-building-bank me-1"></i>By carrier</h3></div>
                <div class="table-responsive"><table class="table table-vcenter card-table table-sm">
                    <thead><tr><th>Carrier</th><th class="text-end">Worked</th><th class="text-end">Accounts</th><th class="text-end">→Coding</th><th class="text-end">→Client</th></tr></thead>
                    <tbody>
                    <?php if (!$prodBreak): ?><tr><td colspan="5" class="text-center text-secondary py-3">No worked visits in this window.</td></tr>
                    <?php else: foreach ($prodBreak as $r): ?>
                        <tr><td><?= e($r['grp']) ?></td><td class="text-end fw-medium"><?= number_format((int)$r['worked']) ?></td>
                            <td class="text-end"><?= number_format((int)$r['accounts']) ?></td>
                            <td class="text-end"><?= (int)$r['coding']?:'—' ?></td><td class="text-end"><?= (int)$r['client']?:'—' ?></td></tr>
                    <?php endforeach; endif; ?>
                    </tbody>
                </table></div>
            </div>
        </div><div class="col-lg-5"><?php $renderDaily(['exportUrl' => $prodExportUrl, 'details' => $prodDetail]); ?></div></div>

    <?php elseif ($report === 'quality'): ?>
        <?php $renderKpis($qualKpis); ?>
        <div class="row"><div class="col-lg-5">
            <div class="card mb-3"><div class="card-header py-2"><h3 class="card-title small"><i class="ti ti-list-check me-1"></i>Defects by parameter</h3></div>
                <div class="table-responsive"><table class="table table-vcenter card-table table-sm">
                    <thead><tr><th>Parameter</th><th class="text-end">Fails</th></tr></thead>
                    <tbody>
                    <?php if (!$paramBreak): ?><tr><td colspan="2" class="text-center text-secondary py-3">No defects in this window. 🎉</td></tr>
                    <?php else: foreach ($paramBreak as $r): ?>
                        <tr><td><?= e(AR_AUDIT_PARAMS[$r['param_key']] ?? $r['param_key']) ?></td><td class="text-end"><span class="badge bg-red-lt"><?= (int)$r['fails'] ?></span></td></tr>
                    <?php endforeach; endif; ?>
                    </tbody>
                </table></div>
            </div>
        </div><div class="col-lg-7">
            <div class="card mb-3"><div class="card-header py-2"><h3 class="card-title small"><i class="ti ti-building-bank me-1"></i>Quality by carrier</h3></div>
                <div class="table-responsive"><table class="table table-vcenter card-table table-sm">
                    <thead><tr><th>Carrier</th><th class="text-end">Audited</th><th class="text-end">Accuracy</th><th class="text-end">Errors</th></tr></thead>
                    <tbody>
                    <?php if (!$qualBreak): ?><tr><td colspan="4" class="text-center text-secondary py-3">No audits in this window.</td></tr>
                    <?php else: foreach ($qualBreak as $r): $q = $acc((int)$r['opp'], (int)$r['def']); ?>
                        <tr><td><?= e($r['grp']) ?></td><td class="text-end"><?= number_format((int)$r['audited']) ?></td>
                            <td class="text-end"><?= $q===null?'—':'<span class="badge bg-'.($q>=95?'green':($q>=85?'yellow':'red')).'-lt">'.$q.'%</span>' ?></td>
                            <td class="text-end"><?= (int)$r['err']?:'—' ?></td></tr>
                    <?php endforeach; endif; ?>
                    </tbody>
                </table></div>
            </div>
        </div></div>
        <?php $renderDaily(); ?>

    <?php elseif ($report === 'team'): ?>
        <div class="row row-cards mb-3">
            <?php foreach ([['Members',$teamTot['members'],'default'],['Active',$teamTot['active'],'success'],['Idle',$teamTot['idle'],'secondary'],
                            ['Worked visits',number_format($teamTot['worked']),'primary'],['Audited',number_format($teamTot['audited']),'default'],
                            ['Team accuracy',$teamAcc===null?'—':$teamAcc.'%',$accCls($teamAcc)]] as $k): ?>
                <div class="col-6 col-md"><div class="card card-sm"><div class="card-body">
                    <div class="text-secondary small text-uppercase"><?= e($k[0]) ?></div><div class="h1 m-0 text-<?= e($k[2]) ?>"><?= $k[1] ?></div></div></div></div>
            <?php endforeach; ?>
        </div>
        <div class="card"><div class="card-header py-2"><h3 class="card-title small"><i class="ti ti-users-group me-1"></i>Team roster &amp; performance</h3>
            <div class="card-actions text-secondary small"><?= $teamFlat ? 'All AR workers in scope' : ($isManager?'Supervisors → their teams':'Your direct reports') ?></div></div>
            <div class="table-responsive"><table class="table table-vcenter card-table table-sm">
                <thead><tr><th>Member</th><th>Role</th><th class="text-end">Worked</th><th class="text-end">Accounts</th><th class="text-end">→Coding</th><th class="text-end">→Client</th><th class="text-end">Audited</th><th class="text-end">Accuracy</th></tr></thead>
                <tbody>
                <?php
                if (!$teamRootIds) { echo '<tr><td colspan="8" class="text-center text-secondary py-4">No AR team members found in scope yet.</td></tr>'; }
                $renderNode = function (int $id, int $depth) use (&$renderNode, $teamNodes, $teamChildren, $teamProdU, $teamQualU, $acc, $accCls) {
                    $n = $teamNodes[$id] ?? null; if (!$n) return;
                    $pr = $teamProdU[$id] ?? []; $ql = $teamQualU[$id] ?? [];
                    $q = $acc((int)($ql['opp'] ?? 0), (int)($ql['def'] ?? 0));
                    $pad = $depth * 18; ?>
                    <tr>
                        <td><span style="padding-left:<?= $pad ?>px"><?php if ((int)$n['is_lead']): ?><i class="ti ti-users-group text-primary me-1"></i><?php else: ?><i class="ti ti-user text-secondary me-1"></i><?php endif; ?><?= e($n['name']) ?></span></td>
                        <td class="small text-secondary"><?= e($n['roles']) ?></td>
                        <td class="text-end fw-medium"><?= number_format((int)($pr['worked'] ?? 0)) ?></td>
                        <td class="text-end"><?= number_format((int)($pr['accounts'] ?? 0)) ?></td>
                        <td class="text-end"><?= (int)($pr['coding'] ?? 0) ?: '—' ?></td>
                        <td class="text-end"><?= (int)($pr['client'] ?? 0) ?: '—' ?></td>
                        <td class="text-end"><?= number_format((int)($ql['audited'] ?? 0)) ?></td>
                        <td class="text-end"><?= $q===null?'<span class="text-secondary">—</span>':'<span class="badge bg-'.$accCls($q).'-lt">'.$q.'%</span>' ?></td>
                    </tr>
                    <?php foreach ($teamChildren[$id] ?? [] as $c) $renderNode($c, $depth + 1);
                };
                foreach ($teamRootIds as $rid) $renderNode($rid, 0);
                ?>
                </tbody>
            </table></div>
        </div>

    <?php elseif ($report === 'inventory'): ?>
        <?php if (!$fProcess): ?>
            <div class="card"><div class="card-body text-center text-secondary py-5"><i class="ti ti-table-options" style="font-size:2.2rem"></i>
                <div class="mt-2">Choose a <strong>process</strong> above to pivot its live AR inventory.</div></div></div>
        <?php else: ?>
            <?php if ($pivTot): ?><div class="row row-cards mb-3">
                <?php foreach ([['Patients',number_format((int)$pivTot['patients']),'primary'],['Visits',number_format((int)$pivTot['visits']),'default'],
                                ['Insurance balance',number_format((float)$pivTot['ins_bal'],2),'azure'],['Patient balance',number_format((float)$pivTot['pat_bal'],2),'default']] as $k): ?>
                    <div class="col-6 col-md-3"><div class="card card-sm"><div class="card-body"><div class="text-secondary small text-uppercase"><?= e($k[0]) ?></div><div class="h2 m-0 text-<?= e($k[2]) ?>"><?= $k[1] ?></div></div></div></div>
                <?php endforeach; ?>
            </div><?php endif; ?>
            <div class="row">
                <div class="col-lg-6"><div class="card mb-3"><div class="card-header py-2"><h3 class="card-title small"><i class="ti ti-building-bank me-1"></i>① Carrier-wise</h3></div>
                    <div class="table-responsive" style="max-height:420px"><table class="table table-vcenter card-table table-sm">
                        <thead><tr><th>Carrier</th><th class="text-end">Visits</th><th class="text-end">Patients</th><th class="text-end">Ins. bal</th></tr></thead>
                        <tbody><?php foreach ($pivCarrier as $r): ?><tr><td class="small"><?= e($r['carrier']) ?></td><td class="text-end"><?= number_format((int)$r['visits']) ?></td><td class="text-end"><?= number_format((int)$r['patients']) ?></td><td class="text-end font-mono"><?= number_format((float)$r['ins_bal'],2) ?></td></tr><?php endforeach; ?>
                        <?php if (!$pivCarrier): ?><tr><td colspan="4" class="text-center text-secondary py-3">No inventory.</td></tr><?php endif; ?></tbody>
                    </table></div></div></div>
                <div class="col-lg-6"><div class="card mb-3"><div class="card-header py-2"><h3 class="card-title small"><i class="ti ti-coin me-1"></i>③ ±Dollar — insurance-balance bands</h3></div>
                    <div class="table-responsive"><table class="table table-vcenter card-table table-sm">
                        <thead><tr><th>Band</th><th class="text-end">Visits</th><th class="text-end">Ins. bal</th></tr></thead>
                        <tbody><?php foreach ($pivDollar as $r): ?><tr><td><?= e(preg_replace('/^\d· /','',$r['band'])) ?></td><td class="text-end"><?= number_format((int)$r['visits']) ?></td><td class="text-end font-mono <?= (float)$r['ins_bal']<0?'text-danger':'' ?>"><?= number_format((float)$r['ins_bal'],2) ?></td></tr><?php endforeach; ?>
                        <?php if (!$pivDollar): ?><tr><td colspan="3" class="text-center text-secondary py-3">No inventory.</td></tr><?php endif; ?></tbody>
                    </table></div></div></div>
            </div>
            <div class="row">
                <div class="col-lg-6"><div class="card mb-3"><div class="card-header py-2"><h3 class="card-title small"><i class="ti ti-users me-1"></i>② Patient + visits-wise <span class="text-secondary">(most visits first)</span></h3></div>
                    <div class="table-responsive" style="max-height:480px"><table class="table table-vcenter card-table table-sm">
                        <thead><tr><th>Patient Account #</th><th>Patient</th><th class="text-end">Visits</th><th class="text-end">Ins. bal</th></tr></thead>
                        <tbody><?php foreach ($pivPatient as $r): ?><tr><td class="font-mono small"><?= e($r['chart_number']) ?></td><td class="small"><?= e(trim($r['patient']) ?: '—') ?></td><td class="text-end"><span class="badge bg-blue-lt"><?= number_format((int)$r['visits']) ?></span></td><td class="text-end font-mono"><?= number_format((float)$r['ins_bal'],2) ?></td></tr><?php endforeach; ?>
                        <?php if (!$pivPatient): ?><tr><td colspan="4" class="text-center text-secondary py-3">No inventory.</td></tr><?php endif; ?></tbody>
                    </table></div></div></div>
                <div class="col-lg-6"><div class="card mb-3"><div class="card-header py-2"><h3 class="card-title small"><i class="ti ti-sort-descending-2 me-1"></i>④ High → low <span class="text-secondary">(biggest balance first)</span></h3></div>
                    <div class="table-responsive" style="max-height:480px"><table class="table table-vcenter card-table table-sm">
                        <thead><tr><th>Patient Account #</th><th>Carrier</th><th class="text-end">Visits</th><th class="text-end">Ins. bal</th></tr></thead>
                        <tbody><?php foreach ($pivHigh as $r): ?><tr><td class="font-mono small"><?= e($r['chart_number']) ?></td><td class="small"><?= e($r['carrier'] ?? '—') ?></td><td class="text-end"><?= number_format((int)$r['visits']) ?></td><td class="text-end font-mono fw-medium <?= (float)$r['ins_bal']<0?'text-danger':'' ?>"><?= number_format((float)$r['ins_bal'],2) ?></td></tr><?php endforeach; ?>
                        <?php if (!$pivHigh): ?><tr><td colspan="4" class="text-center text-secondary py-3">No inventory.</td></tr><?php endif; ?></tbody>
                    </table></div></div></div>
            </div>
        <?php endif; ?>

    <?php elseif ($report === 'allocation'): /* role-scoped ALLOCATED-inventory analysis */ ?>
        <?php $t = $alc['tot']; ?>
        <div class="row row-cards mb-3">
            <?php foreach ([['Accounts', number_format((int)($t['accounts']??0)), 'primary'], ['Visits', number_format((int)($t['visits']??0)), 'default'], ['Insurance balance', number_format((float)($t['ins_bal']??0), 2), 'azure']] as $k): ?>
                <div class="col-6 col-md-4"><div class="card card-sm"><div class="card-body"><div class="text-secondary small text-uppercase"><?= e($k[0]) ?></div><div class="h1 m-0 text-<?= e($k[2]) ?>"><?= $k[1] ?></div></div></div></div>
            <?php endforeach; ?>
        </div>
        <div class="text-secondary small mb-2"><i class="ti ti-info-circle me-1"></i><?= $isTeam ? "Your team's allocated inventory" : 'Your allocated inventory' ?> — click any column header to re-sort (highest↔lowest).</div>
        <div class="row">
            <?php if ($role === 'user'): /* WORKER: review what I've worked (production) instead of carrier analysis */ ?>
            <div class="col-lg-6"><div class="card mb-3"><div class="card-header py-2"><h3 class="card-title small"><i class="ti ti-checkbox me-1"></i>My production <span class="text-secondary">(worked)</span></h3>
                <div class="card-actions"><span class="badge bg-green-lt"><?= count($alc['production']) ?></span></div></div>
                <div class="table-responsive" style="max-height:460px"><table class="table table-vcenter card-table table-sm ar-pivot">
                    <thead><tr><th onclick="arSortPivot(this)" style="cursor:pointer">Account #</th><th onclick="arSortPivot(this)" style="cursor:pointer">Patient</th>
                        <th onclick="arSortPivot(this)" style="cursor:pointer">Claim status</th><th onclick="arSortPivot(this)" style="cursor:pointer">Action taken</th>
                        <th data-num="1" onclick="arSortPivot(this)" style="cursor:pointer">Worked ▾</th></tr></thead>
                    <tbody>
                    <?php if (!$alc['production']): ?><tr><td colspan="5" class="text-center text-secondary py-3">You haven't worked any visits in this scope yet.</td></tr>
                    <?php else: $bb = ['sent_to_coding'=>['Coding','purple'],'escalated_to_client'=>['Client','orange']];
                        foreach ($alc['production'] as $r): $nm = $alc['names'][(int)$r['process_id'].'|'.(string)$r['chart_number']] ?? ''; $bk = $r['bucket'] ?? ''; ?>
                        <tr><td class="font-mono small"><?= e($r['chart_number']) ?></td>
                            <td class="small"><?= $nm!==''?e($nm):'—' ?></td>
                            <td class="small"><?= e($r['claim_status'] ?? '—') ?></td>
                            <td class="small"><?= e($r['action_taken'] ?? '—') ?><?php if ($bk && isset($bb[$bk])): ?> <span class="badge bg-<?= $bb[$bk][1] ?>-lt"><?= e($bb[$bk][0]) ?></span><?php endif; ?></td>
                            <td class="text-nowrap small" data-v="<?= e((string)($r['worked_at'] ?? '')) ?>"><?= e(fmt_date($r['worked_at'])) ?></td></tr>
                    <?php endforeach; endif; ?>
                    </tbody></table></div></div></div>
            <?php else: ?>
            <div class="col-lg-6"><div class="card mb-3"><div class="card-header py-2"><h3 class="card-title small"><i class="ti ti-building-bank me-1"></i>By carrier</h3></div>
                <div class="table-responsive" style="max-height:460px"><table class="table table-vcenter card-table table-sm ar-pivot">
                    <thead><tr><th onclick="arSortPivot(this)" style="cursor:pointer">Carrier</th>
                        <th class="text-end" data-num="1" onclick="arSortPivot(this)" style="cursor:pointer">Accounts</th>
                        <th class="text-end" data-num="1" onclick="arSortPivot(this)" style="cursor:pointer">Visits</th>
                        <th class="text-end" data-num="1" onclick="arSortPivot(this)" style="cursor:pointer">Ins. balance ▾</th></tr></thead>
                    <tbody>
                    <?php if (!$alc['carrier']): ?><tr><td colspan="4" class="text-center text-secondary py-3">No allocated inventory.</td></tr>
                    <?php else: foreach ($alc['carrier'] as $r): ?>
                        <tr><td class="small"><?= e($r['carrier']) ?></td>
                            <td class="text-end" data-v="<?= (int)$r['accounts'] ?>"><?= number_format((int)$r['accounts']) ?></td>
                            <td class="text-end" data-v="<?= (int)$r['visits'] ?>"><?= number_format((int)$r['visits']) ?></td>
                            <td class="text-end font-mono fw-medium" data-v="<?= (float)$r['ins_bal'] ?>"><?= number_format((float)$r['ins_bal'],2) ?></td></tr>
                    <?php endforeach; endif; ?>
                    </tbody></table></div></div></div>
            <?php endif; ?>
            <div class="col-lg-6"><div class="card mb-3"><div class="card-header py-2"><h3 class="card-title small"><i class="ti ti-users me-1"></i>By patient &amp; visits</h3></div>
                <div class="table-responsive" style="max-height:460px"><table class="table table-vcenter card-table table-sm ar-pivot">
                    <thead><tr><th onclick="arSortPivot(this)" style="cursor:pointer">Patient</th>
                        <th onclick="arSortPivot(this)" style="cursor:pointer">Account #</th>
                        <th onclick="arSortPivot(this)" style="cursor:pointer">Carrier</th>
                        <th class="text-end" data-num="1" onclick="arSortPivot(this)" style="cursor:pointer">Visits ▾</th>
                        <th class="text-end" data-num="1" onclick="arSortPivot(this)" style="cursor:pointer">Ins. balance</th>
                        <th class="w-1"></th></tr></thead>
                    <tbody>
                    <?php if (!$alc['patient']): ?><tr><td colspan="6" class="text-center text-secondary py-3">No allocated inventory.</td></tr>
                    <?php else: foreach ($alc['patient'] as $r): $nm = $alc['names'][(int)$r['process_id'].'|'.(string)$r['chart_number']] ?? ''; ?>
                        <tr><td class="small"><?= $nm!==''?e($nm):'<span class="text-secondary">—</span>' ?></td>
                            <td class="font-mono small"><?= e($r['chart_number']) ?></td>
                            <td class="small"><?= e($r['carrier'] ?? '—') ?></td>
                            <td class="text-end" data-v="<?= (int)$r['visits'] ?>"><span class="badge bg-blue-lt"><?= number_format((int)$r['visits']) ?></span></td>
                            <td class="text-end font-mono fw-medium" data-v="<?= (float)$r['ins_bal'] ?>"><?= number_format((float)$r['ins_bal'],2) ?></td>
                            <td><?php if ($role === 'user'): ?><a href="<?= e(url('/admin/ar-work.php?process='.(int)$r['process_id'].'&account='.rawurlencode((string)$r['chart_number']))) ?>" class="btn btn-sm btn-outline-primary"><i class="ti ti-folder-open"></i></a><?php endif; ?></td></tr>
                    <?php endforeach; endif; ?>
                    </tbody></table></div></div></div>
        </div>

    <?php elseif ($report === 'progress'): /* allocated inventory vs worked */ ?>
        <?php $t = $prog['tot']; $tA=(int)($t['allocated']??0); $tW=(int)($t['worked']??0); $tP=$tA-$tW; $tPct=$tA>0?round(100*$tW/$tA,1):0; ?>
        <div class="row row-cards mb-3">
            <?php foreach ([['Allocated visits',number_format($tA),'primary'],['Worked',number_format($tW),'green'],['Pending',number_format($tP),'orange'],['% worked',$tPct.'%',$tPct>=90?'green':($tPct>=60?'yellow':'red')]] as $k): ?>
                <div class="col-6 col-md-3"><div class="card card-sm"><div class="card-body"><div class="text-secondary small text-uppercase"><?= e($k[0]) ?></div><div class="h1 m-0 text-<?= e($k[2]) ?>"><?= $k[1] ?></div></div></div></div>
            <?php endforeach; ?>
        </div>
        <div class="text-secondary small mb-2"><i class="ti ti-info-circle me-1"></i>Allocated inventory <strong>vs</strong> worked — <?= $isTeam ? "your team's data" : 'your data' ?>. Click any column to re-sort.</div>
        <?php
        $renderProg = function (string $title, string $icon, string $dimLabel, array $rows, string $dimKey) { ?>
            <div class="col-lg-6"><div class="card mb-3"><div class="card-header py-2"><h3 class="card-title small"><i class="ti ti-<?= e($icon) ?> me-1"></i><?= e($title) ?></h3></div>
                <div class="table-responsive" style="max-height:420px"><table class="table table-vcenter card-table table-sm ar-pivot">
                    <thead><tr><th onclick="arSortPivot(this)" style="cursor:pointer"><?= e($dimLabel) ?></th>
                        <th class="text-end" data-num="1" onclick="arSortPivot(this)" style="cursor:pointer">Allocated ▾</th>
                        <th class="text-end" data-num="1" onclick="arSortPivot(this)" style="cursor:pointer">Worked</th>
                        <th class="text-end" data-num="1" onclick="arSortPivot(this)" style="cursor:pointer">Pending</th>
                        <th class="text-end" data-num="1" onclick="arSortPivot(this)" style="cursor:pointer">% worked</th></tr></thead>
                    <tbody>
                    <?php if (!$rows): ?><tr><td colspan="5" class="text-center text-secondary py-3">No allocated inventory.</td></tr>
                    <?php else: foreach ($rows as $r): $a=(int)$r['allocated']; $wk=(int)$r['worked']; $pen=$a-$wk; $pct=$a>0?round(100*$wk/$a,1):0; ?>
                        <tr><td class="small"><?= e($r[$dimKey] ?? '—') ?></td>
                            <td class="text-end fw-medium" data-v="<?= $a ?>"><?= number_format($a) ?></td>
                            <td class="text-end" data-v="<?= $wk ?>"><span class="badge bg-green-lt"><?= number_format($wk) ?></span></td>
                            <td class="text-end" data-v="<?= $pen ?>"><?= $pen ? '<span class="badge bg-orange-lt">'.number_format($pen).'</span>' : '0' ?></td>
                            <td class="text-end" data-v="<?= $pct ?>"><span class="badge bg-<?= $pct>=90?'green':($pct>=60?'yellow':'red') ?>-lt"><?= $pct ?>%</span></td></tr>
                    <?php endforeach; endif; ?>
                    </tbody></table></div></div></div>
        <?php };
        $procRows = array_map(function ($r) { $r['dim'] = trim(($r['cname'] ?? '') . ' › ' . ($r['pname'] ?? ''), ' ›'); return $r; }, $prog['process']);
        ?>
        <div class="row">
            <?php $renderProg('By process', 'route', 'Process', $procRows, 'dim'); ?>
            <?php $renderProg('By carrier', 'building-bank', 'Carrier', $prog['carrier'], 'carrier'); ?>
        </div>
        <?php if ($isTeam): ?>
        <div class="row">
            <?php $renderProg('By user', 'user', 'User', $prog['user'], 'uname'); ?>
            <?php $renderProg('By supervisor', 'users-group', 'Supervisor', $prog['supervisor'], 'sname'); ?>
        </div>
        <?php endif; ?>
    <?php endif; ?>

</div></div>
<script>
function arSortPivot(th){
    var table=th.closest('table'), tb=table.tBodies[0], idx=Array.prototype.indexOf.call(th.parentNode.children, th);
    var asc=(th.getAttribute('data-asc')!=='1');
    Array.prototype.forEach.call(th.parentNode.children,function(h){ h.removeAttribute('data-asc'); h.innerHTML=h.innerHTML.replace(/ [▾▴]$/,''); });
    th.setAttribute('data-asc', asc?'1':'0'); th.innerHTML=th.innerHTML.replace(/ [▾▴]$/,'')+(asc?' ▴':' ▾');
    var num=th.getAttribute('data-num')==='1';
    var rows=Array.prototype.slice.call(tb.rows).filter(function(r){ return r.cells.length>1; });
    rows.sort(function(a,b){
        var x=a.cells[idx], y=b.cells[idx];
        x=num?parseFloat(x.getAttribute('data-v')||0):x.textContent.trim();
        y=num?parseFloat(y.getAttribute('data-v')||0):y.textContent.trim();
        if(num) return asc? x-y : y-x;
        return asc? String(x).localeCompare(y) : String(y).localeCompare(x);
    });
    rows.forEach(function(r){ tb.appendChild(r); });
}
</script>
<?php require __DIR__ . '/../includes/footer.php'; ?>
