<?php
/**
 * Billing audit / QA (billing.audit) — the Billing Auditor's console (DPO quality model, mirrors coding).
 *
 * When a biller saves a chart it is flagged into the audit SAMPLE at the configured rate (in_sample=1).
 * The auditor reviews each sampled chart: enters opportunities/defects (→ accuracy %), an error category
 * + comment, and a verdict (Pass/Error). On an error the auditor chooses per chart to either FLAG it
 * (advisory — the biller's tag stands) or SEND IT BACK to the biller to rework (re-queues it). The biller
 * may RAISE A REBUTTAL from My billing queue; the auditor accepts (overturns → Pass) or rejects it here.
 *
 * Views: queue (sample to audit) · audited · rebuttals. ?id=X audits one chart. Logic in includes/billing.php.
 */
require_once __DIR__ . '/../includes/config.php';
$user = require_login('internal');
$pdo  = db();
$uid  = (int) $user['id'];
$canSupervise = can('billing.supervise') || can('billing.allocate');

$view = in_array($_GET['view'] ?? 'queue', ['queue','audited','rebuttals'], true) ? ($_GET['view'] ?? 'queue') : 'queue';
$fClient = (int) ($_GET['client_id'] ?? 0); $fProcess = (int) ($_GET['process_id'] ?? 0); $fBiller = (int) ($_GET['biller_id'] ?? 0);
$fFacility = (int) ($_GET['facility_id'] ?? 0); $fAuditor = (int) ($_GET['auditor_id'] ?? 0);
$fDosFrom  = coding_parse_date($_GET['dos_from'] ?? '') ?: null;
$fDosTo    = coding_parse_date($_GET['dos_to'] ?? '') ?: null;
$id = (int) ($_GET['id'] ?? 0);

/* Cascade filter option lists over the audit-eligible inventory (worked/allocated). Process depends on the picked
 * Client, Facility on Client + Process; a stale child is reset so the filters/queries stay consistent. Done up front
 * so $ctx/$selfUrl and the shared filter closure all use the corrected values. */
$auditScope = "a.inventory_status IN ('worked','allocated')";
$clients = $pdo->query("SELECT DISTINCT c.id,c.name FROM coding_inventory ci JOIN clients c ON c.id=ci.client_id JOIN billing_allocation a ON a.inventory_id=ci.id WHERE $auditScope ORDER BY c.name")->fetchAll();
$pW=[$auditScope]; $pP=[]; if($fClient){$pW[]='ci.client_id=?';$pP[]=$fClient;}
$ps=$pdo->prepare("SELECT DISTINCT p.id,p.name,c.name cn FROM coding_inventory ci JOIN billing_allocation a ON a.inventory_id=ci.id JOIN processes p ON p.id=ci.process_id JOIN clients c ON c.id=ci.client_id WHERE ".implode(' AND ',$pW)." ORDER BY c.name,p.name"); $ps->execute($pP); $procs=$ps->fetchAll();
if($fProcess && !in_array($fProcess,array_map(fn($o)=>(int)$o['id'],$procs),true)) $fProcess=0;
$fW=[$auditScope]; $fP=[]; if($fClient){$fW[]='ci.client_id=?';$fP[]=$fClient;} if($fProcess){$fW[]='ci.process_id=?';$fP[]=$fProcess;}
$fs=$pdo->prepare("SELECT DISTINCT f.id,f.name FROM coding_inventory ci JOIN billing_allocation a ON a.inventory_id=ci.id JOIN coding_facilities f ON f.id=ci.facility_id WHERE ".implode(' AND ',$fW)." ORDER BY f.name"); $fs->execute($fP); $facils=$fs->fetchAll();
if($fFacility && !in_array($fFacility,array_map(fn($o)=>(int)$o['id'],$facils),true)) $fFacility=0;
$auditors = $pdo->query("SELECT DISTINCT au.id, au.name FROM billing_allocation a JOIN users au ON au.id=a.auditor_id WHERE a.auditor_id IS NOT NULL ORDER BY au.name")->fetchAll();
$billers = billing_allocatable_billers($pdo);

$ctx = array_filter(['view'=>$view!=='queue'?$view:null,'client_id'=>$fClient?:null,'process_id'=>$fProcess?:null,
    'facility_id'=>$fFacility?:null,'biller_id'=>$fBiller?:null,'auditor_id'=>$fAuditor?:null,'dos_from'=>$fDosFrom,'dos_to'=>$fDosTo]);
$selfUrl = fn(array $o=[]) => '/admin/billing-audit.php' . (($q=array_filter(array_merge($ctx,$o), fn($v)=>$v!==null&&$v!==''&&$v!==0))?'?'.http_build_query($q):'');

/* Shared filter fragment — appended to BOTH the KPI and the list/export WHERE builders so chips + grid + export
 * never diverge. All positional ? (native prepares are on). */
