<?php
/**
 * Billing reports (billing.reports / billing.supervise / billing.allocate).
 *
 * Productivity & disposition reporting over the biller WORK actions (billing_allocation_event, event='work').
 * Pick a period grain (Daily / Weekly / Monthly) and a date range; optional client / process / facility scope.
 *   - KPIs: charts worked + Billed / Hold-Deductible / Unbilled splits in range.
 *   - Over time: one row per period with the disposition split.
 *   - By biller: per-biller productivity.
 *   - By carrier: volume + disposition per insurance carrier.
 * CSV export of the over-time series via ?export=csv.
 */
require_once __DIR__ . '/../includes/config.php';
$user = require_login('internal');
$pdo  = db();

$period = in_array($_GET['period'] ?? '', ['day','week','month'], true) ? (string) $_GET['period'] : 'day';
$report = in_array($_GET['report'] ?? '', ['production','quality'], true) ? (string) $_GET['report'] : 'production';   // two tabs
// Validate as a REAL calendar date (not just the regex shape): rejects non-string input (e.g. ?to[]=x →
// no "Array to string" warning) AND calendar-invalid values like 2026-13-99 (which would make strtotime()
// return false → date(...,false) collapse to 1970 → every query silently returns 0 rows).
$validYmd = fn($v) => is_string($v) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $v)
    && checkdate((int) substr($v, 5, 2), (int) substr($v, 8, 2), (int) substr($v, 0, 4));
$to   = $validYmd($_GET['to']   ?? null) ? (string) $_GET['to']   : date('Y-m-d');
$from = $validYmd($_GET['from'] ?? null) ? (string) $_GET['from'] : date('Y-m-d', strtotime('-29 days'));
$toExcl = date('Y-m-d', strtotime($to . ' +1 day'));
$fClient=(int)($_GET['client_id']??0); $fProcess=(int)($_GET['process_id']??0); $fFacility=(int)($_GET['facility_id']??0);
$fBiller=(int)($_GET['biller_id']??0); $fAuditor=(int)($_GET['auditor_id']??0);
$uid = (int) $user['id'];

/* ROLE SCOPE: a biller sees ONLY their own data; a supervisor/manager sees their TEAM (reports_to subtree, incl.
   sub-supervisors → their billers); sysadmin sees everyone. (Billers hold billing.reports, so they reach this page
   — but must not see other billers' numbers.) */
$isSup   = can('billing.supervise');
$teamIds = $isSup ? coding_team_scope($pdo, $uid) : [$uid];     // null = unrestricted (sysadmin)
if ($fBiller && $teamIds !== null && !in_array($fBiller, $teamIds, true)) $fBiller = 0;   // can't peek outside the team
$teamMembers = $isSup
    ? ($teamIds === null
        ? billing_allocatable_billers($pdo)                                               // sysadmin → all billers
        : $pdo->query("SELECT u.id, u.name FROM users u WHERE u.id IN (".implode(',', array_map('intval', $teamIds ?: [0])).") ORDER BY u.name")->fetchAll())
    : [];                                                                                 // biller → no member picker
$userIn      = $fBiller ? [$fBiller] : ($teamIds === null ? null : ($teamIds ?: [0]));     // null = all (sysadmin)
$userScope   = $userIn === null ? '' : (' AND ev.user_id IN (' . implode(',', array_map('intval', $userIn)) . ')');
$allocScope  = $userIn === null ? '' : (' AND a.allocated_biller IN (' . implode(',', array_map('intval', $userIn)) . ')');

$scope = $userScope; $sp = [];   // ci.* filters + the role/user fence (interpolated ints)
if ($fClient)   { $scope .= ' AND ci.client_id=?';   $sp[] = $fClient; }
if ($fProcess)  { $scope .= ' AND ci.process_id=?';  $sp[] = $fProcess; }
if ($fFacility) { $scope .= ' AND ci.facility_id=?'; $sp[] = $fFacility; }

// Period bucket SQL (Monday-of-week for the weekly grain).
$bucket = $period==='month' ? "DATE_FORMAT(ev.created_at,'%Y-%m')"
        : ($period==='week' ? "DATE(DATE_SUB(DATE(ev.created_at), INTERVAL WEEKDAY(ev.created_at) DAY))"
                            : "DATE(ev.created_at)");
$base = "FROM billing_allocation_event ev JOIN coding_inventory ci ON ci.id=ev.inventory_id
         WHERE ev.event='work' AND ev.created_at>=? AND ev.created_at<? $scope";
$args = array_merge([$from, $toExcl], $sp);
// 'worked' = work-event rows (a rework re-save adds one → work ACTIONS); 'charts' = DISTINCT charts (rework never
// inflates it). Both are surfaced so range-production reconciles with the current-backlog snapshot (they measure
// different things: actions-in-range keyed on ev.user_id vs charts-owned-now keyed on allocated_biller).
$splits = "COUNT(*) worked, COUNT(DISTINCT ev.inventory_id) charts,
           SUM(ev.billing_status='billed') billed,
           SUM(ev.billing_status='hold_deductible') hold_deductible,
           SUM(ev.billing_status='unbilled') unbilled";

/* ---- Over-time series ---- */
$ts = $pdo->prepare("SELECT $bucket bucket, COUNT(DISTINCT ev.user_id) billers, $splits $base GROUP BY bucket ORDER BY bucket DESC");
$ts->execute($args); $series = $ts->fetchAll();

/* CSV export of the time series (streamed before any HTML). */
if (($_GET['export'] ?? '') === 'csv') {
    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="billing-report-' . $period . '-' . $from . '_' . $to . '.csv"');
    $out = fopen('php://output', 'w'); fwrite($out, "\xEF\xBB\xBF");
    fputcsv($out, [ucfirst($period), 'Billers', 'Worked', 'Billed', 'Hold-Deductible', 'Unbilled']);
    foreach ($series as $r) fputcsv($out, [$r['bucket'],(int)$r['billers'],(int)$r['worked'],(int)$r['billed'],(int)$r['hold_deductible'],(int)$r['unbilled']]);
    fclose($out); exit;
}

/* ---- Per-bucket production drill-down: the individual charts worked in ONE bucket (a date for the daily grain).
   Shared by the inline expand (?drill=<bucket>) and the Excel export (?export=production&date=<bucket>). Same
   scope + role/user fence as the series, so a supervisor can never drill outside their team. ---- */
$drill = trim((string) ($_GET['drill'] ?? ''));
/* Per-bucket ($bucketVal set) OR whole-range ($bucketVal null) production detail. Same scope + role/user fence
   as the series, so a supervisor can never drill outside their team. */
