<!DOCTYPE html>
<html lang="bn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ইউনিভার্সাল ড্যাশবোর্ড - বিডিআরআইএস</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
    <link href="https://fonts.maateen.me/solaiman-lipi/font.css" rel="stylesheet">
    <style>
        body { font-family: SolaimanLipi, sans-serif; }
        .required-field::after { content: " *"; color: red; }
        .widget-holder { margin-bottom: 20px; }
        .widget-bg { background: #fff; padding: 25px; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
        .form-group label { font-weight: 600; color: #333; }
        #resultTable td .material-icons { font-size: 20px; vertical-align: middle; cursor: pointer; }
        #resultTable td a { margin-right: 8px; text-decoration: none; }
        .summary-card { cursor: pointer; transition: transform 0.2s; }
        .summary-card:hover { transform: scale(1.05); }
        .action-icons a { display: inline-flex; align-items: center; justify-content: center; margin: 0 3px; width: 32px; height: 32px; border-radius: 8px; border: 1px solid #dee2e6; background: #f8f9fa; transition: 0.15s; }
        .action-icons a:hover { transform: translateY(-1px); box-shadow: 0 3px 10px rgba(0,0,0,0.08); text-decoration: none; }
        .action-icons .material-icons { font-size: 20px; color: currentColor; }
        .action-icons a.action-view { background: #fffbe6; border-color: #ffe58f; color: #d48806; }
        .action-icons a.action-print { background: #f1f3f5; border-color: #dee2e6; color: #495057; }
        .action-icons a.action-docs { background: #e7f5ff; border-color: #a5d8ff; color: #1971c2; }
        .action-icons a.action-cert { background: #edf2ff; border-color: #bac8ff; color: #3b5bdb; }
        .action-icons a.action-17 { background: #e3fafc; border-color: #99e9f2; color: #0b7285; }
        .action-icons a.action-receive { background: #ebfbee; border-color: #b2f2bb; color: #2b8a3e; }
        .action-icons a.action-register { background: #e6fcf5; border-color: #96f2d7; color: #087f5b; }
        .action-icons a.action-dup { background: #f3f0ff; border-color: #d0bfff; color: #6741d9; }
        .action-icons a.action-approve { background: #fff3bf; border-color: #ffec99; color: #e67700; }
        .action-icons a.action-reject { background: #ffe3e3; border-color: #ffc9c9; color: #c92a2a; }
        .action-icons a.action-correct { background: #e5dbff; border-color: #d0bfff; color: #5f3dc4; }

        /* টোকেন স্ট্যাটাস বার */
        #tokenStatusBar { font-size: 12px; padding: 6px 14px; border-radius: 6px; margin-bottom: 10px; display: none; }
        #tokenStatusBar.ok  { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
        #tokenStatusBar.warn { background: #fff3cd; color: #856404; border: 1px solid #ffeeba; }
        #tokenStatusBar.err  { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }

        /* ভিউ মডাল ডিজাইন */
        .view-modal-dialog { max-width: 1320px; width: calc(100vw - 40px); margin: 0 auto; }
        .view-header-custom { background: linear-gradient(135deg, #1a5e1d, #0d3b0f); color: white; padding: 15px 20px; border-radius: 8px 8px 0 0; }
        .view-header-custom h4 { margin: 0; font-size: 16px; }
        .view-header-custom .close { color: white; opacity: 0.8; }
        .view-body-custom { padding: 16px; max-height: 82vh; overflow-y: auto; background: #f3f5f7; }
        .info-table-custom { width: 100%; border-collapse: collapse; margin-bottom: 14px; table-layout: fixed; }
        .info-table-custom tr { border-bottom: 1px solid #e0e8e0; }
        .info-table-custom th { width: 22%; background: #f9fbf9; padding: 4px 10px; text-align: left; font-weight: bold; color: #1a5e1d; font-size: 15.5px; line-height: 1.34; vertical-align: top; word-break: break-word; }
        .info-table-custom td { width: 78%; padding: 4px 14px; text-align: left; font-size: 15.5px; color: #2c3e2c; word-break: break-word; line-height: 1.34; vertical-align: top; }
        .info-table-custom th, .info-table-custom td { border: 1px solid #d8e6d8; }
        .info-table-custom tr:nth-child(even) th, .info-table-custom tr:nth-child(even) td { background: #fcfdfc; }
        .section-title-custom { font-size: 16px; font-weight: bold; color: #1a5e1d; margin: 20px 0 12px 0; padding-bottom: 6px; border-bottom: 2px solid #e0e8e0; display: flex; align-items: center; gap: 8px; }
        .status-badge-custom { display: inline-block; padding: 4px 12px; border-radius: 30px; font-size: 11px; font-weight: bold; }
        .status-registered { background: #28a745; color: white; }
        .status-applied { background: #ffc107; color: #212529; }
        .status-duplicate { background: #6f42c1; color: white; }
        .status-other { background: #6c757d; color: white; }
        .docs-grid-custom { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin-top: 10px; margin-bottom: 16px; }
        .doc-card-custom { border: 1px solid #ddd; border-radius: 12px; padding: 12px; text-align: center; transition: 0.2s; background: white; display: flex; flex-direction: column; }
        .doc-card-custom:hover { border-color: #1a5e1d; transform: translateY(-3px); box-shadow: 0 5px 15px rgba(0,0,0,0.1); }
        .doc-card-custom img { width: 100%; height: 240px; object-fit: contain; background: #f5f5f5; border-radius: 8px; margin-bottom: 0; flex: 1 1 auto; }
        .doc-card-custom .doc-type-custom { display: none !important; }
        .view-footer-custom { padding: 15px 20px; background: #f8faf8; border-top: 1px solid #e0e8e0; text-align: center; border-radius: 0 0 8px 8px; }
        .btn-print-custom { background: linear-gradient(135deg, #1a5e1d, #0d3b0f); color: white; border: none; padding: 8px 30px; border-radius: 40px; font-weight: bold; margin: 0 5px; cursor: pointer; }
        .brn17-badge { font-size: 1.1em; letter-spacing: 2px; font-weight: bold; color: #155724; background: #d4edda; padding: 4px 12px; border-radius: 6px; display: inline-block; margin-top: 4px; }
        .doc-page-wrap { width: 100%; max-width: 850px; margin: 20px auto; background: #fff; border: 1px solid #e0e8e0; border-radius: 10px; padding: 24px 32px; box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
        .info-section { break-after: page; page-break-after: always; }
        .docs-section { break-before: page; page-break-before: always; }
        .doc-actions-custom { display: flex; justify-content: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
        .doc-download-text { margin-top: 8px; font-size: 12px; color: #adb5bd; }
        @media (max-width: 768px) { .docs-grid-custom { grid-template-columns: 1fr; } .doc-page-wrap { padding: 12px; border-radius: 0; border: none; box-shadow: none; } .view-modal-dialog { width: calc(100vw - 16px); } }
        @media print { .no-print { display: none !important; } .view-body-custom { padding: 0; background: #fff; } .doc-card-custom { break-inside: avoid; } .doc-page-wrap { max-width: 100%; padding: 0; border: none; border-radius: 0; box-shadow: none; } }
    </style>
</head>
<body class="bg-light">

<div class="container py-4">
    <div id="warning-message-div" class="alert alert-warning alert-dismissible fade show" role="alert" style="display: none">
        <strong>সতর্কীকরণ! </strong> <span id="warning-message-span"></span>
        <button type="button" class="close" data-dismiss="alert">&times;</button>
    </div>

    <!-- ===== টোকেন স্ট্যাটাস বার ===== -->
    <div id="tokenStatusBar"></div>

    <div class="row">
        <div class="col-md-12 widget-holder">
            <div class="widget-bg">

                <!-- ===== সেশন/টোকেন কনফিগ প্যানেল ===== -->
                <div class="card mb-3 border-warning" id="sessionConfigPanel">
                    <div class="card-header bg-warning text-dark d-flex justify-content-between align-items-center py-2"
                         style="cursor:pointer"
                         onclick="$('#sessionConfigBody').slideToggle(); var ic=$('#sessionToggleIcon'); ic.text(ic.text()=='expand_less'?'expand_more':'expand_less')">
                        <span>
                            <i class="material-icons" style="vertical-align:middle;font-size:18px">vpn_key</i>
                            <strong> সেশন / টোকেন কনফিগারেশন</strong>
                            <small class="ml-2 text-dark">(পেজ লোডে BDRIS থেকে অটো নেওয়া হয়)</small>
                        </span>
                        <i class="material-icons" id="sessionToggleIcon">expand_more</i>
                    </div>
                    <div class="card-body py-2" id="sessionConfigBody" style="display:none">
                        <div class="row">
                            <div class="col-md-6">
                                <div class="form-group mb-2">
                                    <label class="small font-weight-bold">X-CSRF-TOKEN
                                        <span class="text-muted font-weight-normal">(bdris.gov.bd থেকে অটো)</span>
                                        <span id="csrfAutoStatus" class="ml-1"></span>
                                    </label>
                                    <div class="input-group input-group-sm">
                                        <input type="text" class="form-control" id="csrfTokenInput" placeholder="অটো লোড হচ্ছে..." autocomplete="off">
                                        <div class="input-group-append">
                                            <button class="btn btn-outline-secondary btn-sm" onclick="autoFetchTokens()" title="BDRIS থেকে রিফ্রেশ করুন">
                                                <i class="material-icons" style="font-size:16px;vertical-align:middle">refresh</i>
                                            </button>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="col-md-6">
                                <div class="form-group mb-2">
                                    <label class="small font-weight-bold">data= টোকেন
                                        <span class="text-muted font-weight-normal">(অফিস সিলেক্টের পর অটো)</span>
                                    </label>
                                    <input type="text" class="form-control form-control-sm" id="unoTokenInput" placeholder="অফিস সিলেক্ট করলে অটো সেট হবে..." autocomplete="off">
                                </div>
                            </div>
                            <div class="col-md-12">
                                <div class="form-group mb-2">
                                    <label class="small font-weight-bold">SESSION Cookie
                                        <span class="text-muted font-weight-normal">(অটো লোড — প্রয়োজনে ম্যানুয়াল পেস্ট করুন)</span>
                                        <span id="cookieAutoStatus" class="ml-1"></span>
                                    </label>
                                    <div class="input-group input-group-sm">
                                        <input type="text" class="form-control" id="sessionCookieInput"
                                               placeholder="SESSION=NTlhYjU0...; srv_id=...; TS00000000076=..."
                                               autocomplete="off">
                                        <div class="input-group-append">
                                            <button class="btn btn-outline-info btn-sm" onclick="autoFetchTokens()" title="BDRIS থেকে অটো ফেচ করুন">
                                                <i class="material-icons" style="font-size:16px;vertical-align:middle">sync</i> অটো ফেচ
                                            </button>
                                        </div>
                                    </div>
                                    <small class="text-muted">
                                        <i class="material-icons" style="font-size:12px;vertical-align:middle">info</i>
                                        অটো ফেচ কাজ না করলে: Browser DevTools → Network → bdris.gov.bd যেকোনো request → Headers → cookie: কপি করুন
                                    </small>
                                </div>
                            </div>
                            <div class="col-md-12 d-flex justify-content-between align-items-center">
                                <div>
                                    <button class="btn btn-sm btn-success" onclick="saveSessionConfig()">
                                        <i class="material-icons" style="font-size:16px;vertical-align:middle">save</i> সেভ করুন
                                    </button>
                                    <button class="btn btn-sm btn-primary ml-1" onclick="autoFetchTokens()">
                                        <i class="material-icons" style="font-size:16px;vertical-align:middle">cloud_download</i> BDRIS থেকে অটো ফেচ
                                    </button>
                                    <button class="btn btn-sm btn-outline-secondary ml-1" onclick="clearSessionConfig()">ক্লিয়ার</button>
                                </div>
                                <span id="sessionSaveStatus" class="small"></span>
                            </div>
                        </div>
                    </div>
                </div>

                <form id="geoSearchForm">
                    <input type="hidden" name="_csrf" id="csrf_token" value="">
                    <div class="row">
                        <div class="col-md-6"><div class="form-group row"><label class="col-md-4 col-form-label required-field">দেশ</label><div class="col-md-8"><select class="form-control geoSelect" data-geo-group="officeAddr" data-geo-order="0"><option value="1">বাংলাদেশ</option></select></div></div></div>
                        <div class="col-md-6"><div class="form-group row"><label class="col-md-4 col-form-label required-field">বিভাগ</label><div class="col-md-8"><select class="form-control geoSelect" id="officeAddrDiv" data-geo-group="officeAddr" data-geo-order="1">
                            <option value="-1">বিভাগ নির্বাচন করুন</option>
                            <option value="5514">রংপুর বিভাগ</option>
                            <option value="5501">ঢাকা বিভাগ</option>
                            <option value="5502">চট্টগ্রাম বিভাগ</option>
                            <option value="5503">রাজশাহী বিভাগ</option>
                            <option value="5504">খুলনা বিভাগ</option>
                            <option value="5505">বরিশাল বিভাগ</option>
                            <option value="5506">সিলেট বিভাগ</option>
                            <option value="5507">ময়মনসিংহ বিভাগ</option>
                        </select></div></div></div>
                        <div class="col-md-6 geo-container" style="display:none"><div class="form-group row"><label class="col-md-4 col-form-label required-field">জেলা</label><div class="col-md-8"><select class="form-control geoSelect" id="officeAddrDist" data-geo-group="officeAddr" data-geo-order="2"><option value="-1">জেলা নির্বাচন করুন</option></select></div></div></div>
                        <div class="col-md-6 geo-container" style="display:none"><div class="form-group row"><label class="col-md-4 col-form-label required-field">উপজেলা</label><div class="col-md-8"><select class="form-control geoSelect" id="officeAddrCityCorpCantOrUpazila" data-geo-group="officeAddr" data-geo-order="3"><option value="-1">উপজেলা নির্বাচন করুন</option></select></div></div></div>
                        <div class="col-md-6 geo-container" style="display:none"><div class="form-group row"><label class="col-md-4 col-form-label required-field">ইউনিয়ন/পৌরসভা</label><div class="col-md-8"><select class="form-control geoSelect" id="officeAddrPaurasavaOrUnion" data-geo-group="officeAddr" data-geo-order="4"><option value="-1">ইউনিয়ন নির্বাচন করুন</option></select></div></div></div>
                        <div class="col-md-6"><div class="form-group row"><label class="col-md-4 col-form-label">সেবা</label><div class="col-md-8"><select class="form-control" id="applicationService"><option value="br">জন্ম নিবন্ধন</option><option value="dr">মৃত্যু নিবন্ধন</option><option value="br_corr">জন্ম সংশোধন</option><option value="dr_corr">মৃত্যু সংশোধন</option><option value="br_cancel">জন্ম সনদ বাতিল</option><option value="dr_cancel">মৃত্যু সনদ বাতিল</option></select></div></div></div>
                        <div class="col-md-6"><div class="form-group row"><label class="col-md-4 col-form-label">স্ট্যাটাস</label><div class="col-md-8"><select class="form-control" id="applicationStatus"><option value="ALL" selected>সবগুলো (All)</option><option value="APPLIED">আবেদনকৃত</option><option value="RECEIVED">গৃহীত</option><option value="APPROVED">অনুমোদিত</option><option value="REGISTERED">রেজিস্টারড</option><option value="REJECTED">বাতিল</option><option value="POSSIBLE_DUPLICATE">সম্ভাব্য ডুপ্লিকেট</option></select></div></div></div>
                        <div class="col-md-12"><div class="form-group row"><label class="col-md-2 col-form-label">সার্চ আবেদন</label><div class="col-md-8"><input type="text" class="form-control" id="applicationSearchValue" placeholder="আবেদন আইডি / নাম / জন্ম তারিখ দিন..."></div><div class="col-md-2"><button type="button" onclick="searchByApplicationId()" class="btn btn-primary btn-sm">সার্চ</button></div></div></div>
                        <input type="hidden" id="officeId" name="officeId">
                        <input type="hidden" id="currentGeoId" value="">
                    </div>
                    <div class="row mt-3"><div class="col-md-12 text-center">
                        <button class="btn btn-info btn-sm px-4" name="searchOfficeButton" id="searchOfficeButton" type="button" disabled>
                            <i class="material-icons" style="vertical-align:middle">search</i> অনুসন্ধান
                        </button>
                    </div></div>
                </form>

                <div class="row mt-4 mb-4" id="summaryContainer" style="display:none">
                    <div class="col-md-2 col-sm-4 mb-2"><div class="card text-center border-primary summary-card" data-status="APPLIED"><div class="card-body p-2"><h6 class="card-title mb-1 small">APPLIED</h6><h4 class="mb-0 text-primary" id="count-APPLIED">0</h4></div></div></div>
                    <div class="col-md-2 col-sm-4 mb-2"><div class="card text-center border-success summary-card" data-status="RECEIVED"><div class="card-body p-2"><h6 class="card-title mb-1 small">RECEIVED</h6><h4 class="mb-0 text-success" id="count-RECEIVED">0</h4></div></div></div>
                    <div class="col-md-2 col-sm-4 mb-2"><div class="card text-center border-warning summary-card" data-status="APPROVED"><div class="card-body p-2"><h6 class="card-title mb-1 small">APPROVED</h6><h4 class="mb-0 text-warning" id="count-APPROVED">0</h4></div></div></div>
                    <div class="col-md-2 col-sm-4 mb-2"><div class="card text-center border-info summary-card" data-status="POSSIBLE_DUPLICATE"><div class="card-body p-2"><h6 class="card-title mb-1 small">POSSIBLE_DUPLICATE</h6><h4 class="mb-0 text-info" id="count-POSSIBLE_DUPLICATE">0</h4></div></div></div>
                    <div class="col-md-2 col-sm-4 mb-2"><div class="card text-center border-secondary summary-card" data-status="REGISTERED"><div class="card-body p-2"><h6 class="card-title mb-1 small">REGISTERED</h6><h4 class="mb-0 text-secondary" id="count-REGISTERED">0</h4></div></div></div>
                    <div class="col-md-2 col-sm-4 mb-2"><div class="card text-center border-danger summary-card" data-status="REJECTED"><div class="card-body p-2"><h6 class="card-title mb-1 small">REJECTED</h6><h4 class="mb-0 text-danger" id="count-REJECTED">0</h4></div></div></div>
                </div>

                <div class="row mt-2" id="resultContainer" style="display:none">
                    <div class="col-md-12">
                        <h5 class="mb-3">আবেদন তালিকা</h5>
                        <div class="table-responsive">
                            <table class="table table-bordered table-striped table-sm" id="resultTable">
                                <thead class="thead-dark">
                                    <tr>
                                        <th style="width:35px">#</th>
                                        <th>আবেদন আইডি / নিবন্ধন নম্বর</th>
                                        <th>আবেদনের তারিখ</th>
                                        <th>জন্ম তারিখ</th>
                                        <th>নাম (বাংলা)</th>
                                        <th>পিতার নাম</th>
                                        <th>মাতার নাম</th>
                                        <th>স্ট্যাটাস</th>
                                        <th>অ্যাকশন</th>
                                    </tr>
                                </thead>
                                <tbody></tbody>
                            </table>
                        </div>
                        <div class="d-flex flex-wrap justify-content-between align-items-center mt-3" id="paginationBar">
                            <div><select class="form-control form-control-sm" id="pageSizeSelect" style="width:80px;"><option value="10">10</option><option value="25">25</option><option value="50" selected>50</option><option value="100">100</option></select></div>
                            <div><button class="btn btn-outline-secondary btn-sm mr-2" id="prevPageBtn">পূর্ববর্তী</button><span id="pageInfo"></span><button class="btn btn-outline-secondary btn-sm ml-2" id="nextPageBtn">পরবর্তী</button></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<!-- ভিউ মডাল -->
<div class="modal fade" id="viewApplicationModal" tabindex="-1" role="dialog">
    <div class="modal-dialog view-modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content">
            <div class="modal-header view-header-custom">
                <h4><i class="material-icons">visibility</i> আবেদনপত্রের বিবরণ</h4>
                <button type="button" class="close" data-dismiss="modal">&times;</button>
            </div>
            <div class="modal-body view-body-custom" id="viewModalBody">
                <div class="text-center p-5"><div class="spinner-border text-success"></div><p>লোড হচ্ছে...</p></div>
            </div>
            <div class="modal-footer view-footer-custom">
                <button class="btn-print-custom" onclick="printCurrentModal()"><i class="material-icons">print</i> প্রিন্ট</button>
                <button class="btn btn-sm btn-outline-secondary" style="border-radius:40px;padding:8px 18px;font-weight:bold;" onclick="openRData()">
                    R Data
                </button>
                <button class="btn-print-custom" style="background:#6c757d;" data-dismiss="modal">বন্ধ</button>
            </div>
        </div>
    </div>
</div>

<!-- Iframe Modal -->
<div class="modal fade" id="iframeModal" tabindex="-1" role="dialog">
    <div class="modal-dialog modal-dialog-centered" style="max-width:95vw;width:95vw;margin:auto;" role="document">
        <div class="modal-content" style="height:90vh;">
            <div class="modal-header" style="background:linear-gradient(135deg,#1a5e1d,#0d3b0f);color:white;padding:10px 20px;">
                <h5 class="modal-title" id="iframeModalLabel">ভিউ</h5>
                <div class="ml-auto d-flex align-items-center">
                    <button class="btn btn-sm btn-light mr-2" onclick="try{var f=document.getElementById('iframeModalFrame');f.contentWindow.focus();f.contentWindow.print();}catch(e){}">
                        <i class="material-icons" style="font-size:18px;vertical-align:middle">print</i> প্রিন্ট
                    </button>
                    <button type="button" class="close" data-dismiss="modal" style="color:white;opacity:1;">&times;</button>
                </div>
            </div>
            <div class="modal-body p-0" style="flex:1;overflow:hidden;">
                <iframe id="iframeModalFrame" src="about:blank" style="width:100%;height:100%;border:none;"></iframe>
            </div>
        </div>
    </div>
</div>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>

<script>
// ============================================================
//  গ্লোবাল স্টেট
// ============================================================
var currentOfficeId = '', currentGeoId = '', lastRows = [];
var listStart = 0, listLength = 50, listTotal = 0;
var lastListStatus = 'ALL', lastSearchValue = '', listDraw = 1, currentViewData = null, currentViewAppId = '', currentViewEncryptedId = '';
var geoDataCache = {};
var detailsCache = {};
var encryptedIdCache = {};
var countsCache = { ts: 0, map: {} };
var countsXhr = null;
var currentModalPrintableHtml = '';

// ============================================================
//  ইউটিলিটি
// ============================================================
function showMessage(msg, type) {
    type = type || 'warning';
    $('#warning-message-span').text(msg);
    $('#warning-message-div').removeClass('alert-warning alert-danger alert-success alert-info')
        .addClass('alert-' + type).fadeIn();
    setTimeout(function(){ $('#warning-message-div').fadeOut(); }, 5000);
}

function esc(s) {
    return String(s == null ? '' : s)
        .replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
        .replace(/"/g,'&quot;').replace(/'/g,'&#39;');
}

function jsq(s) {
    return String(s == null ? '' : s).replace(/\\/g, '\\\\').replace(/'/g, "\\'");
}

function csrfToken()     { return (($('#csrfTokenInput').val()||'').trim())     || (localStorage.getItem('bdris_csrf')||''); }
function dataToken()     { return (($('#unoTokenInput').val()||'').trim())      || (localStorage.getItem('bdris_data_token')||''); }
function sessionCookie() { return (($('#sessionCookieInput').val()||'').trim()) || (localStorage.getItem('bdris_session_cookie')||''); }
function getCurrentService() { return $('#applicationService').val() || 'br'; }
function isCorrectionService() {
    var s = getCurrentService();
    return s === 'br_corr' || s === 'dr_corr';
}
function isCancellationService() {
    var s = getCurrentService();
    return s === 'br_cancel' || s === 'dr_cancel';
}

function buildRequestData(extra) {
    return $.extend({
        csrfToken:     csrfToken(),
        dataToken:     dataToken(),
        sessionCookie: sessionCookie(),
        service:       getCurrentService(),
        geoId:         currentGeoId
    }, extra || {});
}

// ============================================================
//  টোকেন স্ট্যাটাস বার আপডেট
// ============================================================
function updateTokenStatusBar() {
    var csrf   = csrfToken();
    var cookie = sessionCookie();
    var bar    = $('#tokenStatusBar');
    if (csrf && cookie) {
        bar.removeClass('warn err').addClass('ok')
           .html('<i class="material-icons" style="font-size:14px;vertical-align:middle">check_circle</i> সেশন সক্রিয় — CSRF ও Cookie লোড হয়েছে')
           .show();
    } else if (csrf || cookie) {
        bar.removeClass('ok err').addClass('warn')
           .html('<i class="material-icons" style="font-size:14px;vertical-align:middle">warning</i> আংশিক টোকেন — '
               + (!csrf ? 'CSRF Token নেই। ' : '') + (!cookie ? 'Session Cookie নেই।' : '')
               + ' <a href="javascript:void(0)" onclick="autoFetchTokens()">অটো ফেচ করুন</a>')
           .show();
    } else {
        bar.removeClass('ok warn').addClass('err')
           .html('<i class="material-icons" style="font-size:14px;vertical-align:middle">error</i> টোকেন নেই — '
               + '<a href="javascript:void(0)" onclick="autoFetchTokens()">BDRIS থেকে অটো ফেচ করুন</a>'
               + ' অথবা নিচের প্যানেল খুলে ম্যানুয়াল পেস্ট করুন।')
           .show();
    }
}

function autoFetchTokens() {
    $('#sessionSaveStatus').html('<span class="text-warning">এই পেজ থেকে অটো ফেচ বন্ধ রাখা হয়েছে। Session Manager/Extension দিয়ে সেশন কানেক্ট করুন।</span>');
    setTimeout(function(){ $('#sessionSaveStatus').html(''); }, 5000);
    window.location.href = 'session-manager.php';
}

// ============================================================
//  সেশন কনফিগ সেভ / ক্লিয়ার / লোড
// ============================================================
function saveSessionConfig() {
    var csrf   = $('#csrfTokenInput').val().trim();
    var data   = $('#unoTokenInput').val().trim();
    var cookie = $('#sessionCookieInput').val().trim();
    if (csrf)   { localStorage.setItem('bdris_csrf', csrf);           $('#csrf_token').val(csrf); }
    if (data)     localStorage.setItem('bdris_data_token', data);
    if (cookie)   localStorage.setItem('bdris_session_cookie', cookie);
    updateTokenStatusBar();
    $('#sessionSaveStatus').html('<span class="text-success"><i class="material-icons" style="font-size:14px;vertical-align:middle">check_circle</i> সেভ হয়েছে</span>');
    setTimeout(function(){ $('#sessionSaveStatus').html(''); }, 3000);
}

function clearSessionConfig() {
    localStorage.removeItem('bdris_csrf');
    localStorage.removeItem('bdris_data_token');
    localStorage.removeItem('bdris_session_cookie');
    $('#csrfTokenInput,#unoTokenInput,#sessionCookieInput').val('');
    $('#csrf_token').val('');
    updateTokenStatusBar();
    $('#sessionSaveStatus').html('<span class="text-muted">ক্লিয়ার হয়েছে</span>');
    setTimeout(function(){ $('#sessionSaveStatus').html(''); }, 2000);
}

function loadSessionConfig() {
    var csrf   = localStorage.getItem('bdris_csrf')           || '';
    var data   = localStorage.getItem('bdris_data_token')     || '';
    var cookie = localStorage.getItem('bdris_session_cookie') || '';
    if (csrf)   { $('#csrfTokenInput').val(csrf);   $('#csrf_token').val(csrf); }
    if (data)     $('#unoTokenInput').val(data);
    if (cookie)   $('#sessionCookieInput').val(cookie);
    updateTokenStatusBar();
}

function autoLoadLatestSessionFromServer() {
    var now = Date.now();
    var lastTs = parseInt(localStorage.getItem('bdris_last_server_session_ts') || '0', 10) || 0;
    if (lastTs > 0 && (now - lastTs) < 2 * 60 * 1000) return;

    $.ajax({ url: 'api/get-session.php', type: 'GET', dataType: 'json', timeout: 10000, cache: false, data: { _: now } })
    .done(function(res) {
        if (!res || res.ok !== true) return;
        var csrf = (res.csrf_token || res.csrfToken || '').trim();
        var cookie = (res.cookie_string || res.cookieString || '').trim();
        var dataToken = (res.data_token || res.dataToken || '').trim();
        if (!csrf || !cookie) return;
        $('#csrfTokenInput').val(csrf);
        $('#sessionCookieInput').val(cookie);
        localStorage.setItem('bdris_csrf', csrf);
        localStorage.setItem('bdris_session_cookie', cookie);
        if (dataToken) {
            $('#unoTokenInput').val(dataToken);
            localStorage.setItem('bdris_data_token', dataToken);
        }
        localStorage.setItem('bdris_last_server_session_ts', String(Date.now()));
        updateTokenStatusBar();
    })
    .fail(function() {});
}

// ============================================================
//  পেজ লোড — অটো টোকেন ফেচ
// ============================================================
$(document).ready(function() {
    loadSessionConfig();
    updateTokenStatusBar();
    if (!csrfToken() || !sessionCookie()) {
        autoLoadLatestSessionFromServer();
    }
});

// ============================================================
//  জিও ড্রপডাউন
// ============================================================
$('.geoSelect').on('change', function() {
    var geoId    = $(this).val();
    var geoGroup = $(this).data('geo-group');
    var geoOrder = parseInt($(this).data('geo-order'));
    var mapping  = {2:'Dist', 3:'CityCorpCantOrUpazila', 4:'PaurasavaOrUnion'};
    var nextOrder = geoOrder + 1;
    var targetId  = '#' + geoGroup + (mapping[nextOrder] || '');

    if (geoOrder < 4) $('#officeAddrPaurasavaOrUnion').html('<option value="-1">ইউনিয়ন নির্বাচন করুন</option>').closest('.geo-container').hide();
    if (geoOrder < 3) $('#officeAddrCityCorpCantOrUpazila').html('<option value="-1">উপজেলা নির্বাচন করুন</option>').closest('.geo-container').hide();
    if (geoOrder < 2) $('#officeAddrDist').html('<option value="-1">জেলা নির্বাচন করুন</option>').closest('.geo-container').hide();

    if (!geoId || geoId == '-1') { currentOfficeId = ''; $('#searchOfficeButton').prop('disabled', true); return; }

    if (mapping[nextOrder]) {
        var $target  = $(targetId);
        $target.closest('.geo-container').fadeIn();
        $target.html('<option>লোডিং...</option>').prop('disabled', true);
        var cacheKey = 'geo_' + geoGroup + '_' + geoOrder + '_' + geoId;
        if (geoDataCache[cacheKey]) { $target.html(geoDataCache[cacheKey]).prop('disabled', false); return; }
        $.get('proxy_geo.php', { parentId: geoId, geoOrder: geoOrder, geoGroup: geoGroup, geoType: geoOrder==3?3:1, csrfToken: csrfToken() }, function(res) {
            var dataList = Array.isArray(res) ? res : ((res && (res.geoObject || res.data)) || []);
            var options  = '<option value="-1">নির্বাচন করুন</option>';
            dataList.forEach(function(item) {
                var id = item.id || item.code, name = item.nameBn || item.name;
                if (id && name) options += '<option value="' + id + '">' + name + '</option>';
            });
            if (options === '<option value="-1">নির্বাচন করুন</option>') options = '<option value="-1">তথ্য পাওয়া যায়নি</option>';
            $target.html(options).prop('disabled', false);
            geoDataCache[cacheKey] = options;
        }).fail(function() { $target.html('<option value="-1">সার্ভার ত্রুটি</option>').prop('disabled', true); });
        return;
    }

    // ইউনিয়ন সিলেক্ট → অফিস খোঁজো
    if (geoOrder == 4) {
        currentGeoId = geoId;
        $('#currentGeoId').val(geoId);
        $('#officeAlert').remove();
        $('<div class="alert alert-info mt-2" id="officeAlert"><span class="spinner-border spinner-border-sm mr-1"></span> অফিস খোঁজা হচ্ছে...</div>').insertAfter('#officeAddrPaurasavaOrUnion');
        $.get('proxy_office.php', { geoId: geoId, geoGroup: 'officeAddr', geoOrder: 4, geoType: 5, csrfToken: csrfToken(), dataToken: dataToken() }, function(res) {
            $('#officeAlert').remove();
            var officeVal  = (res && res.geoObject) ? (res.geoObject.officeId  || res.officeId)  : (res && res.officeId);
            var officeName = (res && res.geoObject) ? (res.geoObject.officeNameBn || res.officeNameBn || 'অফিস') : (res && res.officeNameBn || 'অফিস');
            var officeEnc  = (res && res.geoObject) ? (res.geoObject.encryptedOfficeId || res.encryptedOfficeId || '') : (res && res.encryptedOfficeId || '');
            if (officeVal) {
                currentOfficeId = officeVal;
                $('#officeId').val(officeVal);
                $('#searchOfficeButton').prop('disabled', false);
                // অফিসের data= টোকেন অটো সেট
                if (officeEnc && !dataToken()) {
                    $('#unoTokenInput').val(officeEnc);
                    localStorage.setItem('bdris_data_token', officeEnc);
                }
                $('<div class="alert alert-success mt-2" id="officeAlert">'
                    + '<i class="material-icons" style="font-size:16px;vertical-align:middle">business</i> '
                    + '<strong>অফিস:</strong> ' + esc(officeName)
                    + ' <span class="badge badge-light ml-1">ID: ' + esc(String(officeVal)) + '</span>'
                    + (officeEnc ? ' <span class="badge badge-secondary ml-1">enc ✓</span>' : '')
                    + '</div>').insertAfter('#officeAddrPaurasavaOrUnion');
                $.get('api/check_status.php', { set_office_id: String(officeVal), _: Date.now() }).fail(function(){});
            } else {
                $('<div class="alert alert-danger mt-2" id="officeAlert">'
                    + '<i class="material-icons" style="font-size:16px;vertical-align:middle">error</i> '
                    + 'অফিস তথ্য পাওয়া যায়নি। CSRF Token ও Session Cookie সঠিক আছে কিনা যাচাই করুন।'
                    + '</div>').insertAfter('#officeAddrPaurasavaOrUnion');
            }
        }).fail(function(xhr) {
            $('#officeAlert').remove();
            var errMsg = (xhr.responseJSON && (xhr.responseJSON._error || xhr.responseJSON.error)) || 'সার্ভার সমস্যা';
            $('<div class="alert alert-warning mt-2" id="officeAlert">' + esc(errMsg) + '</div>').insertAfter('#officeAddrPaurasavaOrUnion');
        });
    }
});

// ============================================================
//  অনুসন্ধান বাটন
// ============================================================
$('#searchOfficeButton').on('click', function() {
    if (!currentOfficeId) { showMessage('অফিস নির্বাচন করুন'); return; }
    $(this).prop('disabled', true).html('<span class="spinner-border spinner-border-sm mr-1"></span>খোঁজা হচ্ছে...');
    listStart = 0; lastListStatus = $('#applicationStatus').val(); lastSearchValue = '';
    loadList();
});

// ============================================================
//  লিস্ট লোড
// ============================================================
function loadList() {
    $('#resultContainer').show(); $('#summaryContainer').show();
    $('#resultTable tbody').html('<tr><td colspan="9" class="text-center"><span class="spinner-border spinner-border-sm mr-2"></span>লোডিং...</td></tr>');
    var reqData = buildRequestData({ action: 'list', officeId: currentOfficeId, status: lastListStatus, draw: listDraw++, start: listStart, length: listLength, searchValue: lastSearchValue || '' });
    $.ajax({ url: 'proxy_list.php', type: 'POST', dataType: 'json', timeout: 45000, data: reqData })
    .done(function(res) {
        if (res && res._error) showMessage(res._error, 'danger');
        var data = (res && res.data) ? res.data : []; lastRows = data;
        renderTableRows(data);
        listTotal = parseInt((res && (res.recordsTotal || res.recordsFiltered)) || 0);
        updatePaginationUi();
        loadCounts();
        $('#searchOfficeButton').prop('disabled', false).html('<i class="material-icons" style="vertical-align:middle">search</i> অনুসন্ধান');
    }).fail(function(xhr) {
        var errMsg = (xhr.responseJSON && (xhr.responseJSON._error || xhr.responseJSON.error)) || 'ডাটা লোড ব্যর্থ হয়েছে';
        $('#resultTable tbody').html('<tr><td colspan="9" class="text-danger text-center">' + esc(errMsg) + '</td></tr>');
        $('#searchOfficeButton').prop('disabled', false).html('<i class="material-icons" style="vertical-align:middle">search</i> অনুসন্ধান');
    });
}

function loadCounts() {
    var statuses = ['APPLIED','RECEIVED','APPROVED','POSSIBLE_DUPLICATE','REGISTERED','REJECTED'];
    var now = Date.now();
    if (countsCache.ts && (now - countsCache.ts) < 60 * 1000 && countsCache.map) {
        statuses.forEach(function(st){ $('#count-'+st).text(countsCache.map[st] != null ? countsCache.map[st] : 0); });
        return;
    }
    if (countsXhr) return;
    statuses.forEach(function(st){ $('#count-'+st).html('<span class="spinner-border spinner-border-sm"></span>'); });
    var reqData = buildRequestData({ action: 'counts', officeId: currentOfficeId, statuses: statuses.join(',') });
    countsXhr = $.ajax({ url: 'proxy_list.php', type: 'POST', dataType: 'json', timeout: 30000, data: reqData })
    .done(function(res){
        var map = (res && res.counts) ? res.counts : {};
        countsCache = { ts: Date.now(), map: map || {} };
        statuses.forEach(function(st){ $('#count-'+st).text(map[st] != null ? map[st] : 0); });
    })
    .fail(function(){
        statuses.forEach(function(st){ $('#count-'+st).text('?'); });
    })
    .always(function(){ countsXhr = null; });
}

// ============================================================
//  টেবিল রো রেন্ডার
// ============================================================
function renderTableRows(data) {
    if (!data || !data.length) {
        $('#resultTable tbody').html('<tr><td colspan="9" class="text-center text-muted py-4"><i class="material-icons">inbox</i> কোনো তথ্য পাওয়া যায়নি</td></tr>');
        return;
    }
    var rows = '';
    var corrSvc = isCorrectionService();
    data.forEach(function(item, idx) {
        var st   = item.status || '';
        var id   = item.id || item.applicationId || '';
        var enc  = item.encryptedId || item.encrypted_id || '';
        var brn17 = item.brn || item.registrationNo || item.bnrn || '';
        var statusMap = {
            'REGISTERED':        '<span class="badge badge-success">REGISTERED</span>',
            'APPROVED':          '<span class="badge badge-warning text-dark">APPROVED</span>',
            'APPLIED':           '<span class="badge badge-secondary">APPLIED</span>',
            'RECEIVED':          '<span class="badge badge-primary">RECEIVED</span>',
            'POSSIBLE_DUPLICATE':'<span class="badge badge-info">POSSIBLE_DUPLICATE</span>',
            'REQUIRES_APPROVAL_WHEN_PARENT_UNKNOWN':'<span class="badge badge-warning text-dark">PARENT_UNKNOWN</span>',
            'REQUIRES_APPROVAL_OF_REMOTE_OFFICE':'<span class="badge badge-warning text-dark">REMOTE_OFFICE</span>',
            'REQUIRES_APPROVAL_OF_HIGHER_AUTHORITY':'<span class="badge badge-warning text-dark">HIGHER_AUTH</span>',
            'PENDING_APPROVAL_FOR_NATIONALITY':'<span class="badge badge-warning text-dark">NATIONALITY</span>',
            'PENDING_APPROVAL_FOR_DOB':'<span class="badge badge-warning text-dark">DOB_APPROVAL</span>',
            'PAID':              '<span class="badge badge-info">PAID</span>',
            'CORRECTED':         '<span class="badge badge-success">CORRECTED</span>',
            'REJECTED':          '<span class="badge badge-danger">REJECTED</span>'
        };
        var statusBadge = statusMap[st] || '<span class="badge badge-secondary">' + esc(st) + '</span>';
        var brnDisplay  = (st === 'REGISTERED' && brn17) ? '<br><span class="brn17-badge" title="১৭ ডিজিট নিবন্ধন নম্বর">🔢 ' + esc(brn17) + '</span>' : '';
        var idText = esc(String(id));
        var encVal = String(enc || '');
        var idJs = jsq(String(id));
        var encJs = jsq(encVal);
        if (id && encVal) encryptedIdCache[String(id)] = encVal;

        var actions = '';
        actions += '<a class="action-view" href="javascript:void(0)" onclick="viewApplication(\'' + idJs + '\',\'' + encJs + '\')" title="১. ভিউ"><i class="material-icons">remove_red_eye</i></a>';
        actions += '<a class="action-print" href="javascript:void(0)" onclick="printApplication(\'' + idJs + '\',\'' + encJs + '\')" title="২. এপ্লিকেশন প্রিন্ট"><i class="material-icons">print</i></a>';
        actions += '<a class="action-docs" href="javascript:void(0)" onclick="viewDocuments(\'' + idJs + '\',\'' + encJs + '\')" title="৩. ডকুমেন্ট প্রিন্ট"><i class="material-icons">description</i></a>';

        var cancelSvc = isCancellationService();
        if (cancelSvc) {
            actions += (st === 'APPLIED' ? '<a class="action-receive" href="javascript:void(0)" onclick="receiveApplication(\'' + idJs + '\',\'' + encJs + '\')" title="গ্রহণ করুন"><i class="material-icons">pan_tool</i></a>' : '');
            actions += ((st === 'RECEIVED' || st === 'APPROVED') ? '<a class="action-register" href="javascript:void(0)" onclick="registerApplicationAction(\'' + idJs + '\',\'' + encJs + '\')" title="নিবন্ধন সম্পন্ন"><i class="material-icons">how_to_reg</i></a>' : '');
            actions += (st === 'RECEIVED' ? '<a class="action-approve" href="javascript:void(0)" onclick="approveApplication(\'' + idJs + '\',\'' + encJs + '\',\'' + jsq(st) + '\')" title="অনুমোদন"><i class="material-icons">check_circle</i></a>' : '');
            actions += ((st !== 'REGISTERED' && st !== 'REJECTED') ? '<a class="action-reject" href="javascript:void(0)" onclick="rejectApplication(\'' + idJs + '\',\'' + encJs + '\')" title="বাতিল করুন"><i class="material-icons">cancel</i></a>' : '');
        } else if (!corrSvc) {
            if (st === 'REGISTERED') {
                var certTitle = getCurrentService() === 'br' ? '৪. জন্ম সনদ প্রিন্ট' : '৪. মৃত্যু সনদ প্রিন্ট';
                actions += '<a class="action-cert" href="javascript:void(0)" onclick="printCertificate(\'' + idJs + '\',\'' + encJs + '\')" title="' + certTitle + '"><i class="material-icons">verified</i></a>';
                actions += '<a class="action-17" href="javascript:void(0)" onclick="view17DigitDoc(\'' + idJs + '\',\'' + encJs + '\')" title="৫. ১৭ ডিজিট নিবন্ধন নম্বর"><i class="material-icons">badge</i></a>';
            }
            actions += (st === 'APPLIED'  ? '<a class="action-receive" href="javascript:void(0)" onclick="receiveApplication(\'' + idJs + '\',\'' + encJs + '\')" title="গ্রহণ করুন"><i class="material-icons">pan_tool</i></a>' : '');
            actions += ((st === 'RECEIVED' || st === 'APPROVED') ? '<a class="action-register" href="javascript:void(0)" onclick="registerApplicationAction(\'' + idJs + '\',\'' + encJs + '\')" title="নিবন্ধন করুন"><i class="material-icons">how_to_reg</i></a>' : '');
            actions += ((st === 'POSSIBLE_DUPLICATE' || st === 'REQUIRES_APPROVAL_WHEN_PARENT_UNKNOWN') ? '<a class="action-dup" href="javascript:void(0)" onclick="checkDuplicates(\'' + encJs + '\',\'' + idJs + '\')" title="ডুপ্লিকেট যাচাই"><i class="material-icons">content_copy</i></a>' : '');
            actions += ((st === 'POSSIBLE_DUPLICATE' || st === 'REQUIRES_APPROVAL_WHEN_PARENT_UNKNOWN') ? '<a class="action-approve" href="javascript:void(0)" onclick="approveApplication(\'' + idJs + '\',\'' + encJs + '\',\'' + jsq(st) + '\')" title="অনুমোদন"><i class="material-icons">check_circle</i></a>' : '');
            actions += ((st === 'APPLIED' || st === 'RECEIVED' || st === 'APPROVED' || st === 'POSSIBLE_DUPLICATE' || st === 'REQUIRES_APPROVAL_WHEN_PARENT_UNKNOWN') ? '<a class="action-reject" href="javascript:void(0)" onclick="rejectApplication(\'' + idJs + '\',\'' + encJs + '\')" title="বাতিল করুন"><i class="material-icons">cancel</i></a>' : '');
        } else {
            actions += (st === 'APPLIED' ? '<a class="action-receive" href="javascript:void(0)" onclick="receiveApplication(\'' + idJs + '\',\'' + encJs + '\')" title="গ্রহণ করুন"><i class="material-icons">pan_tool</i></a>' : '');
            actions += ((st === 'RECEIVED' || st === 'PAID') ? '<a class="action-correct" href="javascript:void(0)" onclick="correctApplication(\'' + idJs + '\',\'' + encJs + '\')" title="সংশোধন সম্পন্ন"><i class="material-icons">task_alt</i></a>' : '');
            actions += ((st === 'REQUIRES_APPROVAL_OF_HIGHER_AUTHORITY' || st === 'PENDING_APPROVAL_FOR_NATIONALITY' || st === 'PENDING_APPROVAL_FOR_DOB' || st === 'REQUIRES_APPROVAL_OF_REMOTE_OFFICE') ? '<a class="action-approve" href="javascript:void(0)" onclick="approveApplication(\'' + idJs + '\',\'' + encJs + '\',\'' + jsq(st) + '\')" title="অনুমোদন"><i class="material-icons">check_circle</i></a>' : '');
            actions += ((st !== 'CORRECTED' && st !== 'REJECTED') ? '<a class="action-reject" href="javascript:void(0)" onclick="rejectApplication(\'' + idJs + '\',\'' + encJs + '\')" title="বাতিল করুন"><i class="material-icons">cancel</i></a>' : '');
        }

        rows += '<tr>'
            + '<td class="text-center text-muted small">' + (listStart + idx + 1) + '</td>'
            + '<td><strong>' + idText + '</strong>' + brnDisplay + '</td>'
            + '<td>' + esc(item.dateApplied || '-') + '</td>'
            + '<td>' + esc(item.personBirthDate || '-') + '</td>'
            + '<td>' + esc(item.personNameBn || '-') + '</td>'
            + '<td>' + esc(item.fatherNameBn || '-') + '</td>'
            + '<td>' + esc(item.motherNameBn || '-') + '</td>'
            + '<td>' + statusBadge + '</td>'
            + '<td class="action-icons" style="white-space:nowrap">'
            + actions
            + '</td></tr>';
    });
    $('#resultTable tbody').html(rows);
}

function updatePaginationUi() {
    var totalPages  = Math.ceil(listTotal / listLength) || 1;
    var currentPage = Math.floor(listStart / listLength) + 1;
    $('#pageInfo').html(' পৃষ্ঠা ' + currentPage + ' / ' + totalPages + ' (মোট ' + listTotal + ') ');
    $('#prevPageBtn').prop('disabled', currentPage <= 1);
    $('#nextPageBtn').prop('disabled', currentPage >= totalPages);
}

// ============================================================
//  iframe লোড হেল্পার
// ============================================================
function openUrlInIframe(label, url) {
    $('#iframeModalLabel').text(label || 'ভিউ');
    $('#iframeModalFrame').attr('srcdoc', '');
    $('#iframeModalFrame').attr('src', url || 'about:blank');
    $('#iframeModal').modal('show');
}

function openHtmlInIframe(label, html) {
    $('#iframeModalLabel').text(label || 'ভিউ');
    $('#iframeModalFrame').attr('src', 'about:blank');
    $('#iframeModalFrame').attr('srcdoc', html || '');
    $('#iframeModal').modal('show');
}

function openLoadingInIframe(label) {
    $('#iframeModalLabel').text(label || 'ভিউ');
    $('#iframeModalFrame').attr('src', 'about:blank');
    $('#iframeModalFrame').attr('srcdoc',
        '<!doctype html><meta charset="utf-8">'
        + '<div style="font-family:SolaimanLipi,Arial,sans-serif;padding:20px;">'
        + '<div style="display:inline-block;border:3px solid #e9ecef;border-top-color:#1a5e1d;border-radius:50%;width:28px;height:28px;animation:spin 1s linear infinite;"></div>'
        + '<span style="margin-left:10px;">লোড হচ্ছে...</span>'
        + '<style>@keyframes spin{to{transform:rotate(360deg)}}</style>'
        + '</div>'
    );
    $('#iframeModal').modal('show');
}

function showIframeError(label, message, details) {
    var pretty = '';
    try { pretty = details ? JSON.stringify(details, null, 2) : ''; } catch (e) { pretty = ''; }
    var html = '<!doctype html><html><head><meta charset="utf-8"><title>' + esc(label || 'Error') + '</title>'
        + '<style>body{font-family:Arial,SolaimanLipi,sans-serif;margin:0;padding:18px;background:#f8f9fa;}'
        + '.box{background:#fff;border:1px solid #e9ecef;border-radius:10px;padding:14px;}'
        + '.t{font-weight:700;color:#dc3545;margin:0 0 8px 0;font-size:18px;}'
        + '.m{margin:0;color:#333;}'
        + 'pre{margin-top:12px;white-space:pre-wrap;word-break:break-word;background:#f6f8fa;border:1px solid #e9ecef;border-radius:8px;padding:10px;}</style>'
        + '</head><body><div class="box"><p class="t">ত্রুটি</p><p class="m">' + esc(message || 'ডাটা আনতে সমস্যা হয়েছে') + '</p>'
        + (pretty ? '<pre>' + esc(pretty) + '</pre>' : '')
        + '</div></body></html>';
    openHtmlInIframe(label || 'ত্রুটি', html);
}

window.openRData = function() {
    var appId = currentViewAppId || (currentViewData && (currentViewData.id || currentViewData.applicationId)) || '';
    var enc = currentViewEncryptedId || (currentViewData && (currentViewData.encryptedId || currentViewData.encrypted_id)) || '';
    if (!appId && !enc) { Swal.fire('নোটিস', 'কোনো ডাটা নেই', 'info'); return; }
    var buildCleanRowsForRData = function(data) {
        var rows = [];
        try { rows = buildNonEmptyRowsForView(data) || []; } catch (e) { rows = []; }

        var addrRegex = /(addr|address)/i;
        rows = rows.filter(function(r) {
            var k = String((r && r.k) || '');
            if (!k) return false;
            if (addrRegex.test(k)) return false;
            return true;
        });

        var prsBn = findFirstValueByKeys(data, ['fullPrsntAddrBn','prsntAddrBn','presentAddressBn','presentAddrBn','presentAddress','prsntAddressBn']);
        var prsEn = findFirstValueByKeys(data, ['fullPrsntAddrEn','prsntAddrEn','presentAddressEn','presentAddrEn','presentAddressEnglish','prsntAddressEn']);
        var permBn = findFirstValueByKeys(data, ['fullPermAddrBn','permAddrBn','permanentAddressBn','permanentAddrBn','permanentAddress','permAddressBn']);
        var permEn = findFirstValueByKeys(data, ['fullPermAddrEn','permAddrEn','permanentAddressEn','permanentAddrEn','permanentAddressEnglish','permAddressEn']);
        var addrRows = [];
        if (prsBn) addrRows.push({ k: 'বর্তমান ঠিকানা (বাংলা)', v: prsBn, isJson: false });
        if (prsEn) addrRows.push({ k: 'বর্তমান ঠিকানা (ইংলিশ)', v: prsEn, isJson: false });
        if (permBn && String(permBn).trim() !== String(prsBn || '').trim()) addrRows.push({ k: 'স্থায়ী ঠিকানা (বাংলা)', v: permBn, isJson: false });
        if (permEn && String(permEn).trim() !== String(prsEn || '').trim()) addrRows.push({ k: 'স্থায়ী ঠিকানা (ইংলিশ)', v: permEn, isJson: false });
        rows = addrRows.concat(rows);

        var normText = function(v) {
            return String(v || '').trim().replace(/\s+/g, ' ').toLowerCase();
        };
        var isBlankText = function(t) {
            var s = String(t || '').trim();
            return !s || s === 'null' || s === 'undefined';
        };
        var out = [];
        var seenKV = {};
        var seenGroupVal = {};

        rows.forEach(function(r) {
            if (!r || !r.k) return;
            var k = String(r.k || '');
            var v = (r.v === null || r.v === undefined) ? '' : String(r.v);
            var tv = v.trim();
            if (isBlankText(tv)) return;

            var kv = normText(k) + '|' + normText(tv);
            if (seenKV[kv]) return;
            seenKV[kv] = 1;

            var group = '';
            if (/(addr|address|birthplace|location)/i.test(k)) group = 'addr';
            else if (/officeName/i.test(k)) group = 'officeName';
            else if (/(personName|applicantName|fatherName|motherName)/i.test(k)) group = 'names';

            if (group && !r.isJson) {
                var nv = normText(tv);
                if (!seenGroupVal[group]) seenGroupVal[group] = {};
                if (seenGroupVal[group][nv]) return;
                seenGroupVal[group][nv] = 1;
            }

            out.push({ k: k, v: v, isJson: !!r.isJson });
        });

        return out;
    };

    openLoadingInIframe('R Data');
    ensureEncryptedId(appId, enc, function(encryptedId) {
        var reqData = buildRequestData({ action: 'rdata', encryptedId: encryptedId });
        $.ajax({ url: 'proxy_list.php', type: 'POST', dataType: 'json', timeout: 45000, data: reqData })
        .done(function(res) {
            var payload = (res && res.data) ? res.data : res;
            var out = buildCleanRowsForRData(payload || {});
            var t = '<table class="info-table-custom">';
            t += '<tr><th style="width:22%">Field</th><th style="width:78%">Value</th></tr>';
            out.forEach(function(r) {
                t += '<tr><th>' + esc(r.k) + '</th><td>' + (r.isJson ? '<div style="white-space:pre-wrap;word-break:break-word;">' + esc(r.v) + '</div>' : esc(r.v)) + '</td></tr>';
            });
            t += '</table>';
            var html = '<!doctype html><html><head><meta charset="utf-8"><title>R Data</title>'
                + '<link href="https://fonts.maateen.me/solaiman-lipi/font.css" rel="stylesheet">'
                + '<style>body{font-family:Arial,SolaimanLipi,sans-serif;margin:0;padding:16px;background:#f3f5f7;}'
                + '.wrap{max-width:1200px;margin:0 auto;background:#fff;border:1px solid #e0e8e0;border-radius:10px;padding:16px;box-shadow:0 8px 24px rgba(0,0,0,0.08);}'
                + '.info-table-custom{width:100%;border-collapse:collapse;margin:0;table-layout:fixed;}'
                + '.info-table-custom tr{border-bottom:1px solid #e0e8e0;}'
                + '.info-table-custom th{width:22%;background:#f9fbf9;padding:3px 7px;text-align:left;font-weight:700;color:#1a5e1d;font-size:14.5px;line-height:1.32;vertical-align:top;word-break:break-word;border:1px solid #d8e6d8;}'
                + '.info-table-custom td{width:78%;padding:3px 10px;text-align:left;font-size:14.5px;line-height:1.32;color:#2c3e2c;word-break:break-word;vertical-align:top;border:1px solid #d8e6d8;}'
                + '.info-table-custom tr:nth-child(even) th,.info-table-custom tr:nth-child(even) td{background:#fcfdfc;}</style>'
                + '</head><body><div class="wrap">' + t + '</div></body></html>';
            $('#iframeModalLabel').text('R Data');
            $('#iframeModalFrame').attr('src', 'about:blank');
            $('#iframeModalFrame').attr('srcdoc', html || '');
        }).fail(function(xhr) {
            var errMsg = (xhr.responseJSON && (xhr.responseJSON._error || xhr.responseJSON.error)) || 'ডাটা আনতে ব্যর্থ হয়েছে';
            showIframeError('R Data', errMsg, xhr.responseJSON || null);
        });
    });
};

function loadInIframe(label, proxyAction, extraData, fallbackUrl) {
    openLoadingInIframe(label);
    var reqData = buildRequestData($.extend({ action: proxyAction }, extraData));
    $.ajax({ url: 'proxy_list.php', type: 'POST', dataType: 'json', timeout: 45000, data: reqData })
    .done(function(res) {
        if (res && res.html) {
            var blob = new Blob([res.html], {type:'text/html;charset=utf-8'});
            $('#iframeModalFrame').attr('src', URL.createObjectURL(blob));
        } else if (res && res.url) {
            $('#iframeModalFrame').attr('src', res.url);
        } else if (fallbackUrl) {
            $('#iframeModalFrame').attr('src', fallbackUrl);
        } else {
            showIframeError(label, 'তথ্য পাওয়া যায়নি। CSRF Token ও Session Cookie সঠিক কিনা যাচাই করুন।', res);
        }
    }).fail(function(xhr) {
        if (fallbackUrl) { $('#iframeModalFrame').attr('src', fallbackUrl); return; }
        var errMsg = (xhr.responseJSON && (xhr.responseJSON._error || xhr.responseJSON.error)) || 'সার্ভার ত্রুটি';
        showIframeError(label, errMsg, xhr.responseJSON || null);
    });
}

// ============================================================
//  অ্যাকশন ফাংশন
// ============================================================
window.printApplication = function(appId, enc) {
    if (!appId && !enc) return;
    var cleanId = String(appId || '').replace(/\D+/g, '');
    if (cleanId) {
        window.open('print-application.php?id=' + encodeURIComponent(cleanId), '_blank');
        return;
    }
    fetchDetailsCached(appId, enc, function(resp, errMsg) {
        if (!resp) { Swal.fire('ত্রুটি', errMsg || 'তথ্য পাওয়া যায়নি', 'error'); return; }
        var resolvedId = String(resp.id || resp.applicationId || '').replace(/\D+/g, '');
        if (resolvedId) {
            window.open('print-application.php?id=' + encodeURIComponent(resolvedId), '_blank');
        } else {
            Swal.fire('ত্রুটি', 'আবেদন আইডি পাওয়া যায়নি', 'error');
        }
    });
};

window.printDocuments = function(appId, enc) {
    if (!appId && !enc) return;
    fetchDetailsCached(appId, enc, function(resp, errMsg) {
        if (!resp) { showIframeError('ডকুমেন্ট', errMsg || 'তথ্য পাওয়া যায়নি', null); return; }
        currentViewData = resp;
        currentViewAppId = String(appId || resp.id || resp.applicationId || '');
        currentViewEncryptedId = String(resp.encryptedId || resp.encrypted_id || enc || '');
        displayDocumentsOnly(resp);
        $('#viewApplicationModal').modal('show');
    });
};

window.printCertificate = function(appId, enc) {
    if (!appId && !enc) return;
    var newTab = window.open('about:blank', '_blank');
    if (newTab) {
        newTab.document.write('<html><head><title>সনদ লোড হচ্ছে...</title><style>body{font-family:sans-serif;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:#f8f9fa;color:#1a5e1d;} .loader{border:4px solid #e9ecef;border-top:4px solid #1a5e1d;border-radius:50%;width:35px;height:35px;animation:spin 1s linear infinite;margin-bottom:12px;} @keyframes spin{0%{transform:rotate(0deg)} 100%{transform:rotate(360deg)}} .box{text-align:center;}</style></head><body><div class="box"><div class="loader"></div><div>জন্ম সনদ লোড হচ্ছে, অনুগ্রহ করে অপেক্ষা করুন...</div></div></body></html>');
    }
    ensureEncryptedId(appId, enc, function(encryptedId) {
        var pdfUrl = 'proxy_list.php?action=print_pdf_cert&encryptedId=' + encodeURIComponent(encryptedId);
        if (newTab) {
            newTab.location.href = pdfUrl;
        } else {
            window.open(pdfUrl, '_blank');
        }
    }, function() {
        if (newTab) newTab.close();
    });
};

window.view17DigitDoc = function(appId, enc) {
    if (!appId && !enc) return;
    var newTab = window.open('about:blank', '_blank');
    if (newTab) {
        newTab.document.write('<html><head><title>সনদ লোড হচ্ছে...</title><style>body{font-family:sans-serif;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:#f8f9fa;color:#1a5e1d;} .loader{border:4px solid #e9ecef;border-top:4px solid #1a5e1d;border-radius:50%;width:35px;height:35px;animation:spin 1s linear infinite;margin-bottom:12px;} @keyframes spin{0%{transform:rotate(0deg)} 100%{transform:rotate(360deg)}} .box{text-align:center;}</style></head><body><div class="box"><div class="loader"></div><div>১৭ ডিজিট সনদ লোড হচ্ছে, অনুগ্রহ করে অপেক্ষা করুন...</div></div></body></html>');
    }
    ensureEncryptedId(appId, enc, function(encryptedId) {
        var pdfUrl = 'proxy_list.php?action=print_pdf_cert&encryptedId=' + encodeURIComponent(encryptedId);
        if (newTab) {
            newTab.location.href = pdfUrl;
        } else {
            window.open(pdfUrl, '_blank');
        }
    }, function() {
        if (newTab) newTab.close();
    });
};

window.checkDuplicates = function(enc, appId) {
    if (!enc && !appId) { showIframeError('ডুপ্লিকেট যাচাই', 'আবেদন তথ্য পাওয়া যায়নি', null); return; }
    ensureEncryptedId(appId, enc, function(encryptedId) {
        openLoadingInIframe('ডুপ্লিকেট যাচাই');
        $.ajax({
            url: 'proxy_list.php',
            type: 'POST',
            dataType: 'json',
            timeout: 45000,
            data: buildRequestData({ action: 'possible_duplicates', encryptedId: encryptedId })
        }).done(function(res) {
            var payload = (res && res.data) ? res.data : res;
            if (payload && payload.ok === false && (payload.error || payload._error)) {
                showIframeError('ডুপ্লিকেট যাচাই', String(payload.error || payload._error || 'ডাটা আনতে সমস্যা হয়েছে'), payload);
                return;
            }
            var list = [];
            if (payload && payload.data && Array.isArray(payload.data)) list = payload.data;
            else if (Array.isArray(payload)) list = payload;
            else if (payload && payload.data && payload.data.data && Array.isArray(payload.data.data)) list = payload.data.data;
            else if (payload && payload.data && payload.data.data && payload.data.data.id) list = [payload.data.data];
            else if (payload && payload.data && payload.data.id) list = [payload.data];
            else if (payload && payload.id) list = [payload];

            if (!list || !list.length) {
                showIframeError('ডুপ্লিকেট যাচাই', 'কোনো ডুপ্লিকেট তথ্য পাওয়া যায়নি (বা BDRIS সার্ভিস পরিবর্তন হয়েছে)।', payload);
                return;
            }

            var norm17 = function(v) {
                var d = String(v || '').replace(/\D+/g, '');
                return d.length === 17 ? d : '';
            };
            var pick = function(o, keys) {
                for (var i = 0; i < keys.length; i++) {
                    var k = keys[i];
                    if (o && o[k] != null && String(o[k]).trim() !== '') return String(o[k]);
                }
                return '';
            };
            var rows = '';
            list.forEach(function(it) {
                if (!it || typeof it !== 'object') return;
                var ubrn = norm17(pick(it, ['birthRegistrationNumber','ubrn','UBRN','registrationNumber']));
                var dob = pick(it, ['personBirthDate','dateOfBirth','dob','birthDate']);
                var name = pick(it, ['personNameBn','personName','nameBn','name','personNameEn']);
                var father = pick(it, ['fatherNameBn','fatherName','fatherNameEn']);
                var mother = pick(it, ['motherNameBn','motherName','motherNameEn']);
                var office = pick(it, ['officeNameBn','registrationOfficeNameBn','registrationOfficeName','officeName']);
                var view = (ubrn ? ('<a class="btn btn-sm btn-outline-info" target="_blank" href="search-birth.php?ubrn=' + encodeURIComponent(ubrn) + (dob ? ('&dob=' + encodeURIComponent(dob)) : '') + '">ভিউ</a>') : '');
                var cert = (ubrn && dob ? ('<a class="btn btn-sm btn-outline-success ms-1" target="_blank" href="print-certificate.php?action=print&mode=main&ubrn=' + encodeURIComponent(ubrn) + '&dob=' + encodeURIComponent(dob) + '">সার্টিফিকেট</a>') : '');
                rows += '<tr>'
                    + '<td>' + esc(ubrn || '-') + '</td>'
                    + '<td>' + esc(dob || '-') + '</td>'
                    + '<td>' + esc(name || '-') + '</td>'
                    + '<td>' + esc(father || '-') + '</td>'
                    + '<td>' + esc(mother || '-') + '</td>'
                    + '<td>' + esc(office || '-') + '</td>'
                    + '<td style="white-space:nowrap">' + (view || cert ? (view + cert) : '-') + '</td>'
                    + '</tr>';
            });

            var html = '<!doctype html><html><head><meta charset="utf-8"><title>ডুপ্লিকেট যাচাই</title>'
                + '<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">'
                + '<style>body{font-family:SolaimanLipi,Arial,sans-serif;background:#f8f9fa;padding:12px;} .card{border-radius:12px;} table{font-size:13px;}</style>'
                + '</head><body>'
                + '<div class="card shadow-sm"><div class="card-body">'
                + '<h6 class="mb-3">সম্ভাব্য ডুপ্লিকেট তালিকা</h6>'
                + '<div class="table-responsive"><table class="table table-sm table-striped align-middle mb-0">'
                + '<thead class="table-light"><tr><th>১৭ ডিজিট</th><th>জন্ম তারিখ</th><th>নাম</th><th>পিতা</th><th>মাতা</th><th>অফিস</th><th>অ্যাকশন</th></tr></thead>'
                + '<tbody>' + (rows || '<tr><td colspan="7" class="text-center text-muted py-3">কোনো তথ্য নেই</td></tr>') + '</tbody>'
                + '</table></div>'
                + '</div></div>'
                + '</body></html>';
            openHtmlInIframe('ডুপ্লিকেট যাচাই', html);
        }).fail(function(xhr) {
            var errMsg = (xhr.responseJSON && (xhr.responseJSON._error || xhr.responseJSON.error)) || 'ডুপ্লিকেট ডাটা আনতে ব্যর্থ হয়েছে';
            showIframeError('ডুপ্লিকেট যাচাই', errMsg, xhr.responseJSON || null);
        });
    });
};

window.viewApplication = function(appId, encryptedId) {
    if (!appId && !encryptedId) { Swal.fire('ত্রুটি', 'আবেদন আইডি পাওয়া যায়নি', 'error'); return; }
    currentModalPrintableHtml = '';
    $('#viewModalBody').html('<div class="text-center p-5"><div class="spinner-border text-success"></div><p class="mt-2">লোড হচ্ছে...</p></div>');
    $('#viewApplicationModal').modal('show');
    fetchDetailsCached(appId, encryptedId, function(resp, errMsg) {
        if (resp) {
            currentViewData = resp;
            currentViewAppId = String(appId || resp.id || resp.applicationId || '');
            currentViewEncryptedId = String(resp.encryptedId || resp.encrypted_id || encryptedId || '');
            displayDocumentsWithData(resp);
            return;
        }
        $('#viewModalBody').html('<div class="alert alert-danger"><i class="material-icons">error</i> ' + esc(errMsg || 'তথ্য পাওয়া যায়নি') + '<br><small>CSRF Token ও Session Cookie সঠিক আছে কিনা যাচাই করুন।</small></div>');
    });
};

window.viewDocuments = function(appId, encryptedId) {
    if (!appId && !encryptedId) { Swal.fire('ত্রুটি', 'আবেদন আইডি পাওয়া যায়নি', 'error'); return; }
    var cleanId = String(appId || '').replace(/\D+/g, '');
    if (cleanId) {
        window.open('print-documents.php?app_id=' + encodeURIComponent(cleanId), '_blank');
        return;
    }
    fetchDetailsCached(appId, encryptedId, function(resp, errMsg) {
        if (!resp) { Swal.fire('ত্রুটি', errMsg || 'তথ্য পাওয়া যায়নি', 'error'); return; }
        var resolvedId = String(resp.id || resp.applicationId || '').replace(/\D+/g, '');
        if (resolvedId) {
            window.open('print-documents.php?app_id=' + encodeURIComponent(resolvedId), '_blank');
        } else {
            Swal.fire('ত্রুটি', 'আবেদন আইডি পাওয়া যায়নি', 'error');
        }
    });
};

function fetchDetailsCached(appId, encryptedId, cb) {
    var enc = (encryptedId || '').trim();
    var id = (appId || '').trim();
    if (!enc && !id) { cb(null, 'আবেদন আইডি পাওয়া যায়নি'); return; }

    var doFetch = function(resolvedEnc) {
        var key = (resolvedEnc || id).trim();
        if (!key) { cb(null, 'আবেদন আইডি পাওয়া যায়নি'); return; }
        var now = Date.now();
        var cached = detailsCache[key];
        if (cached && cached.data && cached.ts && (now - cached.ts) < 2 * 60 * 1000) {
            cb(cached.data, null);
            return;
        }
        var requestData = buildRequestData({ action: 'details', encryptedId: resolvedEnc });
        $.ajax({ url: 'proxy_list.php', type: 'POST', dataType: 'json', timeout: 45000, data: requestData })
        .done(function(resp) {
            if (resp && (resp.id || resp.applicationId || resp.personNameBn || resp.docs)) {
                var st = String(resp.status || '').toUpperCase();
                var hasUbrn = false;
                try {
                    var u0 = findFirstValueByKeys(resp, ['birthRegistrationNumber','ubrn','birthRegNo','birthRegistrationNo','registrationNumber','brn','brn17','brn_17']);
                    var d0 = String(u0 || '').replace(/\D+/g, '');
                    hasUbrn = d0.length === 17;
                } catch (e) { hasUbrn = false; }

                if (st === 'REGISTERED' && !hasUbrn && resolvedEnc) {
                    $.ajax({
                        url: 'proxy_list.php',
                        type: 'POST',
                        dataType: 'json',
                        timeout: 45000,
                        data: buildRequestData({ action: 'resolve_cert_ubrn', encryptedId: resolvedEnc })
                    }).done(function(r2) {
                        var ubrn2 = r2 && r2.ubrn ? String(r2.ubrn) : '';
                        ubrn2 = ubrn2.replace(/\D+/g, '');
                        if (ubrn2.length === 17) {
                            resp.birthRegistrationNumber = ubrn2;
                            resp.ubrn = ubrn2;
                            resp.brn17 = ubrn2;
                        }
                        if (r2 && r2.dob && !resp.personBirthDate) resp.personBirthDate = String(r2.dob);
                        detailsCache[key] = { ts: now, data: resp };
                        cb(resp, null);
                    }).fail(function() {
                        detailsCache[key] = { ts: now, data: resp };
                        cb(resp, null);
                    });
                    return;
                }

                detailsCache[key] = { ts: now, data: resp };
                cb(resp, null);
            } else {
                cb(null, (resp && (resp._error || resp.error)) || 'তথ্য পাওয়া যায়নি');
            }
        }).fail(function(xhr) {
            var errMsg = (xhr.responseJSON && (xhr.responseJSON._error || xhr.responseJSON.error)) || 'ডাটা আনতে ব্যর্থ হয়েছে';
            cb(null, errMsg);
        });
    };

    if (enc) {
        doFetch(enc);
        return;
    }
    ensureEncryptedId(id, '', function(resolvedEnc) { doFetch(resolvedEnc); });
}

function ensureEncryptedId(appId, encryptedId, cb, errCb) {
    var enc = (encryptedId || '').trim();
    if (enc) { cb(enc); return; }
    var id = (appId || '').trim();
    if (!id) { 
        Swal.fire('ত্রুটি', 'আবেদন আইডি পাওয়া যায়নি', 'error'); 
        if (errCb) errCb();
        return; 
    }
    if (encryptedIdCache[id]) { cb(String(encryptedIdCache[id])); return; }
    var reqData = buildRequestData({ action: 'resolve_encrypted', appId: id, officeId: currentOfficeId });
    $.ajax({ url: 'proxy_list.php', type: 'POST', dataType: 'json', timeout: 45000, data: reqData })
    .done(function(res) {
        var got = (res && (res.encryptedId || res.encrypted_id || res.data)) ? String(res.encryptedId || res.encrypted_id || res.data) : '';
        if (got) { encryptedIdCache[id] = got; cb(got); return; }
        Swal.fire('ত্রুটি', (res && (res._error || res.error)) || 'Encrypted ID পাওয়া যায়নি', 'error');
        if (errCb) errCb();
    })
    .fail(function(xhr) {
        var errMsg = (xhr.responseJSON && (xhr.responseJSON._error || xhr.responseJSON.error)) || 'Encrypted ID আনতে ব্যর্থ হয়েছে';
        Swal.fire('ত্রুটি', esc(errMsg), 'error');
        if (errCb) errCb();
    });
}

function buildNonEmptyRowsForView(data) {
    var rows = [];
    var isBlank = function(v) {
        if (v === null || v === undefined) return true;
        if (typeof v === 'string') {
            var t = v.trim();
            return t === '' || t === 'null' || t === 'undefined';
        }
        if (Array.isArray(v)) return v.length === 0;
        if (typeof v === 'object') return Object.keys(v).length === 0;
        return false;
    };
    var toPrintable = function(v) {
        if (v === null || v === undefined) return '';
        if (typeof v === 'string') return v;
        if (typeof v === 'number' || typeof v === 'boolean') return String(v);
        try { return JSON.stringify(v); } catch(e) { return String(v); }
    };
    var walk = function(obj, prefix) {
        if (obj === null || obj === undefined) return;
        if (Array.isArray(obj)) {
            if (!obj.length) return;
            var allScalar = true;
            for (var i = 0; i < obj.length; i++) {
                var it = obj[i];
                if (it !== null && it !== undefined && typeof it === 'object') { allScalar = false; break; }
            }
            if (allScalar) {
                var joined = obj.map(function(x){ return toPrintable(x); }).filter(function(x){ return !isBlank(x); }).join(', ');
                if (!isBlank(joined)) rows.push({ k: prefix || 'value', v: joined, isJson: false });
                return;
            }
            var s = toPrintable(obj);
            if (!isBlank(s)) rows.push({ k: prefix || 'value', v: s, isJson: true });
            return;
        }
        if (typeof obj === 'object') {
            var keys = Object.keys(obj);
            if (!keys.length) return;
            keys.forEach(function(k) {
                if (!k) return;
                if (k === 'docs') return;
                var val = obj[k];
                if (isBlank(val)) return;
                var p = prefix ? (prefix + '.' + k) : k;
                if (typeof val === 'object') walk(val, p);
                else rows.push({ k: p, v: toPrintable(val), isJson: false });
            });
            return;
        }
        var s2 = toPrintable(obj);
        if (!isBlank(s2)) rows.push({ k: prefix || 'value', v: s2, isJson: false });
    };
    walk(data, '');
    return rows;
}

function findFirstValueByKeys(obj, keys) {
    if (!obj || !keys || !keys.length) return '';
    var target = {};
    keys.forEach(function(k) { if (k) target[String(k)] = 1; });
    var seen = {};
    var stack = [obj];
    while (stack.length) {
        var cur = stack.pop();
        if (!cur || typeof cur !== 'object') continue;
        if (seen[cur]) continue;
        try { seen[cur] = 1; } catch (e) {}
        if (Array.isArray(cur)) {
            for (var i = 0; i < cur.length; i++) stack.push(cur[i]);
            continue;
        }
        var ks = Object.keys(cur);
        for (var j = 0; j < ks.length; j++) {
            var k0 = ks[j];
            if (target[k0]) {
                var v0 = cur[k0];
                if (v0 !== null && v0 !== undefined) {
                    var s = (typeof v0 === 'string') ? v0.trim() : String(v0);
                    if (s && s !== 'null' && s !== 'undefined') return s;
                }
            }
            var v1 = cur[k0];
            if (v1 && typeof v1 === 'object') stack.push(v1);
        }
    }
    return '';
}

function buildDocsGridHtml(docs, forPrint) {
    if (!docs || !docs.length) {
        return '<div class="alert alert-warning text-center"><i class="material-icons" style="vertical-align:middle">info</i> কোনো ডকুমেন্ট পাওয়া যায়নি</div>';
    }
    var placeholder = 'data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 800 500%22%3E%3Crect width=%22800%22 height=%22500%22 fill=%22%23f0f0f0%22/%3E%3Ctext x=%22400%22 y=%22270%22 text-anchor=%22middle%22 font-size=%2240%22 fill=%22%23999%22%3ELoading...%3C/text%3E%3C/svg%3E';
    var fallback = 'data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22%3E%3Crect width=%22100%22 height=%22100%22 fill=%22%23f0f0f0%22/%3E%3Ctext x=%2250%22 y=%2255%22 text-anchor=%22middle%22 font-size=%2230%22%3E%F0%9F%93%84%3C/text%3E%3C/svg%3E';
    var html = '<div class="docs-grid-custom">';
    docs.forEach(function(doc) {
        var docId = doc && doc.id ? String(doc.id) : '';
        if (!docId) return;
        var docUrl  = 'image-proxy.php?id=' + encodeURIComponent(docId) + '&csrfToken=' + encodeURIComponent(csrfToken());
        var docLabel = 'ডকুমেন্ট';
        var imgHtml = '';
        if (forPrint) {
            imgHtml = '<img src="' + esc(docUrl) + '" loading="eager" fetchpriority="high" decoding="async" onerror="this.src=\'' + fallback + '\'">';
        } else {
            imgHtml = '<img class="doc-img-lazy" src="' + placeholder + '" data-src="' + esc(docUrl) + '" loading="lazy" fetchpriority="low" decoding="async" onclick="openUrlInIframe(\'' + jsq(docLabel) + '\', \'' + jsq(docUrl) + '\')" onerror="this.src=\'' + fallback + '\'">';
        }
        html += '<div class="doc-card-custom">'
            + imgHtml
            + (forPrint ? '' : (
                '<div class="doc-actions-custom no-print">'
                + '<button type="button" class="btn btn-sm btn-outline-success" onclick="openUrlInIframe(\'' + jsq(docLabel) + '\', \'' + jsq(docUrl) + '\');return false;">ভিউ</button>'
                + '<a class="btn btn-sm btn-outline-secondary" href="' + esc(docUrl) + '" download>ডাউনলোড</a>'
                + '</div>'
            ))
            + '</div>';
    });
    html += '</div>';
    return html;
}

function wireLazyDocImages(scopeEl) {
    var root = scopeEl;
    if (!root) root = document;
    var imgs = root.querySelectorAll ? root.querySelectorAll('img.doc-img-lazy[data-src]') : [];
    if (!imgs || !imgs.length) return;
    var loadImg = function(img) {
        if (!img) return;
        var ds = img.getAttribute('data-src') || '';
        if (!ds) return;
        img.setAttribute('src', ds);
        img.removeAttribute('data-src');
        img.classList.remove('doc-img-lazy');
    };
    var eagerCount = Math.min(2, imgs.length);
    for (var i = 0; i < eagerCount; i++) {
        try { loadImg(imgs[i]); } catch (err) {}
    }
    if (window.IntersectionObserver) {
        var io = new IntersectionObserver(function(entries) {
            entries.forEach(function(e) {
                if (!e.isIntersecting) return;
                loadImg(e.target);
                try { io.unobserve(e.target); } catch (err) {}
            });
        }, { root: null, rootMargin: '800px 0px', threshold: 0.01 });
        imgs.forEach(function(img) { try { io.observe(img); } catch (err) { loadImg(img); } });
        return;
    }
    imgs.forEach(function(img) { loadImg(img); });
}
function buildDocumentsPageHtml(data, forPrint) {
    var officeName = 'হরিনাথপুর ইউনিয়ন পরিষদ';
    var distText = '';
    var upaText = '';
    try {
        var $d = $('#officeAddrDist');
        if ($d && $d.length) {
            var dv = String($d.val() || '');
            if (dv && dv !== '-1') distText = String($d.find('option:selected').text() || '').trim();
        }
        var $u = $('#officeAddrCityCorpCantOrUpazila');
        if ($u && $u.length) {
            var uv = String($u.val() || '');
            if (uv && uv !== '-1') upaText = String($u.find('option:selected').text() || '').trim();
        }
    } catch (e) {}
    var officeSubLine = [upaText, distText].filter(function(x){ return x; }).join(', ');
    var ubrnRaw = findFirstValueByKeys(data, ['birthRegistrationNumber','deathRegistrationNumber','ubrn','birthRegNo','birthRegistrationNo','registrationNumber','registrationNo','brn','brn17','brn_17']);
    var ubrn17 = '';
    if (ubrnRaw) {
        var dig = String(ubrnRaw).replace(/\D+/g, '');
        if (dig.length === 17) ubrn17 = dig;
    }
    var rows = buildNonEmptyRowsForView(data);
    var addrRegex = /(addr|address)/i;
    rows = rows.filter(function(r) {
        var k = String((r && r.k) || '');
        if (!k) return false;
        if (addrRegex.test(k)) return false;
        return true;
    });

    var prsBn = findFirstValueByKeys(data, ['fullPrsntAddrBn','prsntAddrBn','presentAddressBn','presentAddrBn','presentAddress','prsntAddressBn']);
    var prsEn = findFirstValueByKeys(data, ['fullPrsntAddrEn','prsntAddrEn','presentAddressEn','presentAddrEn','presentAddressEnglish','prsntAddressEn']);
    var permBn = findFirstValueByKeys(data, ['fullPermAddrBn','permAddrBn','permanentAddressBn','permanentAddrBn','permanentAddress','permAddressBn']);
    var permEn = findFirstValueByKeys(data, ['fullPermAddrEn','permAddrEn','permanentAddressEn','permanentAddrEn','permanentAddressEnglish','permAddressEn']);
    var addrRows = [];
    if (prsBn) addrRows.push({ k: 'বর্তমান ঠিকানা (বাংলা)', v: prsBn, isJson: false });
    if (prsEn) addrRows.push({ k: 'বর্তমান ঠিকানা (ইংলিশ)', v: prsEn, isJson: false });
    if (permBn && String(permBn).trim() !== String(prsBn || '').trim()) addrRows.push({ k: 'স্থায়ী ঠিকানা (বাংলা)', v: permBn, isJson: false });
    if (permEn && String(permEn).trim() !== String(prsEn || '').trim()) addrRows.push({ k: 'স্থায়ী ঠিকানা (ইংলিশ)', v: permEn, isJson: false });
    rows = addrRows.concat(rows);

    var t = '<table class="info-table-custom">';
    t += '<tr><th style="width:22%">Field</th><th style="width:78%">Value</th></tr>';
    rows.forEach(function(r) {
        if (!r || !r.k) return;
        t += '<tr><th>' + esc(r.k) + '</th><td>' + (r.isJson ? '<div style="white-space:pre-wrap;word-break:break-word;">' + esc(r.v) + '</div>' : esc(r.v)) + '</td></tr>';
    });
    t += '</table>';

    var docsHtml = buildDocsGridHtml((data && data.docs) ? data.docs : [], !!forPrint);
    var body = ''
        + '<div class="doc-page-wrap">'
        + '<div class="info-section">'
        + '<div class="print-header" style="text-align:center;border-bottom:2px solid #1a5e1d;padding-bottom:15px;margin-bottom:18px;">'
        + '<img src="https://upload.wikimedia.org/wikipedia/commons/8/84/Government_Seal_of_Bangladesh.svg" style="width:70px;max-width:70px;height:auto;">'
        + '<h2 style="color:#1a5e1d;margin:6px 0 2px 0;font-size:18px;line-height:1.2;font-weight:700;">গণপ্রজাতন্ত্রী বাংলাদেশ সরকার</h2>'
        + '<h3 style="margin:0 0 4px 0;font-size:15px;font-weight:700;line-height:1.2;">' + esc(officeName) + '</h3>'
        + (officeSubLine ? '<div style="margin:0 0 4px 0;font-size:13px;font-weight:600;line-height:1.2;color:#2c3e2c;">' + esc(officeSubLine) + '</div>' : '')
        + '</div>'
        + (ubrn17 ? (
            '<div style="text-align:center;margin:0 0 14px 0;">'
            + '<div style="display:inline-block;border:1px solid #b2f2bb;background:#ebfbee;border-radius:10px;padding:10px 14px;">'
            + '<div style="font-weight:700;color:#2b8a3e;font-size:14px;">১৭ ডিজিট নিবন্ধন নম্বর</div>'
            + '<div style="margin-top:4px;font-weight:800;color:#1a5e1d;font-size:18px;letter-spacing:1px;">' + esc(ubrn17) + '</div>'
            + '</div>'
            + '</div>'
        ) : '')
        + '<div class="section-title-custom" style="margin-top:0"><i class="material-icons">list_alt</i> তথ্য</div>'
        + t
        + '</div>'
        + '<div class="docs-section">'
        + '<div class="section-title-custom"><i class="material-icons">attach_file</i> ডকুমেন্ট (' + (((data && data.docs) ? data.docs.length : 0)) + ')</div>'
        + docsHtml
        + '</div>'
        + '</div>';

    if (!forPrint) return body;

    var css = ''
        + '@page{size:A4 portrait;margin:12mm;}'
        + 'html,body{width:100%;}'
        + 'body{font-family:SolaimanLipi,Arial,sans-serif;background:#fff;color:#000;font-size:14px;line-height:1.35;-webkit-print-color-adjust:exact;print-color-adjust:exact;}'
        + '*{box-sizing:border-box;}'
        + '.no-print{display:none !important;}'
        + '.doc-page-wrap{width:100%;max-width:100%;margin:0 auto;padding:0;}'
        + '.info-table-custom{width:100%;border-collapse:collapse;margin-bottom:12px;}'
        + '.info-table-custom tr{border-bottom:1px solid #e0e8e0;}'
        + '.info-table-custom th,.info-table-custom td{border:1px solid #d8e6d8;}'
        + '.info-table-custom tr:nth-child(even) th,.info-table-custom tr:nth-child(even) td{background:#fcfdfc;}'
        + '.info-table-custom{table-layout:fixed;}'
        + '.info-table-custom th{width:22%;background:#f9fbf9;padding:3px 7px;text-align:left;font-weight:700;color:#1a5e1d;font-size:14.5px;line-height:1.32;vertical-align:top;word-break:break-word;}'
        + '.info-table-custom td{width:78%;padding:3px 10px;text-align:left;font-size:14.5px;line-height:1.32;color:#2c3e2c;word-break:break-word;vertical-align:top;}'
        + 'table{page-break-inside:auto;} tr{page-break-inside:avoid;page-break-after:auto;}'
        + '.section-title-custom{font-size:16px;font-weight:700;color:#1a5e1d;margin:18px 0 10px 0;padding-bottom:6px;border-bottom:2px solid #e0e8e0;display:flex;align-items:center;gap:8px;}'
        + '.docs-grid-custom{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin-top:10px;margin-bottom:0;}'
        + '.doc-card-custom{border:1px solid #ddd;border-radius:12px;padding:10px;text-align:center;background:#fff;break-inside:avoid;}'
        + '.doc-card-custom img{width:100%;height:260px;object-fit:contain;background:#f5f5f5;border-radius:8px;margin-bottom:0;}'
        + '.doc-type-custom{display:none !important;}'
        + '.doc-download-text{margin-top:10px;font-size:12px;color:#adb5bd;}'
        + '.info-section{break-after:page;page-break-after:always;}'
        + '.docs-section{break-before:page;page-break-before:always;}';

    return '<!doctype html><html><head><meta charset="utf-8"><title>প্রিন্ট</title>'
        + '<link href="https://fonts.maateen.me/solaiman-lipi/font.css" rel="stylesheet">'
        + '<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">'
        + '<style>' + css + '</style>'
        + '</head><body>' + body + '</body></html>';
}

function displayDocumentsWithData(data) {
    currentModalPrintableHtml = buildDocumentsPageHtml(data, true);
    $('#viewModalBody').html(buildDocumentsPageHtml(data, false));
    wireLazyDocImages(document.getElementById('viewModalBody'));
}

function displayInModal(data) {
    var statusMap = {
        'REGISTERED':        '<span class="status-badge-custom status-registered">REGISTERED</span>',
        'APPROVED':          '<span class="status-badge-custom status-applied">APPROVED</span>',
        'APPLIED':           '<span class="status-badge-custom status-other" style="background:#6c757d;color:white">APPLIED</span>',
        'RECEIVED':          '<span class="status-badge-custom" style="background:#007bff;color:white">RECEIVED</span>',
        'POSSIBLE_DUPLICATE':'<span class="status-badge-custom status-duplicate">POSSIBLE_DUPLICATE</span>',
        'REJECTED':          '<span class="status-badge-custom" style="background:#dc3545;color:white">REJECTED</span>'
    };
    var st         = data.status || '';
    var statusBadge = statusMap[st] || '<span class="status-badge-custom status-other">' + esc(st) + '</span>';
    var brn17      = data.brn || data.registrationNo || data.bnrn || '';
    var enc        = data.encryptedId || data.encrypted_id || '';
    var appId      = data.id || data.applicationId || '';

    var officeName = 'হরিনাথপুর ইউনিয়ন পরিষদ';
    var infoHtml = '<div class="print-header" style="text-align:center;border-bottom:2px solid #1a5e1d;padding-bottom:15px;margin-bottom:20px;">'
        + '<img src="https://upload.wikimedia.org/wikipedia/commons/8/84/Government_Seal_of_Bangladesh.svg" width="70">'
        + '<h2 style="color:#1a5e1d;margin:5px 0;">গণপ্রজাতন্ত্রী বাংলাদেশ সরকার</h2>'
        + '<h3 style="margin:4px 0;font-size:16px;font-weight:700;">' + esc(officeName) + '</h3>'
        + '</div>';

    if (brn17) {
        infoHtml += '<div class="alert alert-success text-center mb-3">'
            + '<strong><i class="material-icons" style="vertical-align:middle">badge</i> ১৭ ডিজিট নিবন্ধন নম্বর:</strong>'
            + '<div class="brn17-badge mt-1">' + esc(brn17) + '</div>'
            + '</div>';
    }

    var isBlank = function(v) {
        if (v === null || v === undefined) return true;
        if (typeof v === 'string') {
            var t = v.trim();
            return t === '' || t === 'null' || t === 'undefined';
        }
        if (Array.isArray(v)) return v.length === 0;
        if (typeof v === 'object') return Object.keys(v).length === 0;
        return false;
    };
    var toPrintable = function(v) {
        if (v === null || v === undefined) return '';
        if (typeof v === 'string') return v;
        if (typeof v === 'number' || typeof v === 'boolean') return String(v);
        try { return JSON.stringify(v); } catch(e) { return String(v); }
    };
    var flattenNonEmpty = function(obj, prefix, out) {
        if (obj === null || obj === undefined) return;
        if (Array.isArray(obj)) {
            if (obj.length === 0) return;
            var allScalar = true;
            for (var i = 0; i < obj.length; i++) {
                var it = obj[i];
                if (it !== null && it !== undefined && (typeof it === 'object')) { allScalar = false; break; }
            }
            if (allScalar) {
                var joined = obj.map(function(x){ return toPrintable(x); }).filter(function(x){ return !isBlank(x); }).join(', ');
                if (!isBlank(joined)) out.push({k: prefix, v: joined, isJson: false});
                return;
            }
            var s = toPrintable(obj);
            if (!isBlank(s)) out.push({k: prefix, v: s, isJson: true});
            return;
        }
        if (typeof obj === 'object') {
            var keys = Object.keys(obj);
            if (keys.length === 0) return;
            keys.forEach(function(k) {
                if (!k) return;
                if (k === 'docs') return;
                var p = prefix ? (prefix + '.' + k) : k;
                var val = obj[k];
                if (isBlank(val)) return;
                if (typeof val === 'object') {
                    flattenNonEmpty(val, p, out);
                } else {
                    out.push({k: p, v: toPrintable(val), isJson: false});
                }
            });
            return;
        }
        var s2 = toPrintable(obj);
        if (!isBlank(s2)) out.push({k: prefix || 'value', v: s2, isJson: false});
    };

    var rows = [];
    flattenNonEmpty(data, '', rows);
    rows.sort(function(a,b){ return a.k.localeCompare(b.k); });

    infoHtml += '<div class="text-center mb-3">' + statusBadge + '</div>';
    infoHtml += '<table class="info-table-custom">';
    infoHtml += '<tr><th style="width:35%">Field</th><th>Value</th></tr>';
    rows.forEach(function(r) {
        if (!r || !r.k) return;
        infoHtml += '<tr><th>' + esc(r.k) + '</th><td>' + (r.isJson ? '<div style="white-space:pre-wrap;word-break:break-word;">' + esc(r.v) + '</div>' : esc(r.v)) + '</td></tr>';
    });
    infoHtml += '</table>';

    if (data.docs && data.docs.length) {
        infoHtml += '<div class="section-title-custom"><i class="material-icons">attach_file</i> Documents (' + data.docs.length + ')</div>';
        infoHtml += buildDocsGridHtml(data.docs, false);
    }

    // মডালের ভেতরে অ্যাকশন বাটন
    infoHtml += '<div class="mt-3 text-center no-print">';
    var isCancel = isCancellationService();
    if (st === 'APPLIED')
        infoHtml += '<button class="btn btn-success btn-sm mr-2" onclick="receiveApplication(\'' + esc(String(appId)) + '\',\'' + esc(enc) + '\');$(\'#viewApplicationModal\').modal(\'hide\')"><i class="material-icons" style="font-size:16px;vertical-align:middle">pan_tool</i> গ্রহণ করুন</button>';
    if (!isCorrectionService() && !isCancel && (st === 'RECEIVED' || st === 'APPROVED'))
        infoHtml += '<button class="btn btn-primary btn-sm mr-2" onclick="registerApplicationAction(\'' + esc(String(appId)) + '\',\'' + esc(enc) + '\');$(\'#viewApplicationModal\').modal(\'hide\')"><i class="material-icons" style="font-size:16px;vertical-align:middle">how_to_reg</i> নিবন্ধন করুন</button>';
    if (isCancel && (st === 'RECEIVED' || st === 'APPROVED'))
        infoHtml += '<button class="btn btn-primary btn-sm mr-2" onclick="registerApplicationAction(\'' + esc(String(appId)) + '\',\'' + esc(enc) + '\');$(\'#viewApplicationModal\').modal(\'hide\')"><i class="material-icons" style="font-size:16px;vertical-align:middle">how_to_reg</i> নিবন্ধন সম্পন্ন</button>';
    if (isCorrectionService() && (st === 'RECEIVED' || st === 'PAID'))
        infoHtml += '<button class="btn btn-primary btn-sm mr-2" onclick="correctApplication(\'' + esc(String(appId)) + '\',\'' + esc(enc) + '\');$(\'#viewApplicationModal\').modal(\'hide\')"><i class="material-icons" style="font-size:16px;vertical-align:middle">task_alt</i> সংশোধন সম্পন্ন</button>';
    if (!isCorrectionService() && !isCancel && st === 'REGISTERED' && enc) {
        var certLabel = getCurrentService() === 'br' ? 'জন্ম সনদ' : 'মৃত্যু সনদ';
        infoHtml += '<button class="btn btn-success btn-sm mr-2" onclick="printCertificate(\'' + esc(String(appId)) + '\',\'' + esc(enc) + '\');$(\'#viewApplicationModal\').modal(\'hide\')"><i class="material-icons" style="font-size:16px;vertical-align:middle">verified</i> ' + certLabel + '</button>';
    }
    if (!isCancel && st === 'REGISTERED' && enc)
        infoHtml += '<button class="btn btn-info btn-sm mr-2" onclick="view17DigitDoc(\'' + esc(String(appId)) + '\',\'' + esc(enc) + '\');$(\'#viewApplicationModal\').modal(\'hide\')"><i class="material-icons" style="font-size:16px;vertical-align:middle">badge</i> ১৭ ডিজিট দেখুন</button>';
    if (!isCancel && (st === 'POSSIBLE_DUPLICATE' || st === 'REQUIRES_APPROVAL_WHEN_PARENT_UNKNOWN') && enc)
        infoHtml += '<button class="btn btn-warning btn-sm mr-2" onclick="checkDuplicates(\'' + esc(enc) + '\',\'' + esc(String(appId)) + '\');$(\'#viewApplicationModal\').modal(\'hide\')"><i class="material-icons" style="font-size:16px;vertical-align:middle">content_copy</i> ডুপ্লিকেট যাচাই</button>';
    if (isCancel && st === 'RECEIVED' && enc)
        infoHtml += '<button class="btn btn-success btn-sm mr-2" onclick="approveApplication(\'' + esc(String(appId)) + '\',\'' + esc(enc) + '\',\'' + esc(String(st)) + '\');$(\'#viewApplicationModal\').modal(\'hide\')"><i class="material-icons" style="font-size:16px;vertical-align:middle">check_circle</i> অনুমোদন</button>';
    if (!isCancel && (st === 'POSSIBLE_DUPLICATE' || st === 'REQUIRES_APPROVAL_WHEN_PARENT_UNKNOWN' || st === 'REQUIRES_APPROVAL_OF_HIGHER_AUTHORITY' || st === 'PENDING_APPROVAL_FOR_NATIONALITY' || st === 'PENDING_APPROVAL_FOR_DOB' || st === 'REQUIRES_APPROVAL_OF_REMOTE_OFFICE') && enc)
        infoHtml += '<button class="btn btn-success btn-sm mr-2" onclick="approveApplication(\'' + esc(String(appId)) + '\',\'' + esc(enc) + '\',\'' + esc(String(st)) + '\');$(\'#viewApplicationModal\').modal(\'hide\')"><i class="material-icons" style="font-size:16px;vertical-align:middle">check_circle</i> অনুমোদন</button>';
    if (!isCorrectionService() && !isCancel && (st === 'APPLIED' || st === 'RECEIVED' || st === 'POSSIBLE_DUPLICATE' || st === 'REQUIRES_APPROVAL_WHEN_PARENT_UNKNOWN'))
        infoHtml += '<button class="btn btn-danger btn-sm" onclick="rejectApplication(\'' + esc(String(appId)) + '\',\'' + esc(enc) + '\');$(\'#viewApplicationModal\').modal(\'hide\')"><i class="material-icons" style="font-size:16px;vertical-align:middle">cancel</i> বাতিল করুন</button>';
    if (isCorrectionService() && (st !== 'CORRECTED' && st !== 'REJECTED'))
        infoHtml += '<button class="btn btn-danger btn-sm" onclick="rejectApplication(\'' + esc(String(appId)) + '\',\'' + esc(enc) + '\');$(\'#viewApplicationModal\').modal(\'hide\')"><i class="material-icons" style="font-size:16px;vertical-align:middle">cancel</i> বাতিল করুন</button>';
    if (isCancel && (st !== 'REGISTERED' && st !== 'REJECTED'))
        infoHtml += '<button class="btn btn-danger btn-sm" onclick="rejectApplication(\'' + esc(String(appId)) + '\',\'' + esc(enc) + '\');$(\'#viewApplicationModal\').modal(\'hide\')"><i class="material-icons" style="font-size:16px;vertical-align:middle">cancel</i> বাতিল করুন</button>';
    infoHtml += '</div>';

    $('#viewModalBody').html(infoHtml);
    wireLazyDocImages(document.getElementById('viewModalBody'));
}

window.printCurrentModal = function() {
    if (currentModalPrintableHtml) {
        $('#viewApplicationModal').modal('hide');
        openHtmlInIframe('প্রিন্ট', currentModalPrintableHtml);
        return;
    }
    window.printViewModal();
};

window.printViewModal = function() {
    if (!currentViewData) return;
    var html = buildDocumentsPageHtml(currentViewData, true);
    $('#viewApplicationModal').modal('hide');
    openHtmlInIframe('প্রিন্ট', html);
};

// ============================================================
//  মিউটেশন অ্যাকশন (Receive / Register / Approve / Reject)
// ============================================================
function doMutationAction(label, actionData, confirmText) {
    Swal.fire({
        title: label,
        text: confirmText || (label + ' করতে চান?'),
        icon: 'question',
        showCancelButton: true,
        confirmButtonText: 'হ্যাঁ, করুন',
        cancelButtonText: 'বাতিল'
    }).then(function(res) {
        if (!res.isConfirmed) return;
        var reqData = buildRequestData(actionData);
        Swal.fire({ title: 'অপেক্ষা করুন...', allowOutsideClick: false, didOpen: function(){ Swal.showLoading(); } });
        $.ajax({ url: 'proxy_list.php', type: 'POST', dataType: 'json', timeout: 45000, data: reqData })
        .done(function(r) {
            if (r && (r.error || r._error)) {
                Swal.fire('ত্রুটি', esc(r.error || r._error || (label + ' ব্যর্থ হয়েছে')), 'error');
                return;
            }
            Swal.fire('সফল!', (r && (r.message || r.msg)) || (label + ' সম্পন্ন হয়েছে'), 'success');
            loadList();
        }).fail(function(xhr) {
            var errMsg = (xhr.responseJSON && (xhr.responseJSON._error || xhr.responseJSON.error || xhr.responseJSON.message)) || (label + ' ব্যর্থ হয়েছে');
            Swal.fire('ত্রুটি', esc(errMsg), 'error');
        });
    });
}

window.receiveApplication = function(appId, enc) {
    ensureEncryptedId(appId, enc, function(encryptedId) {
        doMutationAction('গ্রহণ (Receive)', { action: 'receive', encryptedId: encryptedId }, 'এই আবেদনটি গ্রহণ করতে চান?');
    });
};

window.registerApplicationAction = function(appId, enc) {
    ensureEncryptedId(appId, enc, function(encryptedId) {
        if (getCurrentService() !== 'br') {
            doMutationAction('নিবন্ধন (Register)', { action: 'register', encryptedId: encryptedId }, 'এই আবেদনটি নিবন্ধন করতে চান? নিবন্ধনের পর ১৭ ডিজিট নম্বর তৈরি হবে।');
            return;
        }

        var todayIso = (function() {
            var d = new Date();
            var m = String(d.getMonth() + 1).padStart(2, '0');
            var day = String(d.getDate()).padStart(2, '0');
            return d.getFullYear() + '-' + m + '-' + day;
        })();

        var toDdMmYyyy = function(v) {
            v = (v || '').trim();
            if (/^\d{4}-\d{2}-\d{2}$/.test(v)) {
                var p = v.split('-');
                return p[2] + '/' + p[1] + '/' + p[0];
            }
            if (/^\d{2}\/\d{2}\/\d{4}$/.test(v)) return v;
            return v;
        };

        Swal.fire({
            title: 'নিবন্ধন (Birth Register)',
            html:
                '<div class="text-left" style="font-size:13px">'
              + '<div class="mb-2 font-weight-bold">Birth Place & DOB Verifier</div>'
              + '<input class="swal2-input" id="sw-bp-name" placeholder="নাম" style="margin:6px 0;" autocomplete="off">'
              + '<input class="swal2-input" id="sw-bp-brn" placeholder="BRN (17 digit)" style="margin:6px 0;" inputmode="numeric" autocomplete="off">'
              + '<input class="swal2-input" id="sw-bp-date" type="date" value="' + esc(todayIso) + '" style="margin:6px 0;" autocomplete="off">'
              + '<div class="mb-2 mt-3 font-weight-bold">Permanent Address Verifier</div>'
              + '<input class="swal2-input" id="sw-pa-name" placeholder="নাম" style="margin:6px 0;" autocomplete="off">'
              + '<input class="swal2-input" id="sw-pa-brn" placeholder="BRN (17 digit)" style="margin:6px 0;" inputmode="numeric" autocomplete="off">'
              + '<input class="swal2-input" id="sw-pa-date" type="date" value="' + esc(todayIso) + '" style="margin:6px 0;" autocomplete="off">'
              + '<div class="mb-2 mt-3 font-weight-bold">OTP (যদি লাগে)</div>'
              + '<input class="swal2-input" id="sw-otp" placeholder="OTP (optional)" style="margin:6px 0;" autocomplete="off">'
              + '</div>',
            showCancelButton: true,
            confirmButtonText: 'নিবন্ধন করুন',
            cancelButtonText: 'বাতিল',
            focusConfirm: false,
            preConfirm: function() {
                var bpName = ($('#sw-bp-name').val() || '').trim();
                var bpBrn  = ($('#sw-bp-brn').val() || '').replace(/\D+/g, '');
                var bpDate = ($('#sw-bp-date').val() || '').trim();
                var paName = ($('#sw-pa-name').val() || '').trim();
                var paBrn  = ($('#sw-pa-brn').val() || '').replace(/\D+/g, '');
                var paDate = ($('#sw-pa-date').val() || '').trim();
                var otp    = ($('#sw-otp').val() || '').trim();

                if (!bpName || !paName) {
                    Swal.showValidationMessage('Verifier নাম দিতে হবে');
                    return false;
                }
                if (bpBrn.length !== 17 || paBrn.length !== 17) {
                    Swal.showValidationMessage('Verifier BRN ১৭ ডিজিট হতে হবে');
                    return false;
                }
                if (!bpDate || !paDate) {
                    Swal.showValidationMessage('Verification date দিতে হবে');
                    return false;
                }
                return {
                    birthPlaceAndDobVerifierName: bpName,
                    birthPlaceAndDobVerifierBrn: bpBrn,
                    birthPlaceAndDobVerificationDate: toDdMmYyyy(bpDate),
                    permAddrVerifierName: paName,
                    permAddrVerifierBrn: paBrn,
                    permAddrVerificationDate: toDdMmYyyy(paDate),
                    otp: otp
                };
            }
        }).then(function(res) {
            if (!res.isConfirmed) return;
            var v = res.value || {};
            var actionData = $.extend({ action: 'register', encryptedId: encryptedId }, v);
            Swal.fire({ title: 'অপেক্ষা করুন...', allowOutsideClick: false, didOpen: function(){ Swal.showLoading(); } });
            $.ajax({ url: 'proxy_list.php', type: 'POST', dataType: 'json', timeout: 45000, data: buildRequestData(actionData) })
            .done(function(r) {
                if (r && (r.error || r._error)) {
                    Swal.fire('ত্রুটি', esc(r.error || r._error || 'Register ব্যর্থ হয়েছে'), 'error');
                    return;
                }
                Swal.fire('সফল!', (r && (r.message || r.msg)) || 'নিবন্ধন সম্পন্ন হয়েছে', 'success');
                loadList();
            }).fail(function(xhr) {
                var errMsg = (xhr.responseJSON && (xhr.responseJSON._error || xhr.responseJSON.error || xhr.responseJSON.message)) || 'Register ব্যর্থ হয়েছে';
                Swal.fire('ত্রুটি', esc(errMsg), 'error');
            });
        });
    });
};

window.approveApplication = function(appId, enc, status) {
    ensureEncryptedId(appId, enc, function(encryptedId) {
        doMutationAction('অনুমোদন (Approve)', { action: 'approve', status: status, encryptedId: encryptedId }, 'এই আবেদনটি অনুমোদন করতে চান?');
    });
};

window.rejectApplication = function(appId, enc) {
    Swal.fire({
        title: 'বাতিল (Reject)',
        input: 'textarea',
        inputLabel: 'বাতিলের কারণ লিখুন',
        inputPlaceholder: 'কারণ লিখুন...',
        showCancelButton: true,
        confirmButtonText: 'বাতিল করুন',
        cancelButtonText: 'ফিরে যান',
        confirmButtonColor: '#dc3545',
        inputValidator: function(value) { if (!value) return 'বাতিলের কারণ লিখতে হবে!'; }
    }).then(function(res) {
        if (!res.isConfirmed) return;
        ensureEncryptedId(appId, enc, function(encryptedId) {
            var d = { action: 'reject', encryptedId: encryptedId, causeOfRejection: res.value };
            var reqData = buildRequestData(d);
            Swal.fire({ title: 'অপেক্ষা করুন...', allowOutsideClick: false, didOpen: function(){ Swal.showLoading(); } });
            $.ajax({ url: 'proxy_list.php', type: 'POST', dataType: 'json', timeout: 45000, data: reqData })
            .done(function(r) {
                if (r && (r.error || r._error)) {
                    Swal.fire('ত্রুটি', esc(r.error || r._error || 'বাতিল ব্যর্থ হয়েছে'), 'error');
                    return;
                }
                Swal.fire('সফল!', (r && r.message) || 'বাতিল সম্পন্ন হয়েছে', 'success');
                loadList();
            })
            .fail(function(xhr) {
                var errMsg = (xhr.responseJSON && (xhr.responseJSON._error || xhr.responseJSON.error)) || 'বাতিল ব্যর্থ হয়েছে';
                Swal.fire('ত্রুটি', esc(errMsg), 'error');
            });
        });
    });
};

window.correctApplication = function(appId, enc) {
    ensureEncryptedId(appId, enc, function(encryptedId) {
        doMutationAction('সংশোধন (Correct)', { action: 'correct', encryptedId: encryptedId }, 'এই আবেদনটি সংশোধন সম্পন্ন করতে চান?');
    });
};

window.searchByApplicationId = function() {
    var searchVal = ($('#applicationSearchValue').val() || '').trim();
    if (!searchVal) { showMessage('আবেদন আইডি বা নাম দিন', 'warning'); return; }
    lastSearchValue = searchVal;
    $('#resultContainer').show();
    $('#resultTable tbody').html('<tr><td colspan="9" class="text-center"><span class="spinner-border spinner-border-sm mr-2"></span>সার্চ হচ্ছে...</td></tr>');
    var reqData = buildRequestData({ action: 'list', officeId: currentOfficeId, status: 'ALL', draw: listDraw++, start: 0, length: 100, searchValue: searchVal });
    $.ajax({ url: 'proxy_list.php', type: 'POST', dataType: 'json', timeout: 45000, data: reqData })
    .done(function(res) {
        var data = (res && res.data) ? res.data : [];
        renderTableRows(data);
        listTotal = parseInt((res && (res.recordsTotal || data.length)) || 0);
        updatePaginationUi();
        if (!data.length) showMessage('কোনো ফলাফল পাওয়া যায়নি', 'info');
    }).fail(function(xhr) {
        var errMsg = (xhr.responseJSON && xhr.responseJSON._error) || 'সার্চ ব্যর্থ হয়েছে';
        $('#resultTable tbody').html('<tr><td colspan="9" class="text-danger text-center">' + esc(errMsg) + '</td></tr>');
    });
};

// ============================================================
//  ইভেন্ট বাইন্ডিং
// ============================================================
$('#pageSizeSelect').change(function() { listLength = parseInt($(this).val()); listStart = 0; if (currentOfficeId) loadList(); });
$('#prevPageBtn').click(function() { if (listStart > 0) { listStart -= listLength; loadList(); } });
$('#nextPageBtn').click(function() { if ((listStart + listLength) < listTotal) { listStart += listLength; loadList(); } });
$('#applicationStatus').change(function() { if (currentOfficeId) { lastListStatus = $(this).val(); lastSearchValue = ''; listStart = 0; loadList(); } });
$('.summary-card').click(function() { var st = $(this).data('status'); if (st) $('#applicationStatus').val(st).trigger('change'); });
$('#applicationSearchValue').keypress(function(e) { if (e.which === 13) searchByApplicationId(); });
// টোকেন ইনপুট পরিবর্তনে স্ট্যাটাস বার আপডেট
$('#csrfTokenInput,#sessionCookieInput').on('input', function() { updateTokenStatusBar(); });
</script>

</body>
</html>