$applyAuditFilters = function (array &$w, array &$p) use ($fClient,$fProcess,$fFacility,$fBiller,$fAuditor,$fDosFrom,$fDosTo) {
    if ($fClient)   { $w[]='ci.client_id=?';       $p[]=$fClient; }
    if ($fProcess)  { $w[]='ci.process_id=?';      $p[]=$fProcess; }
    if ($fFacility) { $w[]='ci.facility_id=?';     $p[]=$fFacility; }
    if ($fBiller)   { $w[]='a.allocated_biller=?'; $p[]=$fBiller; }
    if ($fAuditor)  { $w[]='a.auditor_id=?';       $p[]=$fAuditor; }
    if ($fDosFrom)  { $w[]='ci.dos>=?';            $p[]=$fDosFrom; }
    if ($fDosTo)    { $w[]='ci.dos<=?';            $p[]=$fDosTo; }
};

/* ============================================================================ POST (PRG) */
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    csrf_check_or_die();
    $act = (string) ($_POST['action'] ?? '');

    if ($act === 'set_sample') {
        if (!$canSupervise) { flash('error', 'Only a supervisor can change the sample rate.'); redirect($selfUrl()); }
        billing_set_audit_sample_pct($pdo, (int) input('sample_pct'), $uid);
        flash('success', 'Audit sample rate updated.');
        redirect($selfUrl());
    }

    if ($act === 'audit') {
        $aid = (int) ($_POST['allocation_id'] ?? 0);
        $row = $pdo->prepare("SELECT a.*, ci.id inv FROM billing_allocation a JOIN coding_inventory ci ON ci.id=a.inventory_id WHERE a.id=?");
        $row->execute([$aid]); $row = $row->fetch();
        if (!$row || $row['inventory_status'] === 'rfi_to_coding') { flash('error', 'Chart not available to audit.'); redirect($selfUrl()); }
        if (($row['rebuttal_status'] ?? 'none') === 'raised') { flash('error', 'Resolve the open rebuttal before re-auditing this chart.'); redirect($selfUrl(['view'=>'rebuttals'])); }

        // Score the 5 BILLING_AUDIT_PARAMS (pass/fail + note). A Fail requires a note. opp=5, def=count of fails.
        $pIn = (array) ($_POST['p'] ?? []); $nIn = (array) ($_POST['note'] ?? []);
        $params = []; $missingReason = false; $def = 0;
        foreach (BILLING_AUDIT_PARAMS as $k => $_) {
            $pr = (($pIn[$k] ?? 'pass') === 'fail') ? 'fail' : 'pass';
            $note = trim((string) ($nIn[$k] ?? ''));
            if ($pr === 'fail') { $def++; if ($note === '') $missingReason = true; }
            $params[$k] = ['result' => $pr, 'note' => $note];
        }
        if ($missingReason) { flash('error', 'Add a note explaining every failed parameter.'); redirect($selfUrl(['id'=>$row['inventory_id']])); }
        $comment = trim((string) input('comment'));
        $flagged = !empty($_POST['flag']);   // the 6th, advisory item — routes to the biller but never counts toward DPO

        $saved = billing_save_audit($pdo, $aid, $uid, $params, $comment, $flagged);
        if (!$saved) { flash('error', 'Could not save — an open rebuttal blocks re-auditing this chart.'); redirect($selfUrl(['view'=>'rebuttals'])); }
        // Advisory model only (no send-back): a defect OR the flag routes the chart to the biller's rebuttals queue.
        $result = ($def > 0 || $flagged) ? 'error' : 'pass';
        billing_log_event($pdo, $aid, (int) $row['inventory_id'], 'audit', $uid,
            ['billing_status'=>$result, 'comment'=> "DPO $def/5" . ($flagged ? ' · flagged' : '')]);
        audit_log('billing.audit', 'billing_allocation', $aid, null, ['result'=>$result,'def'=>$def,'flagged'=>$flagged]);
        $acc = billing_audit_accuracy(5, $def);
        flash('success', "Audited — $result" . ($acc!==null ? " · {$acc}% ($def/5 defect".($def===1?'':'s').")" : '') . ($flagged ? ' · flagged for the biller.' : ''));
        redirect($selfUrl());
    }

    if ($act === 'rebuttal_resolve') {
        // Per-parameter resolve: for each disputed param the auditor Accepts (→ flip to pass) or Keeps the fail.
        $aid = (int) ($_POST['allocation_id'] ?? 0);
        $note = trim((string) input('note'));
        $row = $pdo->prepare("SELECT * FROM billing_allocation WHERE id=?"); $row->execute([$aid]); $row = $row->fetch();
        if ($row && $row['rebuttal_status'] === 'raised') {
            $rb  = (array) ($_POST['rb'] ?? []);   // param_key => accept|keep
            $pdo->beginTransaction();
            $acc = $pdo->prepare("UPDATE billing_audit_param SET result='pass', rebuttal_result='accepted' WHERE allocation_id=? AND param_key=? AND disputed=1");
            $rej = $pdo->prepare("UPDATE billing_audit_param SET rebuttal_result='rejected' WHERE allocation_id=? AND param_key=? AND disputed=1");
            $nAcc = 0;
            foreach (BILLING_AUDIT_PARAMS as $k => $_) {
                if (!isset($rb[$k])) continue;
                if ($rb[$k] === 'accept') { $acc->execute([$aid, (string) $k]); $nAcc += $acc->rowCount(); }
                else                      { $rej->execute([$aid, (string) $k]); }
            }
            // any disputed param the auditor didn't decide → reject (the fail stands)
            $pdo->prepare("UPDATE billing_audit_param SET rebuttal_result='rejected' WHERE allocation_id=? AND disputed=1 AND rebuttal_result='pending'")->execute([$aid]);
            billing_recompute_audit($pdo, $aid);   // re-derive opp/def/result from the (now overturned) params
            $decision = $nAcc > 0 ? 'accepted' : 'rejected';
            $pdo->prepare("UPDATE billing_allocation SET rebuttal_status=?, rebuttal_resolved_at=NOW(), audit_comment=CONCAT(COALESCE(audit_comment,''),?) WHERE id=?")
                ->execute([$decision, "\n[rebuttal $decision] " . $note, $aid]);
            $pdo->commit();
            billing_log_event($pdo, $aid, (int) $row['inventory_id'], 'rebuttal_resolve', $uid, ['comment'=>$decision.' '.$note]);
            audit_log('billing.rebuttal_resolve', 'billing_allocation', $aid, null, ['decision'=>$decision, 'accepted'=>$nAcc]);
            flash('success', "Rebuttal resolved — $nAcc parameter(s) accepted.");
        }
        redirect($selfUrl(['view'=>'rebuttals']));
    }
    redirect($selfUrl());
}

