<?php
/**
 * AR / Collections work queue (ar.work) — the AR worker USER's console (Billing is a SEPARATE department).
 *
 * A user works ONLY the claims allocated to THEM (ar_allocation.allocated_user = me). All allocation /
 * reshuffle logic lives in the SUPERVISOR's console (admin/ar-allocation.php); this page is the worker
 * view: pick a claim from your queue, work it (notes / claim status / action taken / next follow-up)
 * and record the outcome. Every save is mirrored into ar_allocation_event for the work history.
 *
 * Filters cascade in this exact order (all GET, each select auto-submits):
 *     Vertical » Process » Allocation type » Priority
 * — and are scoped to the signed-in user's own allocations the whole way down. The route gate
 * (ar-queue.php => ['ar.work']) and the nav entry are handled elsewhere.
 *
 * Business helpers come from includes/ar.php: ar_dropdowns(), ar_followup_within_cap(),
 * ar_process_report_ids(), AR_PRIORITIES / AR_ALLOC_TYPES / AR_MAX_FOLLOWUP_DAYS.
 */
require_once __DIR__ . '/../includes/config.php';
$user = require_login('internal');
$pdo  = db();
$uid  = (int) $user['id'];

/* ---- Current GET filter state (also re-applied on the PRG redirect after a POST) ---- */
$fVertical = (int) ($_GET['vertical_id'] ?? 0);
$fProcess  = (int) ($_GET['process_id'] ?? 0);
$fPriority = isset(AR_PRIORITIES[$_GET['priority'] ?? '']) ? (string) $_GET['priority'] : '';

/** Page URL preserving the current filter context (for the PRG redirect + clear link). */
$ctx = array_filter([
    'vertical_id' => $fVertical ?: null,
    'process_id'  => $fProcess ?: null,
    'priority'    => $fPriority !== '' ? $fPriority : null,
]);
$selfUrl = fn(array $over = []) => '/admin/ar-queue.php'
    . (($q = array_filter(array_merge($ctx, $over), fn($v) => $v !== null && $v !== '')) ? ('?' . http_build_query($q)) : '');

/* Working a claim now happens PER-VISIT on admin/ar-work.php (GetNext + per-visit tagging). This page is the
 * read-only queue/overview; the "Work" action links into ar-work.php for the chosen account. */

/* ============================================================================ GET — load page data */

