<?php
/* DebtorsDashboard.php - Modern Debtors/Accounts Receivable Dashboard */
error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING & ~E_DEPRECATED);
$PageSecurity = 0;

/* Buffer output so session includes don't corrupt API JSON */
$_isAPI = isset($_GET['api']);
if ($_isAPI) { ob_start(); }

include('includes/session.inc');
$Title = _('Debtors Dashboard');
$userid = $_SESSION['UserID'];

/* ─── API MODE ─── */
if ($_isAPI) {
    ob_end_clean(); /* Discard any output from includes */
    header('Content-Type: application/json');
    header('Cache-Control: no-cache');

    $conn = new mysqli('localhost', 'sooggoo', '4Compassion*', 'evergreenint');
    if ($conn->connect_error) {
        echo json_encode(['error' => 'DB connection failed']);
        exit;
    }
    $conn->set_charset('utf8');

    $action = $_GET['api'];
    $currentYear = date('Y');
    $currentMonth = date('m');
    $yearStart = $currentYear . '-01-01';
    $today = date('Y-m-d');

    /* ── Debug / Test ── */
    if ($action === 'debug') {
        echo json_encode([
            'status' => 'ok',
            'php' => PHP_VERSION,
            'db' => $conn->server_info,
            'user' => $userid,
            'tables_check' => (bool)$conn->query("SELECT 1 FROM debtortrans LIMIT 1"),
            'debtorsmaster_check' => (bool)$conn->query("SELECT 1 FROM debtorsmaster LIMIT 1"),
            'debtoraccount_check' => (bool)$conn->query("SELECT 1 FROM debtoraccount LIMIT 1"),
            'department_check' => (bool)$conn->query("SELECT 1 FROM department LIMIT 1")
        ]);
        exit;
    }

    /* ── KPI Summary ── */
    if ($action === 'summary') {
        $out = [];

        // Total AR (all unsettled)
        $r = $conn->query("SELECT SUM(ovamount + ovgst + ovfreight + ovdiscount - alloc - ptax - retention) AS total
                           FROM debtortrans WHERE settled=0 AND cancelled=0");
        $out['totalAR'] = ($r && $row = $r->fetch_assoc()) ? round((isset($row['total']) ? $row['total'] : 0), 2) : 0;

        // Overdue AR (>20 days)
        $r = $conn->query("SELECT SUM(CASE WHEN DATEDIFF(CURDATE(), trandate) >= 20
                           THEN ovamount + ovgst + ovfreight + ovdiscount - alloc - ptax - retention ELSE 0 END) AS overdue
                           FROM debtortrans WHERE settled=0 AND cancelled=0");
        $out['overdueAR'] = ($r && $row = $r->fetch_assoc()) ? round((isset($row['overdue']) ? $row['overdue'] : 0), 2) : 0;

        // Current AR (<=20 days)
        $out['currentAR'] = round($out['totalAR'] - $out['overdueAR'], 2);
        $out['overduePercent'] = $out['totalAR'] > 0 ? round(($out['overdueAR'] / $out['totalAR']) * 100, 1) : 0;

        // YTD Sales (type=10 invoices)
        $r = $conn->query("SELECT SUM(ovamount + ovgst) AS sales FROM debtortrans
                           WHERE type='10' AND cancelled=0
                           AND trandate BETWEEN '{$yearStart}' AND '{$today}'");
        $out['ytdSales'] = ($r && $row = $r->fetch_assoc()) ? round((isset($row['sales']) ? $row['sales'] : 0), 2) : 0;

        // YTD Receipts (type=12)
        $r = $conn->query("SELECT SUM(ABS(ovamount) + ABS(ovgst)) AS receipts FROM debtortrans
                           WHERE type='12' AND cancelled=0
                           AND trandate BETWEEN '{$yearStart}' AND '{$today}'");
        $out['ytdReceipts'] = ($r && $row = $r->fetch_assoc()) ? round((isset($row['receipts']) ? $row['receipts'] : 0), 2) : 0;

        // Total active debtors
        $r = $conn->query("SELECT COUNT(DISTINCT debtorno) AS cnt FROM debtortrans WHERE settled=0 AND cancelled=0");
        $out['activeDebtors'] = ($r && $row = $r->fetch_assoc()) ? intval(isset($row['cnt']) ? $row['cnt'] : 0) : 0;

        // DSO (Days Sales Outstanding) = (AR / YTD Sales) * days elapsed
        $daysElapsed = (time() - strtotime($yearStart)) / 86400;
        $out['dso'] = ($out['ytdSales'] > 0 && $daysElapsed > 0)
            ? round(($out['totalAR'] / ($out['ytdSales'] / $daysElapsed)), 0)
            : 0;

        echo json_encode($out);
        exit;
    }

    /* ── Aging Buckets Totals ── */
    if ($action === 'aging_buckets') {
        $r = $conn->query("
            SELECT
                SUM(CASE WHEN DATEDIFF(CURDATE(), LAST_DAY(trandate)) < 30 THEN ovamount+ovgst+ovfreight+ovdiscount-alloc-ptax-retention ELSE 0 END) AS current_bucket,
                SUM(CASE WHEN DATEDIFF(CURDATE(), LAST_DAY(trandate)) BETWEEN 30 AND 59 THEN ovamount+ovgst+ovfreight+ovdiscount-alloc-ptax-retention ELSE 0 END) AS days_30,
                SUM(CASE WHEN DATEDIFF(CURDATE(), LAST_DAY(trandate)) BETWEEN 60 AND 89 THEN ovamount+ovgst+ovfreight+ovdiscount-alloc-ptax-retention ELSE 0 END) AS days_60,
                SUM(CASE WHEN DATEDIFF(CURDATE(), LAST_DAY(trandate)) BETWEEN 90 AND 119 THEN ovamount+ovgst+ovfreight+ovdiscount-alloc-ptax-retention ELSE 0 END) AS days_90,
                SUM(CASE WHEN DATEDIFF(CURDATE(), LAST_DAY(trandate)) BETWEEN 120 AND 149 THEN ovamount+ovgst+ovfreight+ovdiscount-alloc-ptax-retention ELSE 0 END) AS days_120,
                SUM(CASE WHEN DATEDIFF(CURDATE(), LAST_DAY(trandate)) BETWEEN 150 AND 179 THEN ovamount+ovgst+ovfreight+ovdiscount-alloc-ptax-retention ELSE 0 END) AS days_150,
                SUM(CASE WHEN DATEDIFF(CURDATE(), LAST_DAY(trandate)) >= 180 THEN ovamount+ovgst+ovfreight+ovdiscount-alloc-ptax-retention ELSE 0 END) AS days_180
            FROM debtortrans
            WHERE settled=0 AND cancelled=0 AND trandate > '2020-12-31'
              AND account_number IS NOT NULL AND account_number != ''
        ");
        if ($r && $row = $r->fetch_assoc()) {
            echo json_encode($row);
        } else {
            echo json_encode(['current_bucket'=>0,'days_30'=>0,'days_60'=>0,'days_90'=>0,'days_120'=>0,'days_150'=>0,'days_180'=>0,'error'=>$conn->error]);
        }
        exit;
    }

    /* ── Monthly Trend (current year) ── */
    if ($action === 'monthly_trend') {
        $rows = [];
        $r = $conn->query("
            SELECT MONTH(trandate) AS m, MONTHNAME(trandate) AS month_name,
                SUM(ovamount+ovgst+ovfreight+ovdiscount-alloc-ptax-retention) AS balance,
                SUM(CASE WHEN DATEDIFF(CURDATE(), trandate) >= 20
                    THEN ovamount+ovgst+ovfreight+ovdiscount-alloc-ptax-retention ELSE 0 END) AS overdue
            FROM debtortrans
            WHERE settled=0 AND cancelled=0 AND YEAR(trandate) = '{$currentYear}'
            GROUP BY MONTH(trandate), MONTHNAME(trandate)
            ORDER BY MONTH(trandate)
        ");
        if ($r) { while ($row = $r->fetch_assoc()) {
            $rows[] = [
                'month' => substr($row['month_name'], 0, 3),
                'receivable' => round(floatval($row['balance']), 2),
                'overdue' => round(floatval($row['overdue']), 2)
            ];
        } }
        echo json_encode($rows);
        exit;
    }

    /* ── Department Breakdown ── */
    if ($action === 'department_breakdown') {
        $rows = [];
        $r = $conn->query("
            SELECT IFNULL(d.departmentname, 'Unassigned') AS dept,
                SUM(dt.ovamount+dt.ovgst+dt.ovfreight+dt.ovdiscount-dt.alloc-dt.ptax-dt.retention) AS balance
            FROM debtortrans dt
            LEFT JOIN debtoraccount da ON dt.account_number = da.account_number
            LEFT JOIN department d ON da.departmentid = d.departmentid
            WHERE dt.settled=0 AND dt.cancelled=0
              AND dt.account_number IS NOT NULL AND dt.account_number != ''
            GROUP BY d.departmentname
            HAVING balance > 0
            ORDER BY balance DESC
        ");
        if ($r) { while ($row = $r->fetch_assoc()) {
            $rows[] = ['department' => $row['dept'], 'balance' => round(floatval($row['balance']), 2)];
        } }
        echo json_encode($rows);
        exit;
    }

    /* ── Top Debtors ── */
    if ($action === 'top_debtors') {
        $limit = intval(isset($_GET['limit']) ? intval($_GET['limit']) : 10);
        $rows = [];
        $r = $conn->query("
            SELECT dm.debtorno, dm.name,
                SUM(dt.ovamount+dt.ovgst+dt.ovfreight+dt.ovdiscount-dt.alloc-dt.ptax-dt.retention) AS balance,
                SUM(CASE WHEN DATEDIFF(CURDATE(), dt.trandate) >= 20
                    THEN dt.ovamount+dt.ovgst+dt.ovfreight+dt.ovdiscount-dt.alloc-dt.ptax-dt.retention ELSE 0 END) AS overdue,
                MAX(dt.trandate) AS last_trans
            FROM debtortrans dt
            JOIN debtorsmaster dm ON dt.debtorno = dm.debtorno
            WHERE dt.settled=0 AND dt.cancelled=0
            GROUP BY dm.debtorno, dm.name
            HAVING balance > 0
            ORDER BY balance DESC
            LIMIT {$limit}
        ");
        if ($r) { while ($row = $r->fetch_assoc()) {
            $rows[] = [
                'debtorno' => $row['debtorno'],
                'name' => $row['name'],
                'balance' => round(floatval($row['balance']), 2),
                'overdue' => round(floatval($row['overdue']), 2),
                'lastTrans' => $row['last_trans']
            ];
        } }
        echo json_encode($rows);
        exit;
    }

    /* ── Full Aging Report (from JSON file) ── */
    if ($action === 'aging_report') {
        // Regenerate the JSON via node
        $nodePath = '/usr/bin/node';
        $appPath = '/home/erp/www/wormalderp/nodejsapp/app.js';
        @shell_exec("$nodePath $appPath 2>&1");

        $jsonFile = 'nodejsapp/aging_report.json';
        if (file_exists($jsonFile)) {
            $data = json_decode(file_get_contents($jsonFile), true);
            if ($data) {
                echo json_encode($data);
            } else {
                echo json_encode([]);
            }
        } else {
            echo json_encode([]);
        }
        exit;
    }

    /* ── Outstanding Transactions for an account ── */
    if ($action === 'outstanding_trans') {
        $acct = $conn->real_escape_string(isset($_GET['account']) ? $_GET['account'] : '');
        $rows = [];
        $r = $conn->query("
            SELECT
                CASE dt.type
                    WHEN 10 THEN 'Invoice'
                    WHEN 11 THEN 'Credit Note'
                    WHEN 12 THEN 'Receipt'
                    ELSE dt.type
                END AS trans_type,
                dt.transno AS trans_no,
                DATE_FORMAT(dt.trandate, '%d/%m/%Y') AS trans_date,
                ROUND(dt.ovamount + dt.ovgst + dt.ovfreight + dt.ovdiscount, 2) AS total,
                ROUND(dt.ovamount + dt.ovgst + dt.ovfreight + dt.ovdiscount - dt.alloc - dt.ptax - dt.retention, 2) AS outstanding
            FROM debtortrans dt
            WHERE dt.account_number = '{$acct}' AND dt.settled=0 AND dt.cancelled=0
            ORDER BY dt.trandate DESC
        ");
        if ($r) { while ($row = $r->fetch_assoc()) {
            $rows[] = $row;
        } }
        echo json_encode($rows);
        exit;
    }

    /* ── All Transactions for an account ── */
    if ($action === 'all_trans') {
        $acct = $conn->real_escape_string(isset($_GET['account']) ? $_GET['account'] : '');
        $rows = [];
        $r = $conn->query("
            SELECT
                CASE dt.type
                    WHEN 10 THEN 'Invoice'
                    WHEN 11 THEN 'Credit Note'
                    WHEN 12 THEN 'Receipt'
                    ELSE dt.type
                END AS trans_type,
                dt.transno AS trans_no,
                DATE_FORMAT(dt.trandate, '%d/%m/%Y') AS trans_date,
                ROUND(dt.ovamount + dt.ovgst + dt.ovfreight + dt.ovdiscount, 2) AS total,
                ROUND(dt.ovamount + dt.ovgst + dt.ovfreight + dt.ovdiscount - dt.alloc - dt.ptax - dt.retention, 2) AS outstanding
            FROM debtortrans dt
            WHERE dt.account_number = '{$acct}' AND dt.cancelled=0
            ORDER BY dt.trandate DESC
            LIMIT 200
        ");
        if ($r) { while ($row = $r->fetch_assoc()) {
            $rows[] = $row;
        } }
        echo json_encode($rows);
        exit;
    }

    /* ── Collection Performance (last 6 months receipts vs invoices) ── */
    if ($action === 'collection_performance') {
        $rows = [];
        $r = $conn->query("
            SELECT MONTHNAME(trandate) AS month_name, MONTH(trandate) AS m,
                SUM(CASE WHEN type=10 THEN ovamount+ovgst ELSE 0 END) AS invoiced,
                SUM(CASE WHEN type=12 THEN ABS(ovamount)+ABS(ovgst) ELSE 0 END) AS collected
            FROM debtortrans
            WHERE cancelled=0 AND trandate >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
            GROUP BY MONTH(trandate), MONTHNAME(trandate)
            ORDER BY MONTH(trandate)
        ");
        if ($r) { while ($row = $r->fetch_assoc()) {
            $rows[] = [
                'month' => substr($row['month_name'], 0, 3),
                'invoiced' => round(floatval($row['invoiced']), 2),
                'collected' => round(floatval($row['collected']), 2)
            ];
        } }
        echo json_encode($rows);
        exit;
    }

    $conn->close();
    echo json_encode(['error' => 'Unknown API action']);
    exit;
}

/* ─── PERMISSION CHECK ─── */
$allowedUsers = ['admin','maazil','mosheed','zubia','nitika','ravinesh','sharukh','ravneet','mere','Avishek','Priti','zibran','saula','shaireen'];
if (!in_array($userid, $allowedUsers)) {
    include('includes/newheader.php');
    echo '<div style="padding:40px;text-align:center;font-size:18px;color:#FF4D4F;">You do not have permission to access this section.</div>';
    include('includes/footer.inc');
    exit;
}

include('includes/newheader.php');
?>

<!-- CDN Resources -->
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.min.js"></script>

<style>
/* ─── GLOBAL ─── */
.debtor-dash * { box-sizing: border-box; margin: 0; padding: 0; }
.debtor-dash { font-family: 'Poppins', sans-serif; color: #1F2937; padding: 0; }

/* ─── HEADER BANNER ─── */
.debtor-hdr {
    background: linear-gradient(135deg, #2AABB3 0%, #1E8F96 50%, #187278 100%);
    padding: 28px 32px 22px;
    border-radius: 0 0 16px 16px;
    color: #fff;
    margin-bottom: 20px;
    position: relative;
    overflow: hidden;
}
.debtor-hdr::before {
    content: '';
    position: absolute;
    top: -40px; right: -40px;
    width: 180px; height: 180px;
    background: rgba(255,255,255,0.06);
    border-radius: 50%;
}
.debtor-hdr::after {
    content: '';
    position: absolute;
    bottom: -60px; left: 30%;
    width: 240px; height: 240px;
    background: rgba(255,255,255,0.04);
    border-radius: 50%;
}
.debtor-hdr h1 {
    font-size: 22px; font-weight: 700;
    margin-bottom: 4px;
    position: relative; z-index: 1;
}
.debtor-hdr .breadcrumbs {
    font-size: 13px; opacity: 0.85;
    position: relative; z-index: 1;
}
.debtor-hdr .breadcrumbs a { color: #fff; text-decoration: none; }
.debtor-hdr .breadcrumbs a:hover { text-decoration: underline; }
.debtor-hdr .hdr-meta {
    position: absolute; right: 32px; top: 50%;
    transform: translateY(-50%);
    text-align: right; z-index: 1;
    font-size: 13px; opacity: 0.9;
}

/* ─── DASHBOARD TOGGLE ─── */
.dash-toggle {
    display: flex; align-items: center; gap: 8px;
    padding: 10px 20px;
    cursor: pointer; user-select: none;
    font-size: 14px; font-weight: 600; color: #1E8F96;
    border-bottom: 1px solid #E5E7EB;
    background: #F8FFFE;
}
.dash-toggle i { transition: transform 0.3s; }
.dash-toggle.collapsed i { transform: rotate(-90deg); }
.dash-panel { transition: max-height 0.4s ease, opacity 0.3s; overflow: hidden; }
.dash-panel.collapsed { max-height: 0 !important; opacity: 0; }

/* ─── KPI CARDS ─── */
.kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; padding: 20px; }
@media (max-width: 1200px) { .kpi-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .kpi-grid { grid-template-columns: 1fr; } }

.kpi-card {
    background: #fff;
    border-radius: 12px;
    padding: 20px 22px;
    border-left: 4px solid #2AABB3;
    box-shadow: 0 1px 4px rgba(0,0,0,0.06);
    transition: transform 0.2s, box-shadow 0.2s;
    position: relative;
}
.kpi-card:hover { transform: translateY(-2px); box-shadow: 0 4px 16px rgba(42,171,179,0.12); }
.kpi-card.warning { border-left-color: #FAAD14; }
.kpi-card.danger { border-left-color: #FF4D4F; }
.kpi-card.success { border-left-color: #52C41A; }
.kpi-card.info { border-left-color: #1890FF; }
.kpi-card.purple { border-left-color: #722ED1; }

.kpi-icon {
    width: 44px; height: 44px;
    border-radius: 10px;
    display: flex; align-items: center; justify-content: center;
    font-size: 20px; color: #fff;
    position: absolute; top: 18px; right: 18px;
}
.kpi-icon.teal { background: linear-gradient(135deg, #2AABB3, #1E8F96); }
.kpi-icon.orange { background: linear-gradient(135deg, #FAAD14, #D48806); }
.kpi-icon.red { background: linear-gradient(135deg, #FF4D4F, #CF1322); }
.kpi-icon.green { background: linear-gradient(135deg, #52C41A, #389E0D); }
.kpi-icon.blue { background: linear-gradient(135deg, #1890FF, #096DD9); }
.kpi-icon.purple { background: linear-gradient(135deg, #722ED1, #531DAB); }

.kpi-label { font-size: 12px; color: #8C8C8C; text-transform: uppercase; letter-spacing: 0.5px; font-weight: 500; }
.kpi-value { font-size: 26px; font-weight: 700; color: #1F2937; margin: 6px 0 4px; }
.kpi-sub { font-size: 12px; color: #8C8C8C; }
.kpi-sub .up { color: #52C41A; }
.kpi-sub .down { color: #FF4D4F; }

/* ─── CHART PANELS ─── */
.chart-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; padding: 0 20px 20px; }
@media (max-width: 900px) { .chart-grid { grid-template-columns: 1fr; } }

.chart-card {
    background: #fff;
    border-radius: 12px;
    padding: 20px;
    box-shadow: 0 1px 4px rgba(0,0,0,0.06);
}
.chart-card h3 {
    font-size: 15px; font-weight: 600; color: #1F2937;
    margin-bottom: 16px;
    padding-bottom: 10px;
    border-bottom: 1px solid #F0F0F0;
}
.chart-card h3 i { color: #2AABB3; margin-right: 8px; }
.chart-card canvas { max-height: 280px; }

/* ─── TOP DEBTORS PANEL ─── */
.top-debtors-grid { display: grid; grid-template-columns: 2fr 1fr; gap: 16px; padding: 0 20px 20px; }
@media (max-width: 900px) { .top-debtors-grid { grid-template-columns: 1fr; } }

.debtor-rank {
    display: flex; align-items: center; gap: 14px;
    padding: 12px 16px;
    border-bottom: 1px solid #F5F5F5;
    transition: background 0.15s;
}
.debtor-rank:hover { background: #F8FFFE; }
.debtor-rank:last-child { border-bottom: none; }

.rank-num {
    width: 30px; height: 30px;
    border-radius: 50%;
    background: #E6F7F8;
    color: #1E8F96;
    font-weight: 700; font-size: 13px;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.rank-num.hot { background: #FFF1F0; color: #FF4D4F; }
.debtor-rank .name { font-weight: 500; font-size: 14px; flex: 1; }
.debtor-rank .amount { font-weight: 700; font-size: 14px; color: #1F2937; text-align: right; }
.debtor-rank .overdue-tag { font-size: 11px; color: #FF4D4F; font-weight: 500; }

/* ─── PROGRESS BAR ─── */
.aging-bar { display: flex; height: 12px; border-radius: 6px; overflow: hidden; margin-top: 8px; }
.aging-bar .seg { transition: width 0.5s; }
.aging-bar .seg.s-current { background: #52C41A; }
.aging-bar .seg.s-30 { background: #FAAD14; }
.aging-bar .seg.s-60 { background: #FA8C16; }
.aging-bar .seg.s-90 { background: #F5222D; }
.aging-bar .seg.s-120 { background: #CF1322; }
.aging-bar .seg.s-150 { background: #A8071A; }
.aging-bar .seg.s-180 { background: #5C0011; }

.aging-legend {
    display: flex; flex-wrap: wrap; gap: 12px; margin-top: 12px; font-size: 12px;
}
.aging-legend .leg-item { display: flex; align-items: center; gap: 5px; }
.aging-legend .dot { width: 10px; height: 10px; border-radius: 3px; }

/* ─── FULL AGING TABLE ─── */
.aging-section { padding: 0 20px 20px; }

.aging-toolbar {
    display: flex; align-items: center; gap: 10px; margin-bottom: 14px; flex-wrap: wrap;
}
.aging-toolbar input[type="text"] {
    padding: 8px 14px; border: 1px solid #D9D9D9; border-radius: 8px;
    font-size: 13px; font-family: 'Poppins', sans-serif;
    width: 280px; outline: none;
    transition: border 0.2s;
}
.aging-toolbar input[type="text"]:focus { border-color: #2AABB3; box-shadow: 0 0 0 2px rgba(42,171,179,0.15); }

.aging-toolbar select {
    padding: 8px 12px; border: 1px solid #D9D9D9; border-radius: 8px;
    font-size: 13px; font-family: 'Poppins', sans-serif;
    outline: none; background: #fff; cursor: pointer;
}

.btn-action {
    padding: 8px 16px;
    border: none; border-radius: 8px;
    font-size: 12px; font-weight: 600;
    font-family: 'Poppins', sans-serif;
    cursor: pointer;
    display: inline-flex; align-items: center; gap: 6px;
    transition: all 0.2s;
}
.btn-action.primary { background: #2AABB3; color: #fff; }
.btn-action.primary:hover { background: #1E8F96; }
.btn-action.outline { background: #fff; color: #2AABB3; border: 1px solid #2AABB3; }
.btn-action.outline:hover { background: #E6F7F8; }
.btn-action.success { background: #52C41A; color: #fff; }
.btn-action.success:hover { background: #389E0D; }
.btn-action.warning { background: #FAAD14; color: #fff; }
.btn-action.warning:hover { background: #D48806; }
.btn-action.danger { background: #FF4D4F; color: #fff; }
.btn-action.danger:hover { background: #CF1322; }
.btn-action:disabled { opacity: 0.5; cursor: not-allowed; }

/* ─── TABLE STYLES ─── */
.ar-table-wrap {
    overflow-x: auto; border-radius: 12px;
    box-shadow: 0 1px 4px rgba(0,0,0,0.06);
    background: #fff;
}
.ar-table {
    width: 100%; border-collapse: collapse;
    font-size: 13px;
}
.ar-table thead th {
    background: linear-gradient(135deg, #2AABB3, #1E8F96);
    color: #fff; font-weight: 600;
    padding: 12px 14px;
    text-align: left;
    position: sticky; top: 0; z-index: 2;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
}
.ar-table thead th:hover { background: #187278; }
.ar-table thead th .sort-arrow { margin-left: 4px; font-size: 10px; opacity: 0.7; }
.ar-table tbody tr {
    border-bottom: 1px solid #F5F5F5;
    transition: background 0.15s;
    cursor: pointer;
}
.ar-table tbody tr:hover { background: #F0FDFE; }
.ar-table tbody tr.selected { background: #D6F5F7; }
.ar-table tbody td {
    padding: 10px 14px;
    white-space: nowrap;
}
.ar-table tbody td.num { text-align: right; font-variant-numeric: tabular-nums; }
.ar-table tbody td.negative { color: #52C41A; }
.ar-table tbody td.overdue-cell { color: #FF4D4F; font-weight: 600; }

.table-footer {
    display: flex; justify-content: space-between; align-items: center;
    padding: 12px 16px; font-size: 13px; color: #8C8C8C;
    border-top: 1px solid #F0F0F0;
}
.table-footer .pagination { display: flex; gap: 4px; }
.table-footer .pagination button {
    padding: 6px 12px; border: 1px solid #D9D9D9; border-radius: 6px;
    background: #fff; cursor: pointer; font-size: 12px; font-family: 'Poppins', sans-serif;
}
.table-footer .pagination button.active { background: #2AABB3; color: #fff; border-color: #2AABB3; }
.table-footer .pagination button:hover:not(.active) { border-color: #2AABB3; color: #2AABB3; }

/* ─── MODAL ─── */
.modal-overlay {
    position: fixed; top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(0,0,0,0.45);
    display: flex; align-items: center; justify-content: center;
    z-index: 9999;
    animation: fadeIn 0.2s;
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

.modal-box {
    background: #fff; border-radius: 16px;
    width: 90%; max-width: 800px; max-height: 80vh;
    overflow: hidden;
    box-shadow: 0 20px 60px rgba(0,0,0,0.2);
    animation: slideUp 0.3s;
}
@keyframes slideUp { from { transform: translateY(40px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }

.modal-box .modal-header {
    padding: 18px 24px;
    background: linear-gradient(135deg, #2AABB3, #1E8F96);
    color: #fff;
    display: flex; justify-content: space-between; align-items: center;
}
.modal-box .modal-header h3 { font-size: 16px; font-weight: 600; }
.modal-box .modal-close {
    background: rgba(255,255,255,0.2); border: none; color: #fff;
    width: 32px; height: 32px; border-radius: 8px;
    cursor: pointer; font-size: 16px;
    display: flex; align-items: center; justify-content: center;
}
.modal-box .modal-body { padding: 20px 24px; overflow-y: auto; max-height: 60vh; }

/* ─── LOADING ─── */
.loading-wrap {
    display: flex; align-items: center; justify-content: center;
    padding: 60px; color: #2AABB3;
}
.spinner {
    width: 36px; height: 36px;
    border: 3px solid #E6F7F8;
    border-top: 3px solid #2AABB3;
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
    margin-right: 12px;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ─── ALERT ROW ─── */
.alert-section { padding: 0 20px 16px; }
.alert-card {
    background: #FFF7E6; border: 1px solid #FFE58F; border-radius: 10px;
    padding: 14px 20px; display: flex; align-items: center; gap: 12px;
    font-size: 13px;
}
.alert-card.critical { background: #FFF1F0; border-color: #FFA39E; }
.alert-card i { font-size: 18px; }
.alert-card.critical i { color: #FF4D4F; }
.alert-card:not(.critical) i { color: #FAAD14; }
</style>

<div class="debtor-dash" id="debtorDashRoot">
    <div class="loading-wrap" id="mainLoader">
        <div class="spinner"></div>
        <span style="font-size:15px;font-weight:500;">Loading Debtors Dashboard...</span>
    </div>
</div>

<script>
(function() {
    const API = 'DebtorsDashboard.php?api=';
    const FMT = (n) => {
        if (n == null || isNaN(n)) return '$0.00';
        const abs = Math.abs(n);
        if (abs >= 1e6) return (n < 0 ? '-' : '') + '$' + (abs/1e6).toFixed(2) + 'M';
        if (abs >= 1e3) return (n < 0 ? '-' : '') + '$' + (abs/1e3).toFixed(1) + 'K';
        return '$' + Number(n).toLocaleString('en-US', {minimumFractionDigits:2, maximumFractionDigits:2});
    };
    const FMTFULL = (n) => '$' + Number(n||0).toLocaleString('en-US', {minimumFractionDigits:2, maximumFractionDigits:2});

    // State
    let state = {
        summary: null, agingBuckets: null, monthlyTrend: null, deptBreakdown: null,
        topDebtors: null, agingReport: null, collectionPerf: null,
        loading: true, dashCollapsed: false,
        search: '', deptFilter: '', sortCol: 'total_balance', sortDir: 'desc',
        page: 1, pageSize: 25,
        selectedRow: null, modal: null, modalData: null, modalLoading: false
    };

    // Fetch all data
    async function fetchAll() {
        try {
            const safeFetch = async (url, label) => {
                try {
                    const r = await fetch(url);
                    if (!r.ok) { console.error(label + ' HTTP ' + r.status); return null; }
                    const text = await r.text();
                    try { return JSON.parse(text); }
                    catch(e) { console.error(label + ' invalid JSON:', text.substring(0, 200)); return null; }
                } catch(e) { console.error(label + ' fetch error:', e); return null; }
            };

            const [summary, buckets, trend, dept, top, aging, coll] = await Promise.all([
                safeFetch(API+'summary', 'summary'),
                safeFetch(API+'aging_buckets', 'aging_buckets'),
                safeFetch(API+'monthly_trend', 'monthly_trend'),
                safeFetch(API+'department_breakdown', 'department_breakdown'),
                safeFetch(API+'top_debtors&limit=10', 'top_debtors'),
                safeFetch(API+'aging_report', 'aging_report'),
                safeFetch(API+'collection_performance', 'collection_performance')
            ]);
            state.summary = summary || {totalAR:0, overdueAR:0, currentAR:0, overduePercent:0, ytdSales:0, ytdReceipts:0, activeDebtors:0, dso:0};
            state.agingBuckets = buckets || {current_bucket:0, days_30:0, days_60:0, days_90:0, days_120:0, days_150:0, days_180:0};
            state.monthlyTrend = trend || [];
            state.deptBreakdown = dept || [];
            state.topDebtors = top || [];
            state.agingReport = aging || [];
            state.collectionPerf = coll || [];
            state.loading = false;

            // Restore dashboard toggle
            const saved = localStorage.getItem('debtorDashCollapsed');
            if (saved === 'true') state.dashCollapsed = true;

            render();
            initCharts();
        } catch(e) {
            console.error('Dashboard load error:', e);
            document.getElementById('mainLoader').innerHTML = '<span style="color:#FF4D4F;">Error loading dashboard data. Please refresh.</span>';
        }
    }

    function render() {
        const root = document.getElementById('debtorDashRoot');
        const s = state.summary;
        const year = new Date().getFullYear();

        // Alerts
        let alertsHTML = '';
        if (s && s.overduePercent > 50) {
            alertsHTML = `<div class="alert-section">
                <div class="alert-card critical">
                    <i class="fas fa-exclamation-triangle"></i>
                    <span><strong>High Risk:</strong> ${s.overduePercent}% of total receivables are overdue. Immediate collection action recommended.</span>
                </div>
            </div>`;
        } else if (s && s.overduePercent > 30) {
            alertsHTML = `<div class="alert-section">
                <div class="alert-card">
                    <i class="fas fa-exclamation-circle"></i>
                    <span><strong>Attention:</strong> ${s.overduePercent}% of receivables are overdue. Review aging accounts.</span>
                </div>
            </div>`;
        }

        root.innerHTML = `
            <!-- HEADER -->
            <div class="debtor-hdr">
                <div class="breadcrumbs"><a href="index.php">Home</a> / <a href="DebtorsDashboard.php">Debtors</a> / Dashboard</div>
                <h1><i class="fas fa-chart-line" style="margin-right:10px;"></i>Accounts Receivable Dashboard</h1>
                <div class="hdr-meta">
                    <div style="font-size:16px;font-weight:600;">YTD ${year}</div>
                    <div>DSO: <strong>${s ? s.dso : '–'} days</strong></div>
                </div>
            </div>

            ${alertsHTML}

            <!-- DASHBOARD TOGGLE -->
            <div class="dash-toggle ${state.dashCollapsed ? 'collapsed' : ''}" id="dashToggle">
                <i class="fas fa-chevron-down"></i>
                <span>Dashboard Analytics</span>
            </div>

            <!-- DASHBOARD PANEL -->
            <div class="dash-panel ${state.dashCollapsed ? 'collapsed' : ''}" id="dashPanel" style="max-height:${state.dashCollapsed ? '0' : '4000px'};">

                <!-- KPI CARDS -->
                <div class="kpi-grid">
                    <div class="kpi-card">
                        <div class="kpi-icon teal"><i class="fas fa-file-invoice-dollar"></i></div>
                        <div class="kpi-label">YTD Sales</div>
                        <div class="kpi-value">${s ? FMT(s.ytdSales) : '...'}</div>
                        <div class="kpi-sub">Invoiced this year</div>
                    </div>
                    <div class="kpi-card info" style="border-left-color:#1890FF;">
                        <div class="kpi-icon blue"><i class="fas fa-hand-holding-usd"></i></div>
                        <div class="kpi-label">Total Receivable</div>
                        <div class="kpi-value">${s ? FMT(s.totalAR) : '...'}</div>
                        <div class="kpi-sub">${s ? s.activeDebtors : '–'} active accounts</div>
                    </div>
                    <div class="kpi-card danger">
                        <div class="kpi-icon red"><i class="fas fa-exclamation-circle"></i></div>
                        <div class="kpi-label">Overdue Receivable</div>
                        <div class="kpi-value">${s ? FMT(s.overdueAR) : '...'}</div>
                        <div class="kpi-sub"><span class="down">${s ? s.overduePercent : '–'}%</span> of total AR</div>
                    </div>
                    <div class="kpi-card success">
                        <div class="kpi-icon green"><i class="fas fa-money-bill-wave"></i></div>
                        <div class="kpi-label">YTD Collections</div>
                        <div class="kpi-value">${s ? FMT(s.ytdReceipts) : '...'}</div>
                        <div class="kpi-sub">Payments received</div>
                    </div>
                </div>

                <!-- AGING BAR VISUALIZATION -->
                <div style="padding:0 20px 16px;">
                    <div class="chart-card">
                        <h3><i class="fas fa-layer-group"></i>Aging Distribution</h3>
                        ${renderAgingBar()}
                        <div class="aging-legend">
                            <div class="leg-item"><span class="dot" style="background:#52C41A;"></span>Current</div>
                            <div class="leg-item"><span class="dot" style="background:#FAAD14;"></span>30 Days</div>
                            <div class="leg-item"><span class="dot" style="background:#FA8C16;"></span>60 Days</div>
                            <div class="leg-item"><span class="dot" style="background:#F5222D;"></span>90 Days</div>
                            <div class="leg-item"><span class="dot" style="background:#CF1322;"></span>120 Days</div>
                            <div class="leg-item"><span class="dot" style="background:#A8071A;"></span>150 Days</div>
                            <div class="leg-item"><span class="dot" style="background:#5C0011;"></span>180+ Days</div>
                        </div>
                    </div>
                </div>

                <!-- CHARTS ROW 1 -->
                <div class="chart-grid">
                    <div class="chart-card">
                        <h3><i class="fas fa-chart-bar"></i>Monthly Receivable vs Overdue (${year})</h3>
                        <canvas id="chartMonthly"></canvas>
                    </div>
                    <div class="chart-card">
                        <h3><i class="fas fa-chart-pie"></i>Aging Buckets Breakdown</h3>
                        <canvas id="chartAgingPie"></canvas>
                    </div>
                </div>

                <!-- CHARTS ROW 2 -->
                <div class="chart-grid">
                    <div class="chart-card">
                        <h3><i class="fas fa-exchange-alt"></i>Collection Performance (Last 6 Months)</h3>
                        <canvas id="chartCollection"></canvas>
                    </div>
                    <div class="chart-card">
                        <h3><i class="fas fa-building"></i>Department Breakdown</h3>
                        <canvas id="chartDept"></canvas>
                    </div>
                </div>

                <!-- TOP DEBTORS -->
                <div class="top-debtors-grid">
                    <div class="chart-card">
                        <h3><i class="fas fa-trophy"></i>Top 10 Debtors by Outstanding Balance</h3>
                        ${renderTopDebtors()}
                    </div>
                    <div class="chart-card">
                        <h3><i class="fas fa-info-circle"></i>Quick Summary</h3>
                        <div style="font-size:13px;line-height:2;">
                            <div><strong>Current AR:</strong> ${s ? FMTFULL(s.currentAR) : '–'}</div>
                            <div><strong>Overdue AR:</strong> <span style="color:#FF4D4F;">${s ? FMTFULL(s.overdueAR) : '–'}</span></div>
                            <div><strong>Overdue %:</strong> <span style="color:#FF4D4F;">${s ? s.overduePercent : '–'}%</span></div>
                            <div><strong>DSO:</strong> ${s ? s.dso : '–'} days</div>
                            <div><strong>Active Accounts:</strong> ${s ? s.activeDebtors : '–'}</div>
                            <div><strong>YTD Sales:</strong> ${s ? FMTFULL(s.ytdSales) : '–'}</div>
                            <div><strong>YTD Collections:</strong> ${s ? FMTFULL(s.ytdReceipts) : '–'}</div>
                            <div><strong>Collection Rate:</strong> ${s && s.ytdSales > 0 ? Math.round((s.ytdReceipts / s.ytdSales)*100) : '–'}%</div>
                        </div>
                    </div>
                </div>

            </div><!-- end dash-panel -->

            <!-- FULL AGING REPORT TABLE -->
            <div class="aging-section">
                <div class="chart-card" style="padding:0;">
                    <h3 style="padding:18px 20px 14px; margin:0; border-radius:12px 12px 0 0;">
                        <i class="fas fa-table"></i>Aging Report
                        <span style="font-weight:400;font-size:12px;color:#8C8C8C;margin-left:8px;">${state.agingReport.length} accounts</span>
                    </h3>

                    <!-- TOOLBAR -->
                    <div class="aging-toolbar" style="padding:0 20px;">
                        <input type="text" id="agingSearch" placeholder="Search by name, account, department..."
                               value="${state.search}">
                        <select id="deptFilterSelect">
                            <option value="">All Departments</option>
                            ${getDeptOptions()}
                        </select>
                        <button class="btn-action primary" id="btnPrint" disabled><i class="fas fa-print"></i> Print Statement</button>
                        <button class="btn-action outline" id="btnPrintInv" disabled><i class="fas fa-file-alt"></i> Print + Invoices</button>
                        <button class="btn-action success" id="btnEmail" disabled><i class="fas fa-envelope"></i> Email Statement</button>
                        <button class="btn-action warning" id="btnOutTrans" disabled><i class="fas fa-list"></i> Outstanding Trans</button>
                        <button class="btn-action outline" id="btnAllTrans" disabled><i class="fas fa-list-alt"></i> All Trans</button>
                        <button class="btn-action danger" id="btnPrintAll"><i class="fas fa-print"></i> Print All</button>
                        <button class="btn-action outline" id="btnExportCSV"><i class="fas fa-file-csv"></i> Export CSV</button>
                    </div>

                    <!-- TABLE -->
                    <div class="ar-table-wrap" style="margin:14px 20px 0;">
                        ${renderAgingTable()}
                    </div>

                    <!-- PAGINATION -->
                    <div class="table-footer" style="margin:0 20px;">
                        ${renderPagination()}
                    </div>
                </div>
            </div>

            <!-- MODAL -->
            ${state.modal ? renderModal() : ''}
        `;

        bindEvents();
    }

    function renderAgingBar() {
        const b = state.agingBuckets;
        if (!b) return '<div style="color:#8C8C8C;font-size:13px;">Loading...</div>';
        const vals = [
            parseFloat(b.current_bucket)||0, parseFloat(b.days_30)||0, parseFloat(b.days_60)||0,
            parseFloat(b.days_90)||0, parseFloat(b.days_120)||0, parseFloat(b.days_150)||0, parseFloat(b.days_180)||0
        ];
        const total = vals.reduce((a,c) => a + Math.max(c,0), 0);
        if (total <= 0) return '<div style="color:#8C8C8C;">No aging data</div>';
        const pcts = vals.map(v => Math.max(v,0)/total*100);
        const classes = ['s-current','s-30','s-60','s-90','s-120','s-150','s-180'];
        const labels = ['Current','30 Days','60 Days','90 Days','120 Days','150 Days','180+ Days'];

        let bar = '<div class="aging-bar">';
        pcts.forEach((p,i) => {
            if (p > 0) bar += `<div class="seg ${classes[i]}" style="width:${p}%" title="${labels[i]}: ${FMTFULL(vals[i])} (${p.toFixed(1)}%)"></div>`;
        });
        bar += '</div>';

        // Amount labels below
        bar += '<div style="display:flex;flex-wrap:wrap;gap:16px;margin-top:10px;font-size:12px;">';
        vals.forEach((v,i) => {
            if (v > 0) bar += `<span><strong>${labels[i]}:</strong> ${FMTFULL(v)}</span>`;
        });
        bar += '</div>';
        return bar;
    }

    function renderTopDebtors() {
        if (!state.topDebtors || state.topDebtors.length === 0) return '<div style="color:#8C8C8C;">No data</div>';
        return state.topDebtors.map((d, i) => `
            <div class="debtor-rank">
                <div class="rank-num ${i < 3 ? 'hot' : ''}">${i+1}</div>
                <div class="name">
                    ${d.name}
                    ${d.overdue > 0 ? `<div class="overdue-tag">Overdue: ${FMTFULL(d.overdue)}</div>` : ''}
                </div>
                <div class="amount">${FMTFULL(d.balance)}</div>
            </div>
        `).join('');
    }

    function getFilteredData() {
        let data = state.agingReport || [];
        const q = state.search.toLowerCase();
        if (q) {
            data = data.filter(r =>
                (r.name||'').toLowerCase().includes(q) ||
                (r.account_number||'').toLowerCase().includes(q) ||
                (r.departmentname||'').toLowerCase().includes(q) ||
                String(r.debtorno||'').includes(q)
            );
        }
        if (state.deptFilter) {
            data = data.filter(r => (r.departmentname||'') === state.deptFilter);
        }
        // Sort
        const col = state.sortCol;
        const dir = state.sortDir === 'asc' ? 1 : -1;
        data.sort((a, b) => {
            let va = a[col], vb = b[col];
            if (typeof va === 'string') return va.localeCompare(vb) * dir;
            return ((va||0) - (vb||0)) * dir;
        });
        return data;
    }

    function getDeptOptions() {
        if (!state.agingReport) return '';
        const depts = [...new Set(state.agingReport.map(r => r.departmentname).filter(Boolean))].sort();
        return depts.map(d => `<option value="${d}" ${state.deptFilter === d ? 'selected' : ''}>${d}</option>`).join('');
    }

    function renderAgingTable() {
        const data = getFilteredData();
        const start = (state.page - 1) * state.pageSize;
        const pageData = data.slice(start, start + state.pageSize);

        const cols = [
            {key:'debtorno', label:'Debtor#', cls:''},
            {key:'name', label:'Customer Name', cls:''},
            {key:'account_number', label:'Account#', cls:''},
            {key:'departmentname', label:'Department', cls:''},
            {key:'total_balance', label:'Total Balance', cls:'num'},
            {key:'current', label:'Current', cls:'num'},
            {key:'30days', label:'30 Days', cls:'num'},
            {key:'60days', label:'60 Days', cls:'num'},
            {key:'90days', label:'90 Days', cls:'num'},
            {key:'120days', label:'120 Days', cls:'num'},
            {key:'150days', label:'150 Days', cls:'num'},
            {key:'180daysplus', label:'180+ Days', cls:'num'}
        ];

        const arrow = (key) => {
            if (state.sortCol !== key) return '<span class="sort-arrow">⇅</span>';
            return `<span class="sort-arrow">${state.sortDir === 'asc' ? '▲' : '▼'}</span>`;
        };

        let thead = '<thead><tr>';
        cols.forEach(c => {
            thead += `<th data-sort="${c.key}">${c.label}${arrow(c.key)}</th>`;
        });
        thead += '</tr></thead>';

        let tbody = '<tbody>';
        if (pageData.length === 0) {
            tbody += `<tr><td colspan="12" style="text-align:center;padding:30px;color:#8C8C8C;">No matching records found</td></tr>`;
        } else {
            pageData.forEach((r, idx) => {
                const globalIdx = start + idx;
                const isSelected = state.selectedRow === globalIdx;
                const overdueAmount = (parseFloat(r['90days'])||0) + (parseFloat(r['120days'])||0) + (parseFloat(r['150days'])||0) + (parseFloat(r['180daysplus'])||0);
                tbody += `<tr class="${isSelected ? 'selected' : ''}" data-idx="${globalIdx}">
                    <td>${r.debtorno||''}</td>
                    <td>${r.name||''}</td>
                    <td>${r.account_number||''}</td>
                    <td>${r.departmentname||''}</td>
                    <td class="num" style="font-weight:600;">${FMTFULL(r.total_balance)}</td>
                    <td class="num">${FMTFULL(r.current)}</td>
                    <td class="num">${formatAgingCell(r['30days'])}</td>
                    <td class="num">${formatAgingCell(r['60days'])}</td>
                    <td class="num ${parseFloat(r['90days'])>0?'overdue-cell':''}">${formatAgingCell(r['90days'])}</td>
                    <td class="num ${parseFloat(r['120days'])>0?'overdue-cell':''}">${formatAgingCell(r['120days'])}</td>
                    <td class="num ${parseFloat(r['150days'])>0?'overdue-cell':''}">${formatAgingCell(r['150days'])}</td>
                    <td class="num ${parseFloat(r['180daysplus'])>0?'overdue-cell':''}">${formatAgingCell(r['180daysplus'])}</td>
                </tr>`;
            });
        }
        tbody += '</tbody>';

        // Totals row
        let totals = '<tfoot><tr style="background:#F0FDFE;font-weight:700;">';
        totals += '<td colspan="4" style="padding:10px 14px;">TOTALS</td>';
        const numCols = ['total_balance','current','30days','60days','90days','120days','150days','180daysplus'];
        numCols.forEach(c => {
            const sum = data.reduce((a, r) => a + (parseFloat(r[c])||0), 0);
            totals += `<td class="num" style="padding:10px 14px;">${FMTFULL(sum)}</td>`;
        });
        totals += '</tr></tfoot>';

        return `<table class="ar-table">${thead}${tbody}${totals}</table>`;
    }

    function formatAgingCell(val) {
        const n = parseFloat(val) || 0;
        if (n === 0) return '<span style="color:#D9D9D9;">-</span>';
        return FMTFULL(n);
    }

    function renderPagination() {
        const data = getFilteredData();
        const totalPages = Math.ceil(data.length / state.pageSize);
        const showing = Math.min(state.page * state.pageSize, data.length);
        const from = data.length > 0 ? ((state.page-1)*state.pageSize + 1) : 0;

        let pagBtns = '';
        const maxBtns = 7;
        let startP = Math.max(1, state.page - 3);
        let endP = Math.min(totalPages, startP + maxBtns - 1);
        if (endP - startP < maxBtns - 1) startP = Math.max(1, endP - maxBtns + 1);

        pagBtns += `<button data-page="${state.page-1}" ${state.page<=1?'disabled':''}>‹</button>`;
        for (let p = startP; p <= endP; p++) {
            pagBtns += `<button data-page="${p}" class="${p===state.page?'active':''}">${p}</button>`;
        }
        pagBtns += `<button data-page="${state.page+1}" ${state.page>=totalPages?'disabled':''}>›</button>`;

        return `
            <span>Showing ${from}–${showing} of ${data.length} accounts</span>
            <div class="pagination">${pagBtns}</div>
        `;
    }

    function renderModal() {
        if (!state.modal) return '';
        const title = state.modal === 'outstanding' ? 'Outstanding Transactions' : 'All Transactions';
        let body = '';
        if (state.modalLoading) {
            body = '<div class="loading-wrap"><div class="spinner"></div> Loading...</div>';
        } else if (state.modalData && state.modalData.length > 0) {
            body = `<table class="ar-table" style="font-size:12px;">
                <thead><tr>
                    <th>Type</th><th>No</th><th>Date</th><th style="text-align:right;">Total</th><th style="text-align:right;">Outstanding</th>
                </tr></thead><tbody>`;
            state.modalData.forEach(r => {
                body += `<tr>
                    <td>${r.trans_type}</td><td>${r.trans_no}</td><td>${r.trans_date}</td>
                    <td class="num">${FMTFULL(r.total)}</td>
                    <td class="num" style="${parseFloat(r.outstanding)>0?'color:#FF4D4F;font-weight:600;':''}">${FMTFULL(r.outstanding)}</td>
                </tr>`;
            });
            body += '</tbody></table>';
        } else {
            body = '<div style="text-align:center;padding:30px;color:#8C8C8C;">No transactions found.</div>';
        }

        return `<div class="modal-overlay" id="modalOverlay">
            <div class="modal-box">
                <div class="modal-header">
                    <h3><i class="fas fa-list" style="margin-right:8px;"></i>${title}</h3>
                    <button class="modal-close" id="modalClose">×</button>
                </div>
                <div class="modal-body">${body}</div>
            </div>
        </div>`;
    }

    function getSelectedRecord() {
        if (state.selectedRow === null) return null;
        const data = getFilteredData();
        return data[state.selectedRow] || null;
    }

    function bindEvents() {
        // Dashboard toggle
        const toggle = document.getElementById('dashToggle');
        if (toggle) toggle.onclick = () => {
            state.dashCollapsed = !state.dashCollapsed;
            localStorage.setItem('debtorDashCollapsed', state.dashCollapsed);
            render(); initCharts();
        };

        // Search
        const searchInput = document.getElementById('agingSearch');
        if (searchInput) {
            searchInput.oninput = (e) => { state.search = e.target.value; state.page = 1; state.selectedRow = null; render(); initCharts(); };
            searchInput.focus();
            searchInput.setSelectionRange(searchInput.value.length, searchInput.value.length);
        }

        // Dept filter
        const deptSel = document.getElementById('deptFilterSelect');
        if (deptSel) deptSel.onchange = (e) => { state.deptFilter = e.target.value; state.page = 1; state.selectedRow = null; render(); initCharts(); };

        // Table row selection
        document.querySelectorAll('.ar-table tbody tr[data-idx]').forEach(tr => {
            tr.onclick = () => {
                const idx = parseInt(tr.dataset.idx);
                state.selectedRow = state.selectedRow === idx ? null : idx;
                render(); initCharts();
            };
        });

        // Sort
        document.querySelectorAll('.ar-table thead th[data-sort]').forEach(th => {
            th.onclick = (e) => {
                e.stopPropagation();
                const col = th.dataset.sort;
                if (state.sortCol === col) state.sortDir = state.sortDir === 'asc' ? 'desc' : 'asc';
                else { state.sortCol = col; state.sortDir = col === 'name' || col === 'departmentname' ? 'asc' : 'desc'; }
                state.page = 1;
                render(); initCharts();
            };
        });

        // Pagination
        document.querySelectorAll('.pagination button[data-page]').forEach(btn => {
            btn.onclick = () => {
                const p = parseInt(btn.dataset.page);
                if (p >= 1 && p <= Math.ceil(getFilteredData().length / state.pageSize)) {
                    state.page = p;
                    render(); initCharts();
                }
            };
        });

        // Action buttons
        const sel = getSelectedRecord();
        const hasSelection = sel !== null;

        ['btnPrint','btnPrintInv','btnEmail','btnOutTrans','btnAllTrans'].forEach(id => {
            const btn = document.getElementById(id);
            if (btn) btn.disabled = !hasSelection;
        });

        const btnPrint = document.getElementById('btnPrint');
        if (btnPrint) btnPrint.onclick = () => {
            const r = getSelectedRecord();
            if (r) window.location.href = `PrintStatements.php?FromCust=${r.debtorno}&accountnumber=${r.account_number}&department=${r.departmentname||''}`;
        };

        const btnPrintInv = document.getElementById('btnPrintInv');
        if (btnPrintInv) btnPrintInv.onclick = () => {
            const r = getSelectedRecord();
            if (r) window.location.href = `PrintStatementsInvoices.php?FromCust=${r.debtorno}&accountnumber=${r.account_number}&department=${r.departmentname||''}`;
        };

        const btnPrintAll = document.getElementById('btnPrintAll');
        if (btnPrintAll) btnPrintAll.onclick = () => { window.location.href = 'PrintAllStatements.php'; };

        const btnEmail = document.getElementById('btnEmail');
        if (btnEmail) btnEmail.onclick = () => {
            const r = getSelectedRecord();
            if (r) {
                fetch('debtors/EmailStatementsSingle.php', {
                    method: 'POST',
                    headers: {'Content-Type':'application/x-www-form-urlencoded'},
                    body: 'FromCust=' + encodeURIComponent(r.account_number)
                });
                alert('Statement email sent for ' + r.name);
            }
        };

        const btnOutTrans = document.getElementById('btnOutTrans');
        if (btnOutTrans) btnOutTrans.onclick = () => loadTransactions('outstanding');

        const btnAllTrans = document.getElementById('btnAllTrans');
        if (btnAllTrans) btnAllTrans.onclick = () => loadTransactions('all');

        // Export CSV
        const btnCSV = document.getElementById('btnExportCSV');
        if (btnCSV) btnCSV.onclick = exportCSV;

        // Modal close
        const modalOverlay = document.getElementById('modalOverlay');
        if (modalOverlay) modalOverlay.onclick = (e) => {
            if (e.target === modalOverlay) { state.modal = null; state.modalData = null; render(); initCharts(); }
        };
        const modalClose = document.getElementById('modalClose');
        if (modalClose) modalClose.onclick = () => { state.modal = null; state.modalData = null; render(); initCharts(); };
    }

    async function loadTransactions(type) {
        const r = getSelectedRecord();
        if (!r) return;
        state.modal = type;
        state.modalLoading = true;
        state.modalData = null;
        render(); initCharts();

        const apiType = type === 'outstanding' ? 'outstanding_trans' : 'all_trans';
        try {
            const res = await fetch(API + apiType + '&account=' + encodeURIComponent(r.account_number));
            state.modalData = await res.json();
        } catch(e) { state.modalData = []; }
        state.modalLoading = false;
        render(); initCharts();
    }

    function exportCSV() {
        const data = getFilteredData();
        const headers = ['Debtor No','Name','Account Number','Department','Total Balance','Current','30 Days','60 Days','90 Days','120 Days','150 Days','180+ Days'];
        const keys = ['debtorno','name','account_number','departmentname','total_balance','current','30days','60days','90days','120days','150days','180daysplus'];
        let csv = headers.join(',') + '\n';
        data.forEach(r => {
            csv += keys.map(k => {
                let v = r[k] == null ? '' : String(r[k]);
                if (v.includes(',') || v.includes('"')) v = '"' + v.replace(/"/g,'""') + '"';
                return v;
            }).join(',') + '\n';
        });
        const blob = new Blob([csv], {type:'text/csv'});
        const a = document.createElement('a');
        a.href = URL.createObjectURL(blob);
        a.download = 'aging_report_' + new Date().toISOString().slice(0,10) + '.csv';
        a.click();
    }

    // ─── CHARTS ───
    let charts = {};
    function initCharts() {
        if (state.dashCollapsed) return;

        // Destroy existing charts
        Object.values(charts).forEach(c => { if (c) c.destroy(); });
        charts = {};

        // Monthly Receivable vs Overdue
        const ctxM = document.getElementById('chartMonthly');
        if (ctxM && state.monthlyTrend) {
            charts.monthly = new Chart(ctxM, {
                type: 'bar',
                data: {
                    labels: state.monthlyTrend.map(r=>r.month),
                    datasets: [
                        { label: 'Receivable', data: state.monthlyTrend.map(r=>r.receivable), backgroundColor: 'rgba(42,171,179,0.7)', borderRadius: 4 },
                        { label: 'Overdue', data: state.monthlyTrend.map(r=>r.overdue), backgroundColor: 'rgba(255,77,79,0.7)', borderRadius: 4 }
                    ]
                },
                options: {
                    responsive: true, maintainAspectRatio: true,
                    plugins: { legend: { position: 'top', labels: { font: { family: 'Poppins', size: 12 } } } },
                    scales: {
                        y: { beginAtZero: true, ticks: { callback: v => FMT(v), font: { family: 'Poppins', size: 11 } } },
                        x: { ticks: { font: { family: 'Poppins', size: 11 } } }
                    }
                }
            });
        }

        // Aging Pie
        const ctxA = document.getElementById('chartAgingPie');
        if (ctxA && state.agingBuckets) {
            const b = state.agingBuckets;
            const vals = [b.current_bucket, b.days_30, b.days_60, b.days_90, b.days_120, b.days_150, b.days_180].map(v=>Math.max(parseFloat(v)||0, 0));
            charts.agingPie = new Chart(ctxA, {
                type: 'doughnut',
                data: {
                    labels: ['Current','30 Days','60 Days','90 Days','120 Days','150 Days','180+ Days'],
                    datasets: [{ data: vals, backgroundColor: ['#52C41A','#FAAD14','#FA8C16','#F5222D','#CF1322','#A8071A','#5C0011'], borderWidth: 2, borderColor: '#fff' }]
                },
                options: {
                    responsive: true, maintainAspectRatio: true, cutout: '55%',
                    plugins: {
                        legend: { position: 'right', labels: { font: { family: 'Poppins', size: 11 }, padding: 12 } },
                        tooltip: { callbacks: { label: (ctx) => ctx.label + ': ' + FMTFULL(ctx.raw) } }
                    }
                }
            });
        }

        // Collection Performance
        const ctxC = document.getElementById('chartCollection');
        if (ctxC && state.collectionPerf) {
            charts.collection = new Chart(ctxC, {
                type: 'bar',
                data: {
                    labels: state.collectionPerf.map(r=>r.month),
                    datasets: [
                        { label: 'Invoiced', data: state.collectionPerf.map(r=>r.invoiced), backgroundColor: 'rgba(24,144,255,0.7)', borderRadius: 4 },
                        { label: 'Collected', data: state.collectionPerf.map(r=>r.collected), backgroundColor: 'rgba(82,196,26,0.7)', borderRadius: 4 }
                    ]
                },
                options: {
                    responsive: true, maintainAspectRatio: true,
                    plugins: { legend: { position: 'top', labels: { font: { family: 'Poppins', size: 12 } } } },
                    scales: {
                        y: { beginAtZero: true, ticks: { callback: v => FMT(v), font: { family: 'Poppins', size: 11 } } },
                        x: { ticks: { font: { family: 'Poppins', size: 11 } } }
                    }
                }
            });
        }

        // Department Breakdown
        const ctxD = document.getElementById('chartDept');
        if (ctxD && state.deptBreakdown) {
            const deptColors = ['#2AABB3','#1890FF','#722ED1','#EB2F96','#FA8C16','#52C41A','#FAAD14','#13C2C2','#F5222D','#2F54EB'];
            charts.dept = new Chart(ctxD, {
                type: 'doughnut',
                data: {
                    labels: state.deptBreakdown.map(r=>r.department),
                    datasets: [{ data: state.deptBreakdown.map(r=>r.balance), backgroundColor: deptColors.slice(0, state.deptBreakdown.length), borderWidth: 2, borderColor: '#fff' }]
                },
                options: {
                    responsive: true, maintainAspectRatio: true, cutout: '50%',
                    plugins: {
                        legend: { position: 'right', labels: { font: { family: 'Poppins', size: 11 }, padding: 10 } },
                        tooltip: { callbacks: { label: (ctx) => ctx.label + ': ' + FMTFULL(ctx.raw) } }
                    }
                }
            });
        }
    }

    // ─── INIT ───
    fetchAll();
})();
</script>

<?php include('includes/footer.inc'); ?>