/* ---- Excel export of the active view, honouring the filters (req 4). Before header — download() flushes+exits.
 *  Access = the page's own billing.audit route gate (already enforced by require_login); shows exactly what the
 *  auditor sees on screen, at a higher row cap. ---- */
if (($_GET['export'] ?? '') === 'xlsx') {
    require_once __DIR__ . '/../includes/xlsx.php';
    $ew = []; $ep = []; $applyAuditFilters($ew, $ep);
    if ($view==='queue')        $ew[] = "a.in_sample=1 AND a.audit_result IS NULL AND a.inventory_status='worked'";
    elseif ($view==='audited')  $ew[] = "a.audit_result IS NOT NULL";
    else                        $ew[] = "a.rebuttal_status='raised'";
    $est = $pdo->prepare("SELECT a.*, ci.patient_name, ci.patient_mrn, ci.dos, c.name cn, p.name pn, f.name fn,
            COALESCE(bp.name,cp.name,pr.name) provider, u.name biller, au.name auditor
        FROM billing_allocation a JOIN coding_inventory ci ON ci.id=a.inventory_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
        LEFT JOIN users u ON u.id=a.allocated_biller LEFT JOIN users au ON au.id=a.auditor_id
        WHERE " . implode(' AND ', $ew) . " ORDER BY a.worked_at DESC, a.id DESC LIMIT 20000");
    $est->execute($ep); $erows = $est->fetchAll();
    $exLines = $erows ? coding_effective_lines_bulk($pdo, array_values(array_unique(array_map(fn($r)=>(int)$r['inventory_id'],$erows)))) : [];
    $cptStr = function (int $inv) use ($pdo, $exLines) {
        $ls = $exLines[$inv] ?? [];
        return implode(' | ', array_map(fn($l) => coding_alf_label($pdo, $l['cpt']) . (($u=(int)($l['units']??1))>1 ? " x$u" : ''), $ls));
    };
    $out = [];
    foreach ($erows as $r) {
        $ac = billing_audit_accuracy((int)$r['audit_opportunities'], (int)$r['audit_defects']);
        $out[] = [
            $r['cn'], $r['pn'], $r['fn'], $r['provider'], $r['patient_name'], (string)($r['patient_mrn']??''), fmt_date($r['dos']),
            $r['biller'] ?: '', $cptStr((int)$r['inventory_id']),
            BILLING_WORK_STATUSES[$r['billing_status']] ?? ($r['billing_status'] ?? ''), (string)($r['carrier']??''),
            (int)$r['in_sample'] ? 'Yes' : 'No',
            $r['audit_result'] ? ucfirst($r['audit_result']) : '', (int)$r['audit_opportunities'], (int)$r['audit_defects'],
            $ac===null ? '' : $ac, (string)($r['audit_error_category']??''), $r['auditor'] ?: '',
            $r['audited_at'] ? date('Y-m-d H:i', strtotime($r['audited_at'])) : '',
            (string)($r['rebuttal_status']??''), (string)($r['audit_comment']??''),
        ];
    }
    $x = new SimpleXlsx();
    $x->addSheet('Billing audit', ['Client','Process','Facility','Provider','Patient','MRN','DOS','Biller','CPT/ALF','Billing tag','Carrier','In sample','Audit result','Opportunities','Defects','Accuracy %','Error category','Auditor','Audited at','Rebuttal','Comment'], $out);
    audit_log('billing.audit.export', 'scope', null, null, ['view'=>$view,'rows'=>count($out),'client'=>$fClient,'process'=>$fProcess,'facility'=>$fFacility,'biller'=>$fBiller,'auditor'=>$fAuditor]);
    $x->download('billing-audit-' . $view . '.xlsx');
    exit;
}

/* ============================================================================ GET */
$samplePct = billing_audit_sample_pct($pdo);

/* KPI chips over worked charts (scoped). */
$kw = ["a.inventory_status IN ('worked','allocated')"]; $kp = [];
$applyAuditFilters($kw, $kp);
$kst = $pdo->prepare("SELECT
        SUM(a.in_sample=1 AND a.audit_result IS NULL AND a.inventory_status='worked') to_audit,
        SUM(a.audit_result IS NOT NULL) audited,
        SUM(a.audit_result='pass') pass, SUM(a.audit_result='error') error,
        SUM(a.rebuttal_status='raised') rebuttals,
        COALESCE(SUM(a.audit_opportunities),0) opp, COALESCE(SUM(a.audit_defects),0) def
    FROM billing_allocation a JOIN coding_inventory ci ON ci.id=a.inventory_id WHERE " . implode(' AND ', $kw));
$kst->execute($kp); $K = $kst->fetch() ?: [];
$acc = billing_audit_accuracy((int)($K['opp']??0), (int)($K['def']??0));

/* The chart being audited (?id). */
$chart = null;
if ($id) {
    $st = $pdo->prepare("SELECT a.*, ci.patient_name, ci.patient_mrn, ci.patient_dob, ci.dos, ci.scribe_flag,
            c.name cn, p.name pn, f.name fn, pr.name prn, cp.name coded_prov, bp.name bill_prov, rp.name rend_prov, u.name biller
        FROM billing_allocation a JOIN coding_inventory ci ON ci.id=a.inventory_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 pr ON pr.id=ci.provider_id
        LEFT JOIN coding_providers cp ON cp.id=ci.coded_provider_id
        LEFT JOIN coding_providers bp ON bp.id=ci.billing_provider_id
        LEFT JOIN coding_providers rp ON rp.id=ci.rendering_provider_id
        LEFT JOIN users u ON u.id=a.allocated_biller
        WHERE a.inventory_id=? AND a.inventory_status IN ('worked','allocated')");
    $st->execute([$id]); $chart = $st->fetch() ?: null;
}

/* List rows for the active view. */
$lw = []; $lp = [];
$applyAuditFilters($lw, $lp);
if ($view==='queue')        $lw[] = "a.in_sample=1 AND a.audit_result IS NULL AND a.inventory_status='worked'";
elseif ($view==='audited')  $lw[] = "a.audit_result IS NOT NULL";
else                        $lw[] = "a.rebuttal_status='raised'";
$rows = $pdo->prepare("SELECT a.*, ci.patient_name, ci.dos, c.name cn, f.name fn, u.name biller, au.name auditor
    FROM billing_allocation a JOIN coding_inventory ci ON ci.id=a.inventory_id
    LEFT JOIN clients c ON c.id=ci.client_id LEFT JOIN coding_facilities f ON f.id=ci.facility_id
    LEFT JOIN users u ON u.id=a.allocated_biller LEFT JOIN users au ON au.id=a.auditor_id
    WHERE " . implode(' AND ', $lw) . " ORDER BY a.worked_at DESC, a.id DESC LIMIT 1000");
$rows->execute($lp); $rows = $rows->fetchAll();
/* $clients/$procs/$facils/$auditors/$billers built up top (cascade). */

// Rebuttals view: bulk-load each chart's DISPUTED params so the auditor can Accept/Keep per parameter.
$disputedByAlloc = [];
if ($view === 'rebuttals' && $rows) {
    $aids = array_map(fn($r) => (int) $r['id'], $rows);
    $in = implode(',', array_fill(0, count($aids), '?'));
    $dq = $pdo->prepare("SELECT allocation_id, param_key, dispute_reason FROM billing_audit_param WHERE disputed=1 AND allocation_id IN ($in)");
    $dq->execute($aids);
    foreach ($dq as $d) $disputedByAlloc[(int) $d['allocation_id']][$d['param_key']] = $d['dispute_reason'];
}

// Coded lines for context (audited chart + visible rows).
$cptIds = array_column($rows, 'inventory_id'); if ($chart) $cptIds[] = (int) $chart['inventory_id'];
$linesByChart = $cptIds ? coding_effective_lines_bulk($pdo, array_values(array_unique(array_map('intval',$cptIds)))) : [];
$lineCell = function (int $invId, string $field) use ($pdo, $linesByChart) {
    $lines = $linesByChart[$invId] ?? []; if (!$lines) return '<span class="text-secondary">—</span>';
    $out=[]; foreach ($lines as $ln) {
        if ($field==='cpt') $out[]='<strong>'.e(coding_alf_label($pdo,$ln['cpt'])).'</strong>';
        elseif ($field==='units') $out[]=(int)($ln['units']??1);
        elseif ($field==='mods') $out[]=e(implode(', ',$ln['mods']??[]))?:'—';
        elseif ($field==='icds') $out[]=e(implode(', ',$ln['icds']??[]))?:'—';
    } return implode('<div class="border-top my-1" style="opacity:.4"></div>',$out);
};
$bsBadge = ['billed'=>'green','hold_deductible'=>'orange','unbilled'=>'red'];
$pageTitle = 'Billing audit';
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-shield-check me-2 text-primary"></i>Billing audit</h2>
        <div class="text-secondary small">QA the <strong>sampled</strong> worked charts — score the <strong>5 audit parameters</strong> Pass/Fail (a Fail needs a note). Any Fail ⇒ Error; then Flag it or Send it back to the biller. Billers can dispute individual parameters; resolve disputes under <strong>Rebuttals</strong>.</div>
    </div>
    <div class="col-auto">
        <form method="POST" action="<?= e(url($selfUrl())) ?>" class="d-flex align-items-end gap-1">
            <?= csrf_field() ?><input type="hidden" name="action" value="set_sample">
            <div><label class="form-label small mb-0">Overall sample rate %</label>
                <input type="number" name="sample_pct" min="0" max="100" value="<?= (int)$samplePct ?>" class="form-control form-control-sm" style="width:90px" <?= $canSupervise?'':'disabled' ?>></div>
            <?php if ($canSupervise): ?><button class="btn btn-sm btn-outline-secondary">Save</button><?php endif; ?>
        </form>
        <?php if ($canSupervise): ?><div class="text-secondary small mt-1 text-end"><a href="<?= e(url('/admin/billing-sampling.php')) ?>"><i class="ti ti-percentage me-1"></i>Set a per-biller sample %</a> (overrides this rate)</div><?php endif; ?>
    </div>
</div></div></div>

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

    <div class="row row-cards mb-3">
        <?php foreach ([['To audit',$K['to_audit']??0,'target-arrow','azure'],['Audited',$K['audited']??0,'checks','primary'],['Pass',$K['pass']??0,'circle-check','green'],['Error',$K['error']??0,'alert-triangle','red'],['Accuracy',$acc===null?'—':$acc.'%','percentage', $acc===null?'secondary':($acc>=95?'green':($acc>=90?'orange':'red'))],['Rebuttals',$K['rebuttals']??0,'message-2','purple']] as [$lbl,$val,$icon,$col]): ?>
        <div class="col"><div class="card card-sm"><div class="card-body py-2 text-center"><div class="stat-label"><i class="ti ti-<?= $icon ?> me-1"></i><?= e($lbl) ?></div><div class="h3 mb-0 text-<?= $col ?>"><?= is_numeric($val)?number_format((int)$val):e($val) ?></div></div></div></div>
        <?php endforeach; ?>
    </div>

    <form method="GET" class="card mb-3"><div class="card-body row g-2 align-items-end">
        <input type="hidden" name="view" value="<?= e($view) ?>">
        <div class="col-md-2"><label class="form-label">Client</label><select name="client_id" class="form-select form-select-sm" onchange="this.form.submit()"><option value="">All clients</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" onchange="this.form.submit()"><option value="">All processes</option><?php foreach($procs as $o):?><option value="<?=(int)$o['id']?>" <?=$fProcess===(int)$o['id']?'selected':''?>><?=e($fClient ? $o['name'] : $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" onchange="this.form.submit()"><option value="">All facilities</option><?php foreach($facils as $o):?><option value="<?=(int)$o['id']?>" <?=$fFacility===(int)$o['id']?'selected':''?>><?=e($o['name'])?></option><?php endforeach;?></select></div>
        <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 billers</option><?php foreach($billers as $b):?><option value="<?=(int)$b['id']?>" <?=$fBiller===(int)$b['id']?'selected':''?>><?=e($b['name'])?></option><?php endforeach;?></select></div>
        <div class="col-md-2"><label class="form-label">Auditor</label><select name="auditor_id" class="form-select form-select-sm" onchange="this.form.submit()"><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>
        <div class="col-md-2"><label class="form-label">DOS from</label><input type="date" name="dos_from" value="<?= e($fDosFrom) ?>" class="form-control form-control-sm"></div>
        <div class="col-md-2"><label class="form-label">DOS to</label><input type="date" name="dos_to" value="<?= e($fDosTo) ?>" class="form-control form-control-sm"></div>
        <div class="col-auto d-flex gap-2">
            <button class="btn btn-sm btn-primary"><i class="ti ti-filter me-1"></i>Apply</button>
            <a href="<?= e(url($selfUrl(['export'=>'xlsx']))) ?>" class="btn btn-sm btn-outline-success"><i class="ti ti-file-spreadsheet me-1"></i>Export Excel</a>
            <a href="<?= e(url('/admin/billing-audit.php')) ?>" class="btn btn-sm btn-ghost-secondary">Clear</a>
        </div>
    </div></form>

    <?php if ($chart): $aId=(int)$chart['id']; $bs=(string)($chart['billing_status']??''); ?>
    <!-- ===================================================== AUDIT FORM -->
    <div class="card mb-3 border-primary">
        <div class="card-header bg-primary-lt"><h3 class="card-title"><i class="ti ti-clipboard-check me-2"></i>Audit chart</h3>
            <div class="card-actions"><a href="<?= e(url($selfUrl(['id'=>null]))) ?>" class="btn btn-sm btn-ghost-secondary">Close</a></div></div>
        <div class="card-body">
            <div class="row g-3 mb-2">
                <div class="col-md-3"><div class="text-secondary small">Patient</div><strong><?= e($chart['patient_name']) ?></strong><div class="small text-secondary"><?= e($chart['patient_mrn']??'') ?></div><div class="small text-secondary">DOB <?= e(fmt_date($chart['patient_dob'] ?? null)) ?></div></div>
                <div class="col-md-3"><div class="text-secondary small">Client · Process · Facility</div><?= e($chart['cn']) ?><div class="small text-secondary"><?= e(trim(($chart['pn']??'') . ' · ' . ($chart['fn']??''), ' ·')) ?></div></div>
                <?php $mainProv = $chart['bill_prov'] ?: $chart['coded_prov'] ?: $chart['prn'] ?: '—'; ?>
                <div class="col-md-3"><div class="text-secondary small">Provider <span class="text-secondary">(billing)</span></div><strong><?= e($mainProv) ?></strong>
                    <?php $prBits=[]; if(!empty($chart['coded_prov']) && $chart['coded_prov']!==$mainProv) $prBits[]='Coded: '.$chart['coded_prov']; if(!empty($chart['scribe_flag']) && !empty($chart['rend_prov']) && $chart['rend_prov']!==$mainProv) $prBits[]='Scribe: '.$chart['rend_prov']; ?>
                    <?php if($prBits): ?><div class="small text-secondary"><?= e(implode(' · ', $prBits)) ?></div><?php endif; ?></div>
                <div class="col-md-3"><div class="text-secondary small">Biller · DOS</div><?= e($chart['biller']??'—') ?><div class="small text-secondary"><?= e(fmt_date($chart['dos'])) ?></div></div>
                <div class="col-md-3"><div class="text-secondary small">Biller's tag</div>
                    <?= $bs!==''?'<span class="badge bg-'.($bsBadge[$bs]??'secondary').'-lt">'.e(BILLING_WORK_STATUSES[$bs]??$bs).'</span>':'—' ?>
                    <div class="small"><?= e($chart['carrier']?:'') ?><?= $chart['secondary_reason']?' · '.e($chart['secondary_reason']):'' ?></div></div>
            </div>
            <div class="mb-3"><div class="text-secondary small mb-1">Coded lines (context)</div>
                <table class="table table-sm table-bordered mb-0" style="max-width:720px"><thead><tr><th>CPT/ALF</th><th class="text-center">Units</th><th>Modifier(s)</th><th>ICD(s)</th></tr></thead>
                <tbody><tr><td><?= $lineCell((int)$chart['inventory_id'],'cpt') ?></td><td class="text-center"><?= $lineCell((int)$chart['inventory_id'],'units') ?></td><td class="small"><?= $lineCell((int)$chart['inventory_id'],'mods') ?></td><td class="small"><?= $lineCell((int)$chart['inventory_id'],'icds') ?></td></tr></tbody></table>
            </div>
            <?php /* existing param scores for pre-fill on re-audit */
            $chartParams = []; $pq = $pdo->prepare("SELECT param_key,result,note FROM billing_audit_param WHERE allocation_id=?"); $pq->execute([$aId]);
            foreach ($pq as $pr) $chartParams[$pr['param_key']] = $pr;
            $isAudited = $chart['audit_result'] !== null; ?>
            <form method="POST" action="<?= e(url($selfUrl())) ?>">
                <?= csrf_field() ?><input type="hidden" name="action" value="audit"><input type="hidden" name="allocation_id" value="<?= $aId ?>">
                <div class="text-secondary small mb-1">Score each parameter <strong>Pass</strong> or <strong>Fail</strong> — a Fail needs a note. Defects = failed parameters (out of 5); accuracy = (5 − defects) / 5.</div>
                <div class="table-responsive"><table class="table table-sm table-vcenter mb-2" style="max-width:920px">
                    <thead><tr><th style="width:42%">Audit parameter</th><th class="w-1 text-nowrap">Result</th><th>Note <span class="text-secondary">(required on Fail)</span></th></tr></thead>
                    <tbody>
                    <?php foreach (BILLING_AUDIT_PARAMS as $k => $label): $cur = $chartParams[$k] ?? null; $isFail = ($cur && $cur['result'] === 'fail'); ?>
                        <tr>
                            <td class="small"><?= e($label) ?></td>
                            <td><div class="btn-group btn-group-sm" role="group">
                                <input type="radio" class="btn-check pv" name="p[<?= e($k) ?>]" id="p_<?= e($k) ?>_pass" value="pass" data-k="<?= e($k) ?>" <?= $isFail?'':'checked' ?>><label class="btn btn-outline-success" for="p_<?= e($k) ?>_pass">Pass</label>
                                <input type="radio" class="btn-check pv" name="p[<?= e($k) ?>]" id="p_<?= e($k) ?>_fail" value="fail" data-k="<?= e($k) ?>" <?= $isFail?'checked':'' ?>><label class="btn btn-outline-danger" for="p_<?= e($k) ?>_fail">Fail</label>
                            </div></td>
                            <td><input type="text" class="form-control form-control-sm note-<?= e($k) ?>" name="note[<?= e($k) ?>]" maxlength="255" value="<?= e($cur['note']??'') ?>" placeholder="reason…"></td>
                        </tr>
                    <?php endforeach; ?>
                        <?php /* 6th item — the advisory Flag. NOT a scored parameter: never counts toward defects / quality. */ ?>
                        <tr style="background:var(--tblr-bg-surface-secondary,#f8fafc)">
                            <td class="small"><strong>Flag only</strong> <span class="badge bg-orange-lt ms-1">advisory</span>
                                <span class="d-block text-secondary" style="font-size:.72rem">Sends the chart to the biller for their attention — does <u>not</u> affect the quality score.</span></td>
                            <td><label class="form-check form-switch mb-0"><input type="checkbox" class="form-check-input" name="flag" value="1" <?= !empty($chart['audit_flagged'])?'checked':'' ?>> <span class="form-check-label small">Flag</span></label></td>
                            <td class="text-secondary small">Optional</td>
                        </tr>
                    </tbody>
                </table></div>
                <div class="row g-3">
                    <div class="col-12"><label class="form-label">Comment</label><textarea name="comment" rows="2" class="form-control" placeholder="Overall note…"><?= e($chart['audit_comment']??'') ?></textarea></div>
                    <div class="col-12"><button class="btn btn-primary"><i class="ti ti-device-floppy me-1"></i><?= $isAudited?'Re-save audit':'Save audit' ?></button>
                        <span class="text-secondary small ms-2">Any Fail (or a Flag) routes the chart to the biller's <strong>My rebuttals</strong>, where they accept, dispute, or agree. Only the 5 parameters count toward quality.</span></div>
                </div>
            </form>
        </div>
    </div>
    <script>
    (function(){
        // A Fail requires a note (client-side hint; server re-checks).
        function refresh(){
            document.querySelectorAll('.pv:checked').forEach(function(r){
                var note=document.querySelector('.note-'+r.dataset.k);
                if(note) note.required = (r.value==='fail');
            });
        }
        document.querySelectorAll('.pv').forEach(function(r){ r.addEventListener('change',refresh); });
        refresh();
    })();
    </script>
    <?php endif; ?>

    <!-- ===================================================== TABS + LIST -->
    <ul class="nav nav-tabs mb-0">
        <?php foreach (['queue'=>'To audit (sample)','audited'=>'Audited','rebuttals'=>'Rebuttals'] as $k=>$lbl): ?>
            <li class="nav-item"><a class="nav-link <?= $view===$k?'active':'' ?>" href="<?= e(url($selfUrl(['view'=>$k,'id'=>null]))) ?>"><?= e($lbl) ?><?php if($k==='rebuttals' && (int)($K['rebuttals']??0)>0):?> <span class="badge bg-purple ms-1"><?= (int)$K['rebuttals'] ?></span><?php endif;?></a></li>
        <?php endforeach; ?>
    </ul>
    <div class="card">
        <div class="table-responsive"><table class="table table-vcenter card-table">
            <thead><tr><th>Patient</th><th>Client</th><th>Biller</th><th>CPT/ALF</th><th>Tag</th>
                <?php if($view==='queue'):?><th>Worked</th><th class="w-1"></th>
                <?php elseif($view==='audited'):?><th>Result</th><th>Accuracy</th><th>Category</th><th>Auditor</th><th class="w-1"></th>
                <?php else:?><th>Result</th><th>Rebuttal</th><th class="w-1"></th><?php endif;?>
            </tr></thead>
            <tbody>
            <?php if (!$rows): ?><tr><td colspan="9" class="text-center text-secondary py-4">Nothing here. 🎉</td></tr>
            <?php else: foreach ($rows as $r): $iid=(int)$r['inventory_id']; $bs=(string)($r['billing_status']??''); $ar=(string)($r['audit_result']??''); $ac=billing_audit_accuracy((int)$r['audit_opportunities'],(int)$r['audit_defects']); ?>
                <tr<?= $id===$iid?' class="table-active"':'' ?>>
                    <td class="small"><strong><?= e($r['patient_name']) ?></strong></td>
                    <td class="small text-secondary"><?= e($r['cn']) ?></td>
                    <td class="small"><?= e($r['biller']??'—') ?></td>
                    <td class="small"><?= $lineCell($iid,'cpt') ?></td>
                    <td><?= $bs!==''?'<span class="badge bg-'.($bsBadge[$bs]??'secondary').'-lt">'.e(BILLING_WORK_STATUSES[$bs]??$bs).'</span>':'—' ?></td>
                    <?php if($view==='queue'): ?>
                        <td class="small text-nowrap text-secondary"><?= e(fmt_date($r['last_worked_date'])) ?></td>
                        <td class="text-end"><a href="<?= e(url($selfUrl(['id'=>$iid]))) ?>" class="btn btn-sm btn-primary"><i class="ti ti-clipboard-check me-1"></i>Audit</a></td>
                    <?php elseif($view==='audited'): ?>
                        <td><span class="badge bg-<?= $ar==='pass'?'green':'red' ?>-lt"><?= e(ucfirst($ar)) ?></span></td>
                        <td class="small"><?= $ac===null?'—':$ac.'% <span class="text-secondary">('.(int)$r['audit_defects'].'/'.(int)$r['audit_opportunities'].')</span>' ?></td>
                        <td class="small text-secondary"><?= e($r['audit_error_category']?:'') ?><?php if((string)$r['rebuttal_status']!=='none'):?> <span class="badge bg-purple-lt"><?= e($r['rebuttal_status']) ?></span><?php endif;?></td>
                        <td class="small"><?= e($r['auditor'] ?? '—') ?></td>
                        <td class="text-end"><a href="<?= e(url($selfUrl(['id'=>$iid]))) ?>" class="btn btn-sm btn-outline-secondary"><i class="ti ti-pencil me-1"></i>Re-audit</a></td>
                    <?php else: $dps = $disputedByAlloc[(int)$r['id']] ?? []; ?>
                        <td><span class="badge bg-red-lt">Error</span></td>
                        <td class="small"><div class="text-secondary">Biller says:</div><?= e($r['rebuttal_comment']?:'—') ?>
                            <?php if ($dps): ?><div class="mt-1"><?php foreach ($dps as $pk=>$reason): ?>
                                <div class="small"><span class="badge bg-orange-lt"><?= e(BILLING_AUDIT_PARAMS[$pk] ?? $pk) ?></span> <span class="text-secondary"><?= e($reason ?: '') ?></span></div>
                            <?php endforeach; ?></div><?php endif; ?>
                        </td>
                        <td class="text-end">
                            <form method="POST" action="<?= e(url($selfUrl())) ?>">
                                <?= csrf_field() ?><input type="hidden" name="action" value="rebuttal_resolve"><input type="hidden" name="allocation_id" value="<?= (int)$r['id'] ?>">
                                <?php foreach ($dps as $pk=>$reason): $rid=(int)$r['id']; ?>
                                    <div class="d-flex align-items-center gap-1 mb-1 justify-content-end">
                                        <span class="small text-secondary text-truncate" style="max-width:150px" title="<?= e(BILLING_AUDIT_PARAMS[$pk]??$pk) ?>"><?= e(BILLING_AUDIT_PARAMS[$pk]??$pk) ?></span>
                                        <div class="btn-group btn-group-sm" role="group">
                                            <input type="radio" class="btn-check" name="rb[<?= e($pk) ?>]" id="rb<?= $rid ?>_<?= e($pk) ?>_k" value="keep" checked><label class="btn btn-outline-danger" for="rb<?= $rid ?>_<?= e($pk) ?>_k">Keep fail</label>
                                            <input type="radio" class="btn-check" name="rb[<?= e($pk) ?>]" id="rb<?= $rid ?>_<?= e($pk) ?>_a" value="accept"><label class="btn btn-outline-success" for="rb<?= $rid ?>_<?= e($pk) ?>_a">Accept</label>
                                        </div>
                                    </div>
                                <?php endforeach; ?>
                                <div class="d-flex gap-1 justify-content-end align-items-center">
                                    <input name="note" class="form-control form-control-sm" placeholder="note" style="width:120px">
                                    <button class="btn btn-sm btn-primary" title="Apply the per-parameter decisions"><i class="ti ti-check me-1"></i>Resolve</button>
                                </div>
                            </form>
                        </td>
                    <?php endif; ?>
                </tr>
            <?php endforeach; endif; ?>
            </tbody>
        </table></div>
        <?php if (count($rows) >= 1000): ?><div class="card-footer text-secondary small">Showing first 1000 — narrow with filters.</div><?php endif; ?>
    </div>
</div></div>
<?php require __DIR__ . '/../includes/footer.php'; ?>