/* KPI chips: VISIT counts across ALL of this user's allocations (the unit of work is the visit id). */
$kpi = ['total' => 0, 'worked' => 0, 'pending' => 0, 'today' => 0, 'high' => 0, 'regular' => 0];
$kst = $pdo->prepare("SELECT
        COUNT(*) total,
        SUM(inventory_status = 'worked') worked,
        SUM(COALESCE(inventory_status,'') <> 'worked') pending,
        SUM(priority = 'today') today,
        SUM(priority = 'high') high,
        SUM(priority = 'regular') regular
    FROM ar_visit_work WHERE allocated_user = ?");
$kst->execute([$uid]);
if ($k = $kst->fetch()) {
    foreach ($kpi as $kk => $_) $kpi[$kk] = (int) ($k[$kk] ?? 0);
}

/* 1. Verticals among THIS user's allocations (for the OPTIONAL vertical filter). */
$verticals = $pdo->prepare("SELECT DISTINCT v.id, v.name
    FROM ar_allocation a
    JOIN processes p ON p.id = a.process_id
    JOIN clients   c ON c.id = p.client_id
    JOIN verticals v ON v.id = c.vertical_id
    WHERE a.allocated_user = ?
    ORDER BY v.name");
$verticals->execute([$uid]);
$verticals = $verticals->fetchAll();
$vIds = array_map(fn($v) => (int) $v['id'], $verticals);
if ($fVertical && $vIds && !in_array($fVertical, $vIds, true)) { $fVertical = 0; }

/* 2. Processes among my allocations (optionally narrowed to the chosen vertical — shown without one too). */
$pq = "SELECT DISTINCT p.id, p.name, c.name AS client_name
    FROM ar_allocation a JOIN processes p ON p.id = a.process_id JOIN clients c ON c.id = p.client_id
    WHERE a.allocated_user = ?" . ($fVertical ? " AND c.vertical_id = ?" : "") . " ORDER BY c.name, p.name";
$st = $pdo->prepare($pq); $st->execute($fVertical ? [$uid, $fVertical] : [$uid]);
$processes = $st->fetchAll();
$pIds = array_map(fn($p) => (int) $p['id'], $processes);
if ($fProcess && $pIds && !in_array($fProcess, $pIds, true)) { $fProcess = 0; }

/* 3. Claim list — ALL my allocations by default; Vertical / Process / Allocation-type / Priority just NARROW it
 *    (none is required, so the open-inventory table is visible the moment the page loads). */
$where = ['a.allocated_user = ?']; $params = [$uid];
if ($fVertical)        { $where[] = 'c.vertical_id = ?';    $params[] = $fVertical; }
if ($fProcess)         { $where[] = 'a.process_id = ?';     $params[] = $fProcess; }
if ($fPriority !== '') { $where[] = 'a.priority = ?';       $params[] = $fPriority; }
$st = $pdo->prepare("SELECT a.*, p.name AS process_name, c.name AS client_name
    FROM ar_allocation a
    JOIN processes p ON p.id = a.process_id
    JOIN clients   c ON c.id = p.client_id
    WHERE " . implode(' AND ', $where) . "
    ORDER BY FIELD(a.priority,'today','high','regular'),
             a.next_follow_up_date IS NULL, a.next_follow_up_date ASC, a.dos ASC
    LIMIT 1000");
$st->execute($params);
$rows = $st->fetchAll();

/* Best-effort patient names for the VISIBLE charts — keyed by "process|chart" since the queue now spans
 * processes (collection_raw is replaced on every upload, so it's not joinable to ar_allocation). One grouped
 * lookup per process present in the result. */
$nameMap = [];
if ($rows) {
    $procCharts = [];
    foreach ($rows as $r) $procCharts[(int) $r['process_id']][(string) $r['chart_number']] = 1;
    foreach ($procCharts as $pidK => $chartsSet) {
        $rids = ar_process_report_ids($pdo, $pidK);
        if (!$rids) continue;
        $charts = array_keys($chartsSet);
        $inR = implode(',', array_map('intval', $rids));
        $inC = implode(',', array_fill(0, count($charts), '?'));
        $nm = $pdo->prepare("SELECT chart_number, MAX(CONCAT(patient_last_name,', ',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) $nameMap[$pidK . '|' . (string) $r['chart_number']] = trim((string) $r['nm'], ', ');
    }
}

/* Per-account VISIT progress (worked / total) from the visit ledger, keyed by "process|chart". */
$visitProg = [];
$vp = $pdo->prepare("SELECT process_id, chart_number, COUNT(*) tot, SUM(inventory_status='worked') wk
    FROM ar_visit_work WHERE allocated_user=? GROUP BY process_id, chart_number");
$vp->execute([$uid]);
foreach ($vp->fetchAll() as $r) $visitProg[(int) $r['process_id'] . '|' . (string) $r['chart_number']] = ['tot' => (int) $r['tot'], 'wk' => (int) $r['wk']];

$prioBadge = ['today' => 'red', 'high' => 'orange', 'regular' => 'secondary'];

$pageTitle = 'My AR queue';
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-checklist me-2 text-primary"></i>My AR queue</h2>
        <div class="text-secondary small">The collection accounts <strong>allocated to you</strong> — shown below by default. Optionally narrow by <strong>Vertical / Process / Allocation type / Priority</strong>, then <strong>Work</strong> an account to tag each visit. Or just hit <strong>Work next account</strong> to flow through them.</div>
    </div>
    <div class="col-auto"><a href="<?= e(url('/admin/ar-work.php?next=1')) ?>" class="btn btn-primary"><i class="ti ti-player-track-next me-1"></i>Work next account</a></div>
</div></div></div>

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

    <!-- ============================================================= KPI CHIPS -->
    <div class="row row-cards mb-3">
        <?php
        $chips = [
            ['Allocated to me', $kpi['total'],   'list-check',   'primary'],
            ['Worked',          $kpi['worked'],  'circle-check', 'green'],
            ['Pending',         $kpi['pending'], 'clock',        'azure'],
            ["Today's priority",$kpi['today'],   'alarm',        'red'],
            ['High priority',   $kpi['high'],    'arrow-up',     'orange'],
            ['Regular',         $kpi['regular'], 'minus',        'secondary'],
        ];
        foreach ($chips as [$lbl, $val, $icon, $col]): ?>
        <div class="col">
            <div class="card card-sm kpi-tile"><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 ?>"><?= number_format($val) ?></div>
            </div></div>
        </div>
        <?php endforeach; ?>
    </div>

    <!-- ============================================================= CASCADING FILTERS -->
    <div class="card mb-3">
        <div class="card-header"><h3 class="card-title"><i class="ti ti-filter me-2"></i>Pick your queue</h3></div>
        <div class="card-body">
            <form method="GET" class="row g-2 align-items-end">
                <div class="col-md-3">
                    <label class="form-label">Vertical</label>
                    <select name="vertical_id" class="form-select" onchange="this.form.submit()">
                        <option value="">— Select vertical —</option>
                        <?php foreach ($verticals as $v): ?>
                            <option value="<?= (int)$v['id'] ?>" <?= $fVertical===(int)$v['id']?'selected':'' ?>><?= e($v['name']) ?></option>
                        <?php endforeach; ?>
                    </select>
                </div>
                <div class="col-md-3">
                    <label class="form-label">Process</label>
                    <select name="process_id" class="form-select" onchange="this.form.submit()" <?= $processes?'':'disabled' ?>>
                        <option value="">— Select process —</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>
                <div class="col-md-3">
                    <label class="form-label">Priority <span class="text-secondary fw-normal">(optional)</span></label>
                    <select name="priority" class="form-select" onchange="this.form.submit()">
                        <option value="">All priorities (today → high → regular)</option>
                        <?php foreach (AR_PRIORITIES as $k => $lbl): ?>
                            <option value="<?= e($k) ?>" <?= $fPriority===$k?'selected':'' ?>><?= e($lbl) ?></option>
                        <?php endforeach; ?>
                    </select>
                </div>
                <div class="col-md-3">
                    <label class="form-label">Search <span class="text-secondary fw-normal">(this list)</span></label>
                    <input type="search" id="ar_inv_search" class="form-control" placeholder="Patient, account #, carrier…" oninput="arInvSearch()" autocomplete="off">
                </div>
                <?php if ($fVertical || $fProcess || $fPriority !== ''): ?>
                    <div class="col-auto"><a href="<?= e(url('/admin/ar-queue.php')) ?>" class="btn btn-link text-secondary">Clear filters</a></div>
                <?php endif; ?>
            </form>
        </div>
    </div>

    <!-- ============================================================= CLAIM LIST (shown by default) -->
    <?php if ($kpi['total'] === 0): ?>
        <div class="card"><div class="card-body text-center text-secondary py-5">
            <i class="ti ti-mood-smile" style="font-size:2rem"></i>
            <div class="mt-2">Nothing is allocated to you yet. Check back once your supervisor allocates claims. 🎉</div>
        </div></div>
    <?php else: ?>
    <div class="card">
        <div class="card-header">
            <h3 class="card-title"><i class="ti ti-list me-2"></i>My open inventory</h3>
            <div class="card-actions text-secondary small">
                <span id="ar_inv_count"><?= number_format(count($rows)) ?></span> account(s)<?= $fPriority!==''?' · '.e(AR_PRIORITIES[$fPriority]):'' ?> · click a header to sort
            </div>
        </div>
        <div class="table-responsive"><table class="table table-vcenter card-table table-sm" id="ar_inv_table">
            <thead><tr>
                <?php $H = fn($l, $num=false) => '<th class="'.($num?'text-end ':'').'" data-num="'.($num?'1':'0').'" onclick="arInvSort(this)" style="cursor:pointer">'.$l.'</th>'; ?>
                <?= $H('Patient Account #') ?><?= $H('Patient') ?><?= $H('Process') ?><?= $H('Carrier') ?><?= $H('DOS', true) ?><?= $H('Priority', true) ?>
                <?= $H('Ins. bal', true) ?><?= $H('Pat. bal', true) ?><?= $H('Visits worked', true) ?>
                <th class="w-1"></th>
            </tr></thead>
            <tbody>
            <?php if (!$rows): ?>
                <tr><td colspan="10" class="text-center text-secondary py-4">No accounts match these filters. <a href="<?= e(url('/admin/ar-queue.php')) ?>">Clear filters</a>.</td></tr>
            <?php else:
                $prioRank = ['today'=>0, 'high'=>1, 'regular'=>2];
                foreach ($rows as $r):
                $rpid = (int) $r['process_id'];
                $pk   = (string) ($r['priority'] ?? '');
                $key  = $rpid . '|' . (string) $r['chart_number'];
                $name = ($nameMap[$key] ?? '') ?: (string) ($r['patient_name'] ?? '');   // live collection_raw name, else the snapshot stored at allocation
                $vpg  = $visitProg[$key] ?? ['tot'=>0,'wk'=>0]; $allDone = $vpg['tot']>0 && $vpg['wk']>=$vpg['tot'];
            ?>
                <tr>
                    <td class="font-mono"><?= e($r['chart_number']) ?></td>
                    <td class="small"><?= $name !== '' ? e($name) : '<span class="text-secondary">' . e($r['chart_number']) . '</span>' ?></td>
                    <td class="small text-secondary"><?= e(($r['client_name'] ?? '') . ' · ' . ($r['process_name'] ?? '')) ?></td>
                    <td class="small"><?= e($r['carrier_name'] ?? '—') ?></td>
                    <td class="small text-nowrap" data-v="<?= e((string)($r['dos'] ?? '')) ?>"><?= e(fmt_date($r['dos'])) ?></td>
                    <td data-v="<?= $prioRank[$pk] ?? 9 ?>"><span class="badge bg-<?= $prioBadge[$pk] ?? 'secondary' ?>-lt"><?= e(AR_PRIORITIES[$pk] ?? '—') ?></span></td>
                    <td class="text-end font-mono" data-v="<?= (float)($r['insurance_balance'] ?? 0) ?>"><?= $r['insurance_balance'] !== null ? number_format((float)$r['insurance_balance'], 2) : '—' ?></td>
                    <td class="text-end font-mono" data-v="<?= (float)($r['patient_balance'] ?? 0) ?>"><?= $r['patient_balance'] !== null ? number_format((float)$r['patient_balance'], 2) : '—' ?></td>
                    <td class="text-end" data-v="<?= (int)$vpg['wk'] ?>"><span class="badge bg-<?= $allDone?'green':($vpg['wk']>0?'azure':'secondary') ?>-lt"><?= $vpg['wk'] ?>/<?= $vpg['tot'] ?></span></td>
                    <td class="text-end">
                        <a href="<?= e(url('/admin/ar-work.php?process=' . $rpid . '&account=' . rawurlencode((string)$r['chart_number']))) ?>" class="btn btn-sm btn-primary"><i class="ti ti-pencil me-1"></i><?= $allDone ? 'Review' : 'Work' ?></a>
                    </td>
                </tr>
            <?php endforeach; endif; ?>
            </tbody>
        </table></div>
        <?php if (count($rows) >= 1000): ?><div class="card-footer text-secondary small">Showing first 1000 — narrow with the filters above.</div><?php endif; ?>
        <?php if (can('ar.reports')): ?><div class="card-footer text-secondary small">Want carrier / patient &amp; visits analysis (sortable high↔low)? See <a href="<?= e(url('/admin/ar-reports.php?report=allocation')) ?>">AR reports → My allocation</a>.</div><?php endif; ?>
    </div>
    <?php endif; ?>

</div></div>
<script>
// click any header to sort (numeric/date cols use data-v); toggles asc/desc.
function arInvSort(th){
    var tb=th.closest('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 ca=a.cells[idx], cb=b.cells[idx];
        var x=ca.getAttribute('data-v'); if(x===null) x=ca.textContent.trim();
        var y=cb.getAttribute('data-v'); if(y===null) y=cb.textContent.trim();
        if(num) return asc? (parseFloat(x)||0)-(parseFloat(y)||0) : (parseFloat(y)||0)-(parseFloat(x)||0);
        return asc? String(x).localeCompare(y) : String(y).localeCompare(x);
    });
    rows.forEach(function(r){ tb.appendChild(r); });
}
// free-text search across the visible rows of My open inventory.
function arInvSearch(){
    var el=document.getElementById('ar_inv_search'), tb=document.querySelector('#ar_inv_table tbody'); if(!el||!tb) return;
    var q=(el.value||'').toLowerCase().trim(), n=0;
    Array.prototype.forEach.call(tb.rows,function(r){ if(r.cells.length<2) return; var show=!q||r.textContent.toLowerCase().indexOf(q)!==-1; r.style.display=show?'':'none'; if(show)n++; });
    var c=document.getElementById('ar_inv_count'); if(c) c.textContent=n.toLocaleString();
}
</script>
<?php require __DIR__ . '/../includes/footer.php'; ?>