$prodDetail = function (?string $bucketVal = null) use ($pdo, $bucket, $scope, $from, $toExcl, $sp): array {
    $bucketClause = $bucketVal !== null ? " AND $bucket=?" : '';
    $q = $pdo->prepare("SELECT u.name biller, ci.patient_name, ci.patient_mrn, c.name cn, p.name pn, f.name fn,
            COALESCE(bp.name, cp.name, pr.name) provider, ci.dos, ev.billing_status, ev.carrier, ev.secondary_reason, ev.created_at
        FROM billing_allocation_event ev
        JOIN coding_inventory ci ON ci.id=ev.inventory_id
        LEFT JOIN users u ON u.id=ev.user_id
        LEFT JOIN clients c ON c.id=ci.client_id
        LEFT JOIN processes p ON p.id=ci.process_id
        LEFT JOIN coding_facilities f ON f.id=ci.facility_id
        LEFT JOIN coding_providers bp ON bp.id=ci.billing_provider_id
        LEFT JOIN coding_providers cp ON cp.id=ci.coded_provider_id
        LEFT JOIN coding_providers pr ON pr.id=ci.provider_id
        WHERE ev.event='work' AND ev.created_at>=? AND ev.created_at<? $scope $bucketClause
        ORDER BY u.name, ev.created_at");
    $q->execute(array_merge([$from, $toExcl], $sp, $bucketVal !== null ? [$bucketVal] : []));
    return $q->fetchAll();
};
/* Shared production→spreadsheet mapping (one row per worked CPT-chart action). */
$prodHeaders = ['Biller','Patient','MRN','Client','Process','Facility','Provider','Chart DOS','Billing status','Carrier','Reason','Worked at'];
$prodToRows  = function (array $prodRows): array {
    $bsLabel = ['billed'=>'Billed','hold_deductible'=>'Hold-Deductible','unbilled'=>'Unbilled'];
    $out = [];
    foreach ($prodRows as $r) $out[] = [
        $r['biller'] ?: '—', $r['patient_name'], $r['patient_mrn'] ?: '', $r['cn'], $r['pn'], $r['fn'], $r['provider'] ?: '',
        !empty($r['dos']) ? date('Y-m-d', strtotime($r['dos'])) : '',
        $bsLabel[$r['billing_status']] ?? ($r['billing_status'] ?: ''), $r['carrier'] ?: '', $r['secondary_reason'] ?: '',
        disp_dt($r['created_at']),
    ];
    return $out;
};

/* Excel export of ONE bucket's production detail. */
$drillDate = trim((string) ($_GET['date'] ?? ''));
if (($_GET['export'] ?? '') === 'production' && $drillDate !== '') {
    require_once __DIR__ . '/../includes/xlsx.php';
    $out = $prodToRows($prodDetail($drillDate));
    $x = new SimpleXlsx();
    $x->addSheet('Production', $prodHeaders, $out);
    audit_log('billing.reports.export_production', 'scope', null, null, ['bucket'=>$drillDate, 'rows'=>count($out)]);
    $x->download('billing-production-' . preg_replace('/[^0-9A-Za-z_-]/', '', $drillDate) . '.xlsx');
    exit;
}

/* #6 — Excel export of the WHOLE selected range's production detail, with the active user/process/client/facility
   filters applied (not limited to one bucket). Same role/team fence as everything else on this page. */
if (($_GET['export'] ?? '') === 'production_all') {
    require_once __DIR__ . '/../includes/xlsx.php';
    $out = $prodToRows($prodDetail(null));
    $x = new SimpleXlsx();
    $x->addSheet('Production', $prodHeaders, $out);
    audit_log('billing.reports.export_production_all', 'scope', null, null,
        ['from'=>$from, 'to'=>$to, 'rows'=>count($out), 'biller'=>$fBiller, 'process'=>$fProcess, 'client'=>$fClient, 'facility'=>$fFacility]);
    $x->download('billing-production-' . $from . '_' . $to . '.xlsx');
    exit;
}

/* #7 — Excel export of the AUDITORS' worked files: every chart audited in the range, one row per audited chart,
   with the auditor, the worker (biller), the DPO score and the auditor's findings. Fenced to the viewer's team
   (allocated_biller scope) + the active client/process/facility filters + an optional single-auditor filter.
   Supervisor/manager/sysadmin only (a plain biller must not see auditor productivity). */
if (($_GET['export'] ?? '') === 'audit_all') {
    if (!$isSup) { http_response_code(403); exit('Forbidden'); }
    require_once __DIR__ . '/../includes/xlsx.php';
    $aScope = $allocScope; $ap = [$from, $toExcl];              // allocScope = role/team fence on a.allocated_biller (ints inlined)
    if ($fClient)   { $aScope .= ' AND ci.client_id=?';   $ap[] = $fClient; }
    if ($fProcess)  { $aScope .= ' AND ci.process_id=?';  $ap[] = $fProcess; }
    if ($fFacility) { $aScope .= ' AND ci.facility_id=?'; $ap[] = $fFacility; }
    if ($fAuditor)  { $aScope .= ' AND a.auditor_id=?';   $ap[] = $fAuditor; }
    $ast = $pdo->prepare("SELECT au.name auditor, u.name worker, ci.patient_name, ci.patient_mrn, c.name cn, p.name pn, f.name fn,
            COALESCE(bp.name, cp.name, pr.name) provider, ci.dos, a.audit_result, a.audit_opportunities, a.audit_defects,
            a.audit_error_category, a.audit_comment, a.audited_at
        FROM billing_allocation a
        JOIN coding_inventory ci ON ci.id=a.inventory_id
        LEFT JOIN users au ON au.id=a.auditor_id
        LEFT JOIN users u  ON u.id=a.allocated_biller
        LEFT JOIN clients c ON c.id=ci.client_id
        LEFT JOIN processes p ON p.id=ci.process_id
        LEFT JOIN coding_facilities f ON f.id=ci.facility_id
        LEFT JOIN coding_providers bp ON bp.id=ci.billing_provider_id
        LEFT JOIN coding_providers cp ON cp.id=ci.coded_provider_id
        LEFT JOIN coding_providers pr ON pr.id=ci.provider_id
        WHERE a.audit_result IS NOT NULL AND a.audited_at>=? AND a.audited_at<? $aScope
        ORDER BY au.name, a.audited_at");
    $ast->execute($ap); $auRows = $ast->fetchAll();
    $out = [];
    foreach ($auRows as $r) {
        $opp = (int) $r['audit_opportunities']; $def = (int) $r['audit_defects'];
        $acc = $opp > 0 ? round(100 * ($opp - $def) / $opp, 1) . '%' : '';
        $out[] = [$r['auditor'] ?: '—', $r['worker'] ?: '—', $r['patient_name'], $r['patient_mrn'] ?: '', $r['cn'], $r['pn'], $r['fn'],
            $r['provider'] ?: '', !empty($r['dos']) ? date('Y-m-d', strtotime($r['dos'])) : '',
            ucfirst((string) ($r['audit_result'] ?: '')), $opp ?: '', $def ?: '', $acc,
            $r['audit_error_category'] ?: '', $r['audit_comment'] ?: '',
            disp_dt($r['audited_at'])];
    }
    $x = new SimpleXlsx();
    $x->addSheet('Auditor production', ['Auditor','Worker (biller)','Patient','MRN','Client','Process','Facility','Provider','Chart DOS','Result','Opportunities','Defects','Accuracy','Error category','Comment','Audited at'], $out);
    audit_log('billing.reports.export_audit_all', 'scope', null, null, ['from'=>$from, 'to'=>$to, 'rows'=>count($out), 'auditor'=>$fAuditor]);
    $x->download('billing-auditor-production-' . $from . '_' . $to . '.xlsx');
    exit;
}
$drillRows = ($drill !== '') ? $prodDetail($drill) : [];

/* ---- KPIs (whole range) ---- */
$kst = $pdo->prepare("SELECT $splits, COUNT(DISTINCT ev.user_id) billers $base");
$kst->execute($args); $K = $kst->fetch() ?: ['worked'=>0,'charts'=>0,'billed'=>0,'hold_deductible'=>0,'unbilled'=>0,'billers'=>0];

/* ---- By biller ($base can't be reused: the JOIN must precede WHERE) ---- */
$bst = $pdo->prepare("SELECT u.name biller, $splits
    FROM billing_allocation_event ev JOIN coding_inventory ci ON ci.id=ev.inventory_id LEFT JOIN users u ON u.id=ev.user_id
    WHERE ev.event='work' AND ev.created_at>=? AND ev.created_at<? $scope AND ev.user_id IS NOT NULL
    GROUP BY ev.user_id, u.name ORDER BY worked DESC");
$bst->execute($args); $byBiller = $bst->fetchAll();

/* ---- By carrier ---- */
$cst = $pdo->prepare("SELECT COALESCE(NULLIF(ev.carrier,''),'(none)') carrier, $splits $base GROUP BY carrier ORDER BY worked DESC LIMIT 100");
$cst->execute($args); $byCarrier = $cst->fetchAll();

/* ---- By client / process / facility (range production, event stream) ---- */
$mkProdBy = function (string $grp, string $joinX) use ($pdo, $splits, $scope, $from, $toExcl, $sp) {
    $st = $pdo->prepare("SELECT $grp grp, $splits
        FROM billing_allocation_event ev JOIN coding_inventory ci ON ci.id=ev.inventory_id $joinX
        WHERE ev.event='work' AND ev.created_at>=? AND ev.created_at<? $scope GROUP BY grp ORDER BY charts DESC, worked DESC LIMIT 100");
    $st->execute(array_merge([$from, $toExcl], $sp)); return $st->fetchAll();
};
$byClientProd   = $mkProdBy("COALESCE(c.name,'(none)')", "LEFT JOIN clients c ON c.id=ci.client_id");
$byProcessProd  = $mkProdBy("COALESCE(p.name,'(none)')", "LEFT JOIN processes p ON p.id=ci.process_id");
$byFacilityProd = $mkProdBy("COALESCE(f.name,'(none)')", "LEFT JOIN coding_facilities f ON f.id=ci.facility_id");

/* ---- Audit quality by biller (DPO) — charts AUDITED in the range (uses audited_at on billing_allocation) ---- */
$qScope = $allocScope; $qp = [$from, $toExcl];
if ($fClient)   { $qScope .= ' AND ci.client_id=?';   $qp[] = $fClient; }
if ($fProcess)  { $qScope .= ' AND ci.process_id=?';  $qp[] = $fProcess; }
if ($fFacility) { $qScope .= ' AND ci.facility_id=?'; $qp[] = $fFacility; }
/* Quality metric expression — shared by the totals row, by-biller and by-auditor breakdowns. audit_flagged (advisory
   6th item) is counted separately: it forces result='error' (routes to the biller's rebuttal queue) but is EXCLUDED
   from opportunities/defects so it never moves the DPO quality score. rebuttal_status buckets the biller's response. */
$qMetric = "COUNT(*) audited, SUM(a.audit_result='pass') pass, SUM(a.audit_result='error') error,
        COALESCE(SUM(a.audit_opportunities),0) opp, COALESCE(SUM(a.audit_defects),0) def,
        COALESCE(SUM(a.audit_flagged),0) flagged,
        SUM(a.rebuttal_status='raised') reb_open, SUM(a.rebuttal_status='accepted') reb_won,
        SUM(a.rebuttal_status='rejected') reb_lost, SUM(a.rebuttal_status='agreed') reb_agreed";
$qWhere = "WHERE a.audit_result IS NOT NULL AND a.audited_at>=? AND a.audited_at<? $qScope";
$qFrom  = "FROM billing_allocation a JOIN coding_inventory ci ON ci.id=a.inventory_id";

$qst = $pdo->prepare("SELECT u.name biller, $qMetric $qFrom LEFT JOIN users u ON u.id=a.allocated_biller $qWhere
    GROUP BY a.allocated_biller, u.name ORDER BY audited DESC");
$qst->execute($qp); $byQuality = $qst->fetchAll();

/* Quality totals for the range (single summary row). */
$qtot = $pdo->prepare("SELECT $qMetric $qFrom $qWhere"); $qtot->execute($qp); $QT = $qtot->fetch() ?: [];

/* By AUDITOR — who audited how much and how they scored (supervisor/manager/sysadmin only). */
$byAuditor = [];
if ($isSup) {
    $aust = $pdo->prepare("SELECT au.name auditor, $qMetric $qFrom LEFT JOIN users au ON au.id=a.auditor_id $qWhere
        GROUP BY a.auditor_id, au.name ORDER BY audited DESC");
    $aust->execute($qp); $byAuditor = $aust->fetchAll();
}

/* Defects by AUDIT PARAMETER (Quality tab) — pass/fail per param, over the same audited range/scope, so the tab can
   show each parameter's fail-rate. Wrapped defensively so the report still renders before the per-param table exists. */
$byParam = [];
try {
    $pst = $pdo->prepare("SELECT ap.param_key, COUNT(*) total, SUM(ap.result='fail') fails, SUM(ap.result='pass') passes
        FROM billing_audit_param ap JOIN billing_allocation a ON a.id=ap.allocation_id JOIN coding_inventory ci ON ci.id=a.inventory_id
        WHERE a.audit_result IS NOT NULL AND a.audited_at>=? AND a.audited_at<? $qScope
        GROUP BY ap.param_key ORDER BY fails DESC");
    $pst->execute($qp); $byParam = $pst->fetchAll();
} catch (Throwable $e) { $byParam = []; }

/* ---- BILLED CPT LINES (which CPTs the billers marked finalized/billed, in the range) ----
   Scoped by billed_by (role/user fence) + ci.* filters; date-bounded by billed_at. Wrapped defensively
   so the report still renders if the per-line table hasn't been provisioned yet. */
$BC = ['lines'=>0,'charts'=>0]; $byCpt = [];
try {
    $bcUser  = $userIn === null ? '' : (' AND bcc.billed_by IN (' . implode(',', array_map('intval', $userIn)) . ')');
    $bcScope = ''; $bcp = [$from, $toExcl];
    if ($fClient)   { $bcScope .= ' AND ci.client_id=?';   $bcp[] = $fClient; }
    if ($fProcess)  { $bcScope .= ' AND ci.process_id=?';  $bcp[] = $fProcess; }
    if ($fFacility) { $bcScope .= ' AND ci.facility_id=?'; $bcp[] = $fFacility; }
    $bcBase = "FROM billing_chart_cpt bcc JOIN coding_inventory ci ON ci.id=bcc.inventory_id
               WHERE bcc.billed=1 AND bcc.billed_at>=? AND bcc.billed_at<? $bcUser $bcScope";
    $t = $pdo->prepare("SELECT COUNT(*) lines, COUNT(DISTINCT bcc.inventory_id) charts $bcBase");
    $t->execute($bcp); $BC = $t->fetch() ?: $BC;
    // Group by the FINALIZED billed code (CPT or ALF value the biller chose), with its type.
    $c = $pdo->prepare("SELECT COALESCE(NULLIF(bcc.billed_code,''), NULLIF(bcc.cpt_code,''), '(blank)') code,
                               COALESCE(NULLIF(bcc.billed_code_type,''),'cpt') type,
                               COUNT(*) lines, COUNT(DISTINCT bcc.inventory_id) charts
                        $bcBase GROUP BY code, type ORDER BY lines DESC LIMIT 200");
    $c->execute($bcp); $byCpt = $c->fetchAll();
} catch (Throwable $e) { /* billing_chart_cpt not provisioned yet */ }

/* ---- ALLOCATED vs WORKED (current snapshot of billing_allocation, role-scoped + ci.* filters) ----
   Allocated = every chart on the team's plates; Worked = inventory_status='worked'; Pending = the rest;
   disposition = billing_status. Shown overall + by biller / client / carrier. NOT date-bounded (it's a backlog view). */
// count only charts CURRENTLY on a plate — exclude pulled-back / sent-to-RFI rows (allocated_biller NULL, non-worked
// status) so Allocated = Worked + Pending holds and the SysAdmin (unfenced) view doesn't over-count off-plate rows.
$avScope = $allocScope . " AND a.allocated_biller IS NOT NULL AND a.inventory_status IN ('allocated','worked')"; $ap = [];
if ($fClient)   { $avScope .= ' AND ci.client_id=?';   $ap[] = $fClient; }
if ($fProcess)  { $avScope .= ' AND ci.process_id=?';  $ap[] = $fProcess; }
if ($fFacility) { $avScope .= ' AND ci.facility_id=?'; $ap[] = $fFacility; }
$avMetric = "COUNT(*) allocated, COALESCE(SUM(a.inventory_status='worked'),0) worked,
             COALESCE(SUM(a.inventory_status<>'worked'),0) pending,
             COALESCE(SUM(a.work_count>1),0) reworked,
             COALESCE(SUM(a.billing_status='billed'),0) billed,
             COALESCE(SUM(a.billing_status='hold_deductible'),0) hold_deductible,
             COALESCE(SUM(a.billing_status='unbilled'),0) unbilled";
$avFrom = "FROM billing_allocation a JOIN coding_inventory ci ON ci.id=a.inventory_id";
$avTot   = $pdo->prepare("SELECT $avMetric $avFrom WHERE 1=1 $avScope"); $avTot->execute($ap); $AV = $avTot->fetch() ?: [];
$avByBiller = $pdo->prepare("SELECT u.name biller, $avMetric $avFrom LEFT JOIN users u ON u.id=a.allocated_biller WHERE 1=1 $avScope GROUP BY a.allocated_biller, u.name ORDER BY allocated DESC");
$avByBiller->execute($ap); $avByBiller = $avByBiller->fetchAll();
$avByClient = $pdo->prepare("SELECT c.name cn, $avMetric $avFrom JOIN clients c ON c.id=ci.client_id WHERE 1=1 $avScope GROUP BY ci.client_id, c.name ORDER BY allocated DESC");
$avByClient->execute($ap); $avByClient = $avByClient->fetchAll();

$clients = $pdo->query("SELECT DISTINCT c.id,c.name FROM coding_inventory ci JOIN clients c ON c.id=ci.client_id WHERE " . billing_released_where('ci') . " ORDER BY c.name")->fetchAll();
$procs   = $pdo->query("SELECT DISTINCT p.id,p.name,c.name cn FROM coding_inventory ci JOIN processes p ON p.id=ci.process_id JOIN clients c ON c.id=ci.client_id WHERE " . billing_released_where('ci') . " ORDER BY c.name,p.name")->fetchAll();
$facils  = $pdo->query("SELECT DISTINCT f.id,f.name FROM coding_inventory ci JOIN coding_facilities f ON f.id=ci.facility_id WHERE " . billing_released_where('ci') . " ORDER BY f.name")->fetchAll();
/* Auditor picker for the #7 auditor-files export (active billing.audit holders) — supervisor/manager/sysadmin only. */
$auditors = $isSup ? $pdo->query("SELECT DISTINCT u.id, u.name FROM users u
        JOIN user_roles ur ON ur.user_id=u.id JOIN role_permissions rp ON rp.role_id=ur.role_id JOIN permissions pm ON pm.id=rp.permission_id
        WHERE pm.code='billing.audit' AND u.status='active' AND u.user_type='internal' ORDER BY u.name")->fetchAll() : [];

$selfUrl = fn(array $o=[]) => '/admin/billing-reports.php?' . http_build_query(array_filter(array_merge(['report'=>$report,'period'=>$period,'from'=>$from,'to'=>$to,'client_id'=>$fClient,'process_id'=>$fProcess,'facility_id'=>$fFacility,'biller_id'=>$fBiller,'auditor_id'=>$fAuditor],$o), fn($v)=>$v!==null&&$v!==''&&$v!==0));
$fmtBucket = fn($b) => $period==='month' ? date('M Y', strtotime($b.'-01')) : ($period==='week' ? 'Wk of '.date('d M Y', strtotime($b)) : date('D, d M Y', strtotime($b)));

$pageTitle = 'Billing reports';
require __DIR__ . '/../includes/header.php';
// Charts (DISTINCT inventory) · Work actions (COUNT(*) event rows, rework-inflated) · Billed · Hold · Unbilled.
$splitCells = function(array $r) {
    return '<td class="text-end fw-bold">'.number_format((int)($r['charts'] ?? 0)).'</td>'
        .'<td class="text-end text-secondary">'.number_format((int)$r['worked']).'</td>'
        .'<td class="text-end"><span class="text-green">'.number_format((int)$r['billed']).'</span></td>'
        .'<td class="text-end"><span class="text-orange">'.number_format((int)$r['hold_deductible']).'</span></td>'
        .'<td class="text-end"><span class="text-red">'.number_format((int)$r['unbilled']).'</span></td>';
};
// header cells matching $splitCells (Charts · Actions · Billed · Hold · Unbilled).
$splitHead = '<th class="text-end">Charts</th><th class="text-end">Work actions</th><th class="text-end">Billed</th><th class="text-end">Hold/Deduct</th><th class="text-end">Unbilled</th>';
/* Allocated · Worked · Pending · % · Billed · Hold · Unbilled cells for the allocation-vs-worked tables. */
$avCells = function(array $r) {
    $a=(int)$r['allocated']; $w=(int)$r['worked']; $pen=(int)$r['pending']; $pct=$a>0?round(100*$w/$a):0;
    $pc = $pct>=90?'green':($pct>=60?'orange':'red');
    return '<td class="text-end fw-bold">'.number_format($a).'</td>'
        .'<td class="text-end"><span class="text-green">'.number_format($w).'</span></td>'
        .'<td class="text-end"><span class="'.($pen?'text-orange':'text-secondary').'">'.number_format($pen).'</span></td>'
        .'<td class="text-end fw-bold text-'.$pc.'">'.$pct.'%</td>'
        .'<td class="text-end text-secondary">'.number_format((int)$r['billed']).'</td>'
        .'<td class="text-end text-secondary">'.number_format((int)$r['hold_deductible']).'</td>'
        .'<td class="text-end text-secondary">'.number_format((int)$r['unbilled']).'</td>';
};
$roleLabel = $isSup ? ($teamIds===null ? 'all billers' : 'your team') : 'your own work';
?>
<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-bar me-2 text-primary"></i>Billing reports</h2>
        <div class="text-secondary small">Allocated-vs-worked &amp; biller productivity — showing <strong><?= e($roleLabel) ?></strong>. <span class="badge bg-blue-lt ms-1"><?= $isSup ? ($teamIds===null?'SysAdmin':'Supervisor/Manager') : 'Biller' ?> view</span></div>
    </div>
    <div class="col-auto d-flex flex-wrap gap-2">
        <a href="<?= e(url($selfUrl(['export'=>'csv']))) ?>" class="btn btn-outline-secondary"><i class="ti ti-download me-1"></i>Export CSV</a>
        <a href="<?= e(url($selfUrl(['export'=>'production_all']))) ?>" class="btn btn-outline-success" title="Every chart worked in the selected date range, with the current user/process filters"><i class="ti ti-file-spreadsheet me-1"></i>Production (range)</a>
        <?php if ($isSup): ?><a href="<?= e(url($selfUrl(['export'=>'audit_all']))) ?>" class="btn btn-outline-success" title="Every chart audited in the range — the auditors' worked files"><i class="ti ti-shield-check me-1"></i>Auditor files (range)</a><?php endif; ?>
    </div>
</div></div></div>

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

    <form method="GET" class="card mb-3"><div class="card-body row g-2 align-items-end">
        <input type="hidden" name="report" value="<?= e($report) ?>">
        <div class="col-auto"><label class="form-label">Grain</label><select name="period" class="form-select form-select-sm" onchange="this.form.submit()">
            <?php foreach(['day'=>'Daily','week'=>'Weekly','month'=>'Monthly'] as $k=>$v):?><option value="<?=$k?>" <?=$period===$k?'selected':''?>><?=$v?></option><?php endforeach;?></select></div>
        <div class="col-auto"><label class="form-label">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">To</label><input type="date" name="to" value="<?= e($to) ?>" class="form-control form-control-sm"></div>
        <div class="col-md-2"><label class="form-label">Client</label><select name="client_id" class="form-select form-select-sm"><option value="">All</option><?php foreach($clients as $o):?><option value="<?=(int)$o['id']?>" <?=$fClient===(int)$o['id']?'selected':''?>><?=e($o['name'])?></option><?php endforeach;?></select></div>
        <div class="col-md-2"><label class="form-label">Process</label><select name="process_id" class="form-select form-select-sm"><option value="">All</option><?php foreach($procs as $o):?><option value="<?=(int)$o['id']?>" <?=$fProcess===(int)$o['id']?'selected':''?>><?=e($o['cn'].' · '.$o['name'])?></option><?php endforeach;?></select></div>
        <div class="col-md-2"><label class="form-label">Facility</label><select name="facility_id" class="form-select form-select-sm"><option value="">All</option><?php foreach($facils as $o):?><option value="<?=(int)$o['id']?>" <?=$fFacility===(int)$o['id']?'selected':''?>><?=e($o['name'])?></option><?php endforeach;?></select></div>
        <?php if ($isSup): ?>
        <div class="col-md-2"><label class="form-label">Biller</label><select name="biller_id" class="form-select form-select-sm" onchange="this.form.submit()"><option value="">All my team</option><?php foreach($teamMembers as $o):?><option value="<?=(int)$o['id']?>" <?=$fBiller===(int)$o['id']?'selected':''?>><?=e($o['name'])?></option><?php endforeach;?></select></div>
        <div class="col-md-2"><label class="form-label">Auditor <span class="text-secondary small">(files export)</span></label><select name="auditor_id" class="form-select form-select-sm"><option value="">All auditors</option><?php foreach($auditors as $o):?><option value="<?=(int)$o['id']?>" <?=$fAuditor===(int)$o['id']?'selected':''?>><?=e($o['name'])?></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> <a href="<?= e(url('/admin/billing-reports.php')) ?>" class="btn btn-sm btn-ghost-secondary">Reset</a></div>
    </div></form>

    <!-- ===================== REPORT TABS ===================== -->
    <ul class="nav nav-tabs mb-3">
        <?php foreach (['production'=>['Production','activity'],'quality'=>['Quality','shield-check']] as $k=>[$lbl,$ic]): ?>
            <li class="nav-item"><a class="nav-link <?= $report===$k?'active':'' ?>" href="<?= e(url($selfUrl(['report'=>$k]))) ?>"><i class="ti ti-<?= e($ic) ?> me-1"></i><?= e($lbl) ?></a></li>
        <?php endforeach; ?>
    </ul>

    <?php if ($report === 'production'): ?>
    <!-- ===================== ALLOCATED vs WORKED (current backlog snapshot, role-scoped — not date-bounded) ===================== -->
    <?php $aA=(int)($AV['allocated']??0); $aW=(int)($AV['worked']??0); $aP=(int)($AV['pending']??0); $aPct=$aA>0?round(100*$aW/$aA,1):0; ?>
    <div class="card mb-3"><div class="card-header"><h3 class="card-title"><i class="ti ti-checklist me-2"></i>Allocated vs worked <span class="text-secondary fw-normal small ms-1">— current backlog of charts on <?= e($roleLabel) ?> (all time)</span></h3></div>
        <div class="card-body">
            <div class="table-responsive mb-3"><table class="table table-vcenter card-table table-sm mb-0" style="max-width:760px">
                <thead><tr><th class="text-end">Allocated</th><th class="text-end">Worked</th><th class="text-end">Pending</th><th class="text-end">% worked</th><th class="text-end">Reworked</th><th class="text-end">Billed</th><th class="text-end">Hold/Deduct</th><th class="text-end">Unbilled</th></tr></thead>
                <tbody><tr>
                    <td class="text-end fw-bold"><?= number_format($aA) ?></td>
                    <td class="text-end text-green"><?= number_format($aW) ?></td>
                    <td class="text-end text-orange"><?= number_format($aP) ?></td>
                    <td class="text-end fw-bold text-<?= $aPct>=90?'green':($aPct>=60?'orange':'red') ?>"><?= $aPct ?>%</td>
                    <td class="text-end text-azure"><?= number_format((int)($AV['reworked']??0)) ?></td>
                    <td class="text-end text-green"><?= number_format((int)($AV['billed']??0)) ?></td>
                    <td class="text-end text-orange"><?= number_format((int)($AV['hold_deductible']??0)) ?></td>
                    <td class="text-end text-red"><?= number_format((int)($AV['unbilled']??0)) ?></td>
                </tr></tbody>
            </table></div>
            <div class="row g-3">
                <div class="col-lg-6"><h4 class="small text-secondary text-uppercase">By biller</h4>
                    <div class="table-responsive" style="max-height:360px;overflow:auto"><table class="table table-vcenter card-table table-sm">
                        <thead><tr><th>Biller</th><th class="text-end">Alloc</th><th class="text-end">Worked</th><th class="text-end">Pending</th><th class="text-end">%</th><th class="text-end">Billed</th><th class="text-end">Hold</th><th class="text-end">Unbil.</th></tr></thead>
                        <tbody><?php if(!$avByBiller):?><tr><td colspan="8" class="text-center text-secondary py-3">No allocated charts.</td></tr><?php else: foreach($avByBiller as $r):?><tr><td class="small"><?= e($r['biller'] ?? '—') ?></td><?= $avCells($r) ?></tr><?php endforeach; endif;?></tbody>
                    </table></div></div>
                <div class="col-lg-6"><h4 class="small text-secondary text-uppercase">By client</h4>
                    <div class="table-responsive" style="max-height:360px;overflow:auto"><table class="table table-vcenter card-table table-sm">
                        <thead><tr><th>Client</th><th class="text-end">Alloc</th><th class="text-end">Worked</th><th class="text-end">Pending</th><th class="text-end">%</th><th class="text-end">Billed</th><th class="text-end">Hold</th><th class="text-end">Unbil.</th></tr></thead>
                        <tbody><?php if(!$avByClient):?><tr><td colspan="8" class="text-center text-secondary py-3">No allocated charts.</td></tr><?php else: foreach($avByClient as $r):?><tr><td class="small"><?= e($r['cn'] ?? '—') ?></td><?= $avCells($r) ?></tr><?php endforeach; endif;?></tbody>
                    </table></div></div>
            </div>
        </div>
    </div>

    <h3 class="mb-2"><i class="ti ti-activity me-1 text-secondary"></i>Productivity <span class="text-secondary fw-normal small">(work done in the selected date range)</span></h3>
    <div class="card mb-3"><div class="table-responsive"><table class="table table-vcenter card-table table-sm mb-0" style="max-width:760px">
        <thead><tr><th class="text-end">Charts worked</th><th class="text-end">Work actions</th><th class="text-end">Billed</th><th class="text-end">Hold/Deduct</th><th class="text-end">Unbilled</th><th class="text-end">Active billers</th></tr></thead>
        <tbody><tr>
            <td class="text-end fw-bold"><?= number_format((int)($K['charts']??0)) ?></td>
            <td class="text-end text-secondary"><?= number_format((int)$K['worked']) ?></td>
            <td class="text-end text-green"><?= number_format((int)$K['billed']) ?></td>
            <td class="text-end text-orange"><?= number_format((int)$K['hold_deductible']) ?></td>
            <td class="text-end text-red"><?= number_format((int)$K['unbilled']) ?></td>
            <td class="text-end text-azure"><?= number_format((int)$K['billers']) ?></td>
        </tr></tbody>
    </table></div>
    <div class="card-footer text-secondary small py-2"><i class="ti ti-info-circle me-1"></i><strong>Charts worked</strong> counts distinct charts; <strong>Work actions</strong> counts every save (a re-worked chart adds an action). Productivity is keyed on <em>who did the work</em> in the date range — it is not the same as the all-time <em>Allocated vs worked</em> snapshot above, which is keyed on the chart's current owner.</div>
    </div>

    <?php $bsBadge = ['billed'=>'green','hold_deductible'=>'orange','unbilled'=>'red']; ?>
    <div class="card mb-3"><div class="card-header"><h3 class="card-title"><?= e(['day'=>'Daily','week'=>'Weekly','month'=>'Monthly'][$period]) ?> production</h3>
        <div class="card-actions text-secondary small"><i class="ti ti-info-circle me-1"></i>Click a <?= e(['day'=>'date','week'=>'week','month'=>'month'][$period]) ?> to see the charts worked, and download that day’s production.</div></div>
        <div class="table-responsive"><table class="table table-vcenter card-table table-sm">
            <thead><tr><th><?= ucfirst($period) ?></th><th class="text-end">Billers</th><?= $splitHead ?></tr></thead>
            <tbody>
            <?php if (!$series): ?><tr><td colspan="7" class="text-center text-secondary py-4">No work recorded in this range.</td></tr>
            <?php else: foreach ($series as $r): $isOpen = ($drill !== '' && $r['bucket']===$drill); ?>
                <tr<?= $isOpen ? ' class="table-active"' : '' ?>>
                    <td><a href="<?= e(url($selfUrl(['drill'=> $isOpen ? null : $r['bucket']]))) ?>#dz" class="text-reset text-decoration-none"><i class="ti ti-chevron-<?= $isOpen?'down':'right' ?> me-1 text-secondary"></i><?= e($fmtBucket($r['bucket'])) ?></a></td>
                    <td class="text-end text-secondary"><?= number_format((int)$r['billers']) ?></td><?= $splitCells($r) ?>
                </tr>
                <?php if ($isOpen): ?>
                <tr class="bg-primary-lt"><td colspan="6" class="p-0"><div id="dz" class="p-2">
                    <div class="d-flex flex-wrap align-items-center gap-2 mb-2">
                        <strong><?= e($fmtBucket($r['bucket'])) ?> — <?= number_format(count($drillRows)) ?> chart(s) worked</strong>
                        <a href="<?= e(url($selfUrl(['drill'=>null]))) ?>" class="btn btn-sm btn-ghost-secondary">Collapse</a>
                        <a href="<?= e(url($selfUrl(['export'=>'production','date'=>$r['bucket']]))) ?>" class="btn btn-sm btn-outline-success ms-auto"><i class="ti ti-file-spreadsheet me-1"></i>Download Excel</a>
                    </div>
                    <div class="table-responsive" style="max-height:420px;overflow:auto"><table class="table table-sm table-vcenter mb-0" style="font-size:.8rem">
                        <thead><tr><th>Biller</th><th>Patient</th><th>MRN</th><th>Client</th><th>Process</th><th>Facility</th><th>Provider</th><th>DOS</th><th>Status</th><th>Carrier</th><th>Worked at</th></tr></thead>
                        <tbody>
                        <?php if (!$drillRows): ?><tr><td colspan="11" class="text-center text-secondary py-3">No production detail for this <?= e(['day'=>'date','week'=>'week','month'=>'month'][$period]) ?>.</td></tr>
                        <?php else: foreach ($drillRows as $d): $dbs=(string)($d['billing_status']??''); ?>
                            <tr>
                                <td class="small"><strong><?= e($d['biller'] ?: '—') ?></strong></td>
                                <td class="small"><?= e($d['patient_name']) ?></td>
                                <td class="small"><?= e($d['patient_mrn'] ?: '—') ?></td>
                                <td class="small text-secondary"><?= e($d['cn']) ?></td>
                                <td class="small text-secondary"><?= e($d['pn']) ?></td>
                                <td class="small"><?= e($d['fn']) ?></td>
                                <td class="small"><?= e($d['provider'] ?: '—') ?></td>
                                <td class="small text-nowrap"><?= e(fmt_date($d['dos'])) ?></td>
                                <td><?= $dbs!=='' ? '<span class="badge bg-'.($bsBadge[$dbs]??'secondary').'-lt">'.e(BILLING_WORK_STATUSES[$dbs]??$dbs).'</span>' : '<span class="text-secondary">—</span>' ?></td>
                                <td class="small"><?= e($d['carrier'] ?: '—') ?></td>
                                <td class="small text-nowrap text-secondary"><?= e($d['created_at'] ? fmt_dt($d['created_at']) : '—') ?></td>
                            </tr>
                        <?php endforeach; endif; ?>
                        </tbody>
                    </table></div>
                </div></td></tr>
                <?php endif; ?>
            <?php endforeach; endif; ?>
            </tbody>
        </table></div>
    </div>

    <?php
    /* Reusable grouped-production table (Charts · Work actions · Billed · Hold · Unbilled) used by every
       production breakdown below. $rows come from $splits (which carries a 'charts' column). */
    $prodTable = function (string $title, string $col1, array $rows, string $key) use ($splitHead, $splitCells) {
        ob_start(); ?>
        <div class="card"><div class="card-header"><h3 class="card-title"><?= e($title) ?></h3></div>
            <div class="table-responsive" style="max-height:480px;overflow:auto"><table class="table table-vcenter card-table table-sm">
                <thead><tr><th><?= e($col1) ?></th><?= $splitHead ?></tr></thead>
                <tbody><?php if(!$rows):?><tr><td colspan="6" class="text-center text-secondary py-3">—</td></tr><?php else: foreach($rows as $r):?><tr><td class="small"><?= e((string)($r[$key] ?? '—')) ?></td><?= $splitCells($r) ?></tr><?php endforeach; endif;?></tbody>
            </table></div>
        </div>
        <?php return ob_get_clean();
    };
    ?>
    <div class="row g-3">
        <div class="col-lg-6"><div class="card"><div class="card-header"><h3 class="card-title">By biller <span class="text-secondary fw-normal small ms-1">— who did the work (in range)</span></h3></div>
            <div class="table-responsive"><table class="table table-vcenter card-table table-sm">
                <thead><tr><th>Biller</th><?= $splitHead ?></tr></thead>
                <tbody><?php if(!$byBiller):?><tr><td colspan="6" class="text-center text-secondary py-3">—</td></tr><?php else: foreach($byBiller as $r):?><tr><td><?= e($r['biller'] ?? '—') ?></td><?= $splitCells($r) ?></tr><?php endforeach; endif;?></tbody>
            </table></div>
            <div class="card-footer text-secondary small py-2"><i class="ti ti-info-circle me-1"></i>Keyed on the biller who logged each work action in the date range — distinct from the owner-based <em>Allocated vs worked → By biller</em> snapshot above.</div>
        </div></div>
        <div class="col-lg-6"><?= $prodTable('By carrier', 'Carrier', $byCarrier, 'carrier') ?></div>
    </div>

    <div class="row g-3 mt-0">
        <div class="col-lg-4"><?= $prodTable('By client', 'Client', $byClientProd, 'grp') ?></div>
        <div class="col-lg-4"><?= $prodTable('By process', 'Process', $byProcessProd, 'grp') ?></div>
        <div class="col-lg-4"><?= $prodTable('By facility', 'Facility', $byFacilityProd, 'grp') ?></div>
    </div>
    <?php endif; /* ===== end PRODUCTION part 1 ===== */ ?>

    <?php if ($report === 'quality'): ?>
    <?php if ($isSup): ?><div class="mb-2"><a href="<?= e(url($selfUrl(['export'=>'audit_all']))) ?>" class="btn btn-sm btn-outline-success"><i class="ti ti-file-spreadsheet me-1"></i>Detailed audit files (Excel)</a></div><?php endif; ?>

    <?php
    /* DPO cells shared by the summary / by-biller / by-auditor tables:
       Audited · Pass · Error · Opp. · Defects · Accuracy% · Flagged (advisory) · Rebuttals Open/Accepted/Rejected/Agreed. */
    $qCells = function (array $r) {
        $ac = billing_audit_accuracy((int)$r['opp'],(int)$r['def']);
        return '<td class="text-end">'.number_format((int)$r['audited']).'</td>'
            .'<td class="text-end text-green">'.number_format((int)$r['pass']).'</td>'
            .'<td class="text-end text-red">'.number_format((int)$r['error']).'</td>'
            .'<td class="text-end text-secondary">'.number_format((int)$r['opp']).'</td>'
            .'<td class="text-end">'.number_format((int)$r['def']).'</td>'
            .'<td class="text-end fw-bold text-'.($ac===null?'secondary':($ac>=95?'green':($ac>=90?'orange':'red'))).'">'.($ac===null?'—':$ac.'%').'</td>'
            .'<td class="text-end text-purple">'.number_format((int)($r['flagged']??0)).'</td>'
            .'<td class="text-end text-orange">'.number_format((int)($r['reb_open']??0)).'</td>'
            .'<td class="text-end text-green">'.number_format((int)($r['reb_won']??0)).'</td>'
            .'<td class="text-end text-red">'.number_format((int)($r['reb_lost']??0)).'</td>'
            .'<td class="text-end text-secondary">'.number_format((int)($r['reb_agreed']??0)).'</td>';
    };
    $qHead = '<th class="text-end">Audited</th><th class="text-end">Pass</th><th class="text-end">Error</th><th class="text-end">Opp.</th><th class="text-end">Defects</th><th class="text-end">Accuracy</th><th class="text-end" title="Flag-only advisory items — do not affect the quality score">Flagged</th><th class="text-end" title="Rebuttal raised, awaiting biller">Reb. open</th><th class="text-end" title="Biller accepted the rebuttal (auditor was right)">Accepted</th><th class="text-end" title="Biller rejected / disputed the rebuttal">Rejected</th><th class="text-end" title="Biller agreed the audit finding">Agreed</th>';
    ?>

    <!-- Quality summary (whole range) -->
    <div class="card mt-1"><div class="card-header"><h3 class="card-title"><i class="ti ti-shield-check me-2"></i>Quality summary <span class="text-secondary fw-normal small ms-1">— charts audited in this range on <?= e($roleLabel) ?></span></h3></div>
        <div class="table-responsive"><table class="table table-vcenter card-table table-sm mb-0">
            <thead><tr><th>Scope</th><?= $qHead ?></tr></thead>
            <tbody><tr class="fw-bold"><td>All audited</td><?php if(!($QT['audited']??0)):?><td colspan="11" class="text-center text-secondary py-2">No charts audited in this range.</td><?php else: echo $qCells($QT); endif;?></tr></tbody>
        </table></div>
        <div class="card-footer text-secondary small py-2"><i class="ti ti-info-circle me-1"></i><strong>Accuracy</strong> = (opportunities − defects) ÷ opportunities across the 5 scored parameters. <strong>Flagged</strong> items are advisory only and are excluded from the score. Every error/flag becomes a <strong>rebuttal</strong> the biller can accept, reject or agree with.</div>
    </div>

    <div class="card mt-3"><div class="card-header"><h3 class="card-title"><i class="ti ti-user-check me-2"></i>Audit quality by biller (DPO)</h3>
        <div class="card-actions text-secondary small">Charts audited in this range</div></div>
        <div class="table-responsive"><table class="table table-vcenter card-table table-sm">
            <thead><tr><th>Biller</th><?= $qHead ?></tr></thead>
            <tbody>
            <?php if (!$byQuality): ?><tr><td colspan="12" class="text-center text-secondary py-3">No charts audited in this range.</td></tr>
            <?php else: foreach ($byQuality as $r): ?>
                <tr><td><?= e($r['biller'] ?? '—') ?></td><?= $qCells($r) ?></tr>
            <?php endforeach; endif; ?>
            </tbody>
        </table></div>
    </div>

    <?php if ($isSup): ?>
    <div class="card mt-3"><div class="card-header"><h3 class="card-title"><i class="ti ti-user-shield me-2"></i>By auditor</h3>
        <div class="card-actions text-secondary small">Who audited how much, in this range</div></div>
        <div class="table-responsive"><table class="table table-vcenter card-table table-sm">
            <thead><tr><th>Auditor</th><?= $qHead ?></tr></thead>
            <tbody>
            <?php if (!$byAuditor): ?><tr><td colspan="12" class="text-center text-secondary py-3">No audits in this range.</td></tr>
            <?php else: foreach ($byAuditor as $r): ?>
                <tr><td><?= e($r['auditor'] ?? '—') ?></td><?= $qCells($r) ?></tr>
            <?php endforeach; endif; ?>
            </tbody>
        </table></div>
    </div>
    <?php endif; ?>

    <div class="card mt-3"><div class="card-header"><h3 class="card-title"><i class="ti ti-list-numbers me-2"></i>Defects by audit parameter</h3>
        <div class="card-actions text-secondary small">Each of the 5 scored parameters, across audits in this range</div></div>
        <div class="table-responsive"><table class="table table-vcenter card-table table-sm">
            <thead><tr><th>Audit parameter</th><th class="text-end">Reviewed</th><th class="text-end">Pass</th><th class="text-end">Failures</th><th class="text-end">Fail rate</th><th class="text-end">Share of defects</th></tr></thead>
            <tbody>
            <?php if (!$byParam): ?><tr><td colspan="6" class="text-center text-secondary py-3">No parameter defects in this range.</td></tr>
            <?php else: $pTot = array_sum(array_map(fn($r)=>(int)$r['fails'],$byParam)); foreach ($byParam as $r):
                $tot=(int)($r['total']??0); $fails=(int)$r['fails']; $frate=$tot>0?round(100*$fails/$tot):0; ?>
                <tr><td class="small"><?= e(BILLING_AUDIT_PARAMS[$r['param_key']] ?? $r['param_key']) ?></td>
                    <td class="text-end text-secondary"><?= number_format($tot) ?></td>
                    <td class="text-end text-green"><?= number_format((int)($r['passes']??0)) ?></td>
                    <td class="text-end fw-bold text-red"><?= number_format($fails) ?></td>
                    <td class="text-end fw-bold text-<?= $frate>=20?'red':($frate>=10?'orange':'secondary') ?>"><?= $frate ?>%</td>
                    <td class="text-end text-secondary"><?= $pTot>0?round(100*$fails/$pTot):0 ?>%</td></tr>
            <?php endforeach; endif; ?>
            </tbody>
        </table></div>
    </div>
    <?php endif; /* ===== end QUALITY ===== */ ?>

    <?php if ($report === 'production'): ?>
    <div class="card mt-3"><div class="card-header"><h3 class="card-title"><i class="ti ti-receipt-2 me-2"></i>Billed codes <span class="text-secondary fw-normal small ms-1">— the CPT/ALF code finalized &amp; billed per line (work actions in the selected range)</span></h3>
        <div class="card-actions"><span class="badge bg-green-lt"><?= number_format((int)($BC['lines']??0)) ?> line(s)</span> <span class="badge bg-blue-lt ms-1"><?= number_format((int)($BC['charts']??0)) ?> chart(s)</span></div></div>
        <div class="table-responsive" style="max-height:480px;overflow:auto"><table class="table table-vcenter card-table table-sm">
            <thead><tr><th>Billed code</th><th>Type</th><th class="text-end">Billed lines</th><th class="text-end">Charts</th></tr></thead>
            <tbody>
            <?php if (!$byCpt): ?><tr><td colspan="4" class="text-center text-secondary py-4">No codes marked billed in this range.</td></tr>
            <?php else: foreach ($byCpt as $r): ?>
                <tr><td class="font-mono"><?= e((string)$r['code']) ?></td>
                    <td><span class="badge bg-<?= ($r['type']??'cpt')==='alf'?'purple':'azure' ?>-lt"><?= e(strtoupper((string)($r['type'] ?? 'cpt'))) ?></span></td>
                    <td class="text-end fw-bold text-green"><?= number_format((int)$r['lines']) ?></td>
                    <td class="text-end text-secondary"><?= number_format((int)$r['charts']) ?></td></tr>
            <?php endforeach; endif; ?>
            </tbody>
        </table></div>
    </div>
    <?php endif; /* ===== end PRODUCTION part 2 ===== */ ?>

</div></div>
<?php require __DIR__ . '/../includes/footer.php'; ?>
