<?php
/* ============================================================================
   THE USER LIST ENGINE
   ----------------------------------------------------------------------------
   One list, six front doors. users_free.php, users_pro.php, users_seller.php
   and the rest are three-line files that set an audience and include this; the
   table, the filters, the modals and the exports live here once.

   The audience is set by the page, not by the query string, so a member of
   staff who has been given only the Free User page cannot type ?role=seller
   and see sellers. That is the whole reason the pages are separate.

   A page sets, before including:
       $WB_SCOPE     all | free | pro | seller | employee | admin | deleted
       $WB_ACL_KEY   which permission opens it   (default users.view)
       $WB_TITLE     what to call it             (default from the scope)
   ============================================================================ */

/* This file lives in admin/includes/, one level below the pages that include
   it, so every path is anchored to the project root instead of being counted
   in ../ from wherever we happen to be. */
$WB_ROOT  = dirname(__DIR__, 2);
$WB_ADMIN = dirname(__DIR__);

require_once $WB_ROOT . '/config.php';
require_once $WB_ROOT . '/db.php';
require_once $WB_ROOT . '/includes/functions.php';
require_once $WB_ROOT . '/includes/Language.php';
require_once $WB_ROOT . '/includes/wallet.php';
require_once $WB_ROOT . '/includes/admin_list.php';
require_once $WB_ROOT . '/includes/notify.php';
require_once $WB_ROOT . '/includes/kyc.php';
require_once $WB_ROOT . '/includes/acl.php';

if (!isLoggedIn() || !isAdmin()) { redirect('login.php'); }
acl_ensure_schema($db);

/* Which list is this, who may open it, and what does it call itself. A page
   that sets no scope (user_list.php) still honours ?role= so every old link
   keeps working. */
$WB_SCOPE   = isset($WB_SCOPE) ? strtolower(trim((string)$WB_SCOPE)) : '';
$WB_LOCKED  = ($WB_SCOPE !== '');
if (!$WB_LOCKED && isset($_GET['role'])) { $WB_SCOPE = strtolower(trim((string)$_GET['role'])); }

/* An audience is: label, icon, user types, subscription, recycle bin, and any
   extra condition that cannot be said with the first five.

   Employees and Admins are both `user_type = 'admin'` in the table — what
   separates them is `staff_level`. The owner account has no level and no role
   at all, so it counts as an admin; otherwise a brand new site would show its
   only account under Employees. */
$WB_LVL_BOSS = "("
    . "LOWER(COALESCE(u.staff_level,'')) IN ('admin','superadmin')"      /* set on the account   */
    . " OR u.role_id IS NULL OR u.role_id = 0"                            /* the owner, no role   */
    . " OR EXISTS (SELECT 1 FROM roles ro WHERE ro.id = u.role_id AND ("  /* the role says so     */
    .     "LOWER(COALESCE(ro.level,'')) = 'admin'"
    .     " OR ro.permissions LIKE '%\"all\"%'))"
    . ")";

$WB_AUDIENCE = [
    'all'      => ['All Users',    'fa-layer-group',   'customer,seller,admin', '',    '',  ''],
    'user'     => ['Users',        'fa-user',          'customer',              '',    '',  ''],
    'free'     => ['Free Users',   'fa-user',          'customer',              'no',  '',  ''],
    'pro'      => ['Pro Users',    'fa-gem',           'customer',              'yes', '',  ''],
    'seller'   => ['Sellers',      'fa-store',         'seller',                '',    '',  ''],
    'employee' => ['Employees',    'fa-user-tie',      'admin',                 '',    '',  'AND NOT ' . $WB_LVL_BOSS],
    'admin'    => ['Admins',       'fa-shield-halved', 'admin',                 '',    '',  'AND ' . $WB_LVL_BOSS],
    'staff'    => ['Staff',        'fa-shield-halved', 'admin',                 '',    '',  ''],
    'deleted'  => ['Deleted Users','fa-trash-can',     'customer,seller,admin', '',    '1', ''],
];
if (!isset($WB_AUDIENCE[$WB_SCOPE])) { $WB_SCOPE = 'all'; }
$WB_AUD = $WB_AUDIENCE[$WB_SCOPE];

$WB_ACL_KEY = isset($WB_ACL_KEY) && $WB_ACL_KEY !== '' ? $WB_ACL_KEY : 'users.view';
acl_guard($WB_ACL_KEY);

/* self-links have to point at whichever front door we came through */
$UL_PAGE = basename($_SERVER['PHP_SELF']);
if ($UL_PAGE === '' || substr($UL_PAGE, -4) !== '.php') { $UL_PAGE = 'user_list.php'; }

/* each list remembers its own filters, so a search on Sellers does not follow
   you to Free Users */
$UL_FKEY = 'users_' . $WB_SCOPE;

/* ---------------------------------------------------------------------------
   Column level access. A staff account only sees the columns its role — or its
   own personal access — allows. ul_col('balance') answers for one column, and
   is used on both the header cell and the body cell so the table never ends up
   ragged. UL_COLS is what is left, and drives the "no users found" colspan.
   --------------------------------------------------------------------------- */
if (!function_exists('ul_col')) {
    function ul_col($c) { return !function_exists('acl_col') || acl_col('users', $c); }
}

/* ---------------------------------------------------------------------------
   WHAT MAY THIS ACCOUNT DO ON THIS LIST?

   Every one of these keys has been tickable on the Roles screen for a while,
   but nothing on this page ever asked. So "do not let them delete users" was a
   tick that changed nothing — the Delete button was drawn for everybody and the
   POST behind it ran for everybody.

   ul_can() is now asked twice for each thing: once to decide whether to draw
   the button, and once at the top of the handler behind it. The second check is
   the one that matters — a button that is not drawn can still be posted by
   hand, and the answer to that has to be no.
   --------------------------------------------------------------------------- */
if (!function_exists('ul_can')) {
    function ul_can($action) { return !function_exists('acl_can') || acl_can('users.' . $action); }
    function ul_need($action) {
        if (ul_can($action)) { return; }
        if (function_exists('acl_deny')) { acl_deny('users.' . $action); }
        http_response_code(403);
        exit('Not allowed.');
    }
}
$UL_COLS = 1; /* the tick box is always there */
foreach (['profile','details','address','region','type','created_by','kyc','subscription',
          'balance','transfer','quick','notes','update','action'] as $__c) {
    /* Transfer is drawn only when the account may actually move money, so it
       has to be counted the same way or the "no users found" row spans one
       column too many and the table goes ragged. */
    if ($__c === 'transfer' && !ul_can('wallet')) { continue; }
    if (ul_col($__c)) { $UL_COLS++; }
}

$lang = new Language($db);
$current_lang = $lang->getCurrentLanguage();
$user_id = $_SESSION['user_id'];

$success_msg = '';
$error_msg = '';
if (isset($_SESSION['flash_success'])) { $success_msg = $_SESSION['flash_success']; unset($_SESSION['flash_success']); }
if (isset($_SESSION['flash_error']))   { $error_msg   = $_SESSION['flash_error'];   unset($_SESSION['flash_error']); }

// --- Auto-create required tables/columns if missing (no manual migration needed) ---
$__conn = $db->getConnection();
$__ddl = [
    "CREATE TABLE IF NOT EXISTS user_notes (
        id INT AUTO_INCREMENT PRIMARY KEY, user_id INT NOT NULL, title VARCHAR(255) NOT NULL,
        description TEXT NULL, created_by INT NULL, created_by_name VARCHAR(120) NULL,
        created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
    "CREATE TABLE IF NOT EXISTS user_update_history (
        id INT AUTO_INCREMENT PRIMARY KEY, user_id INT NOT NULL, field_label VARCHAR(120) NOT NULL,
        old_value TEXT NULL, new_value TEXT NULL, updated_by INT NULL, updated_by_name VARCHAR(120) NULL,
        updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
];
foreach ($__ddl as $__q) { try { $__conn->query($__q); } catch (\Throwable $e) { /* ignore */ } }
$__cols = ['village' => 'VARCHAR(150)', 'post_office' => 'VARCHAR(150)', 'block_city' => 'VARCHAR(150)', 'landmark' => 'VARCHAR(255)',
           /* soft delete — also created by neosspmigration.php */
           'deleted_at' => 'TIMESTAMP NULL DEFAULT NULL', 'deleted_by' => 'INT', 'delete_reason' => 'VARCHAR(255)',
           /* who opened this account — also created by testsmigration.php */
           'created_by' => 'INT', 'created_by_name' => 'VARCHAR(120)', 'created_via' => "VARCHAR(20) NULL DEFAULT 'self'"];
foreach ($__cols as $__c => $__type) {
    try {
        $__r = $__conn->query("SHOW COLUMNS FROM users LIKE '$__c'");
        if ($__r && $__r->num_rows === 0) {
            $__def = (stripos($__type, 'NULL') === false) ? ($__type . ' NULL') : $__type;
            $__conn->query("ALTER TABLE users ADD COLUMN `$__c` $__def");
        }
    } catch (\Throwable $e) { /* ignore */ }
}
kyc_ensure_schema($db); // create kyc_details table if missing

// Current logged-in admin/staff (used for "created by" / "updated by" logging)
$me_row = $db->select("SELECT id, name FROM users WHERE id = ?", [$user_id]);
$me = !empty($me_row) ? $me_row[0] : ['id' => $user_id, 'name' => 'Admin'];

/* staff roles, used by the "Add User" form when the type is Staff / Admin */
$ul_roles = [];
try { $ul_roles = $db->select("SELECT id, name FROM roles ORDER BY name ASC"); } catch (\Throwable $e) {}

/* After a POST we come back to the SAME page of the list instead of jumping
   back to page 1 (the filters themselves are remembered in the session). */
$UL_SELF = $UL_PAGE . ((isset($_GET['p']) && (int)$_GET['p'] > 1) ? '?p=' . (int)$_GET['p'] : '');

/* ============================================================
   AJAX (JSON) ENDPOINTS  — must run before any HTML output
   ============================================================ */
if (isset($_GET['ajax'])) {
    header('Content-Type: application/json');
    $uid = intval($_GET['uid'] ?? 0);
    if ($_GET['ajax'] === 'notes') {
        echo json_encode($db->select("SELECT * FROM user_notes WHERE user_id = ? ORDER BY created_at DESC", [$uid]));
    } elseif ($_GET['ajax'] === 'history') {
        echo json_encode($db->select("SELECT * FROM user_update_history WHERE user_id = ? ORDER BY updated_at DESC", [$uid]));
    } elseif ($_GET['ajax'] === 'user') {
        $r = $db->select("SELECT id,name,mobile,call_number,whatsapp_number,email,gender,state,district,pincode,village,post_office,block_city,landmark,profile_pic,user_type,status,is_subscribed FROM users WHERE id = ?", [$uid]);
        if (!empty($r)) {
            /* Alpine <select> values are strings — normalise so the current
               value is pre-selected in the edit form. */
            $r[0]['status']        = (string)(int)($r[0]['status'] ?? 1);
            $r[0]['is_subscribed'] = (string)(int)($r[0]['is_subscribed'] ?? 0);
        }
        echo json_encode(!empty($r) ? $r[0] : null);
    } elseif ($_GET['ajax'] === 'kyc') {
        $r = $db->select("SELECT * FROM kyc_details WHERE user_id = ?", [$uid]);
        echo json_encode(!empty($r) ? $r[0] : null);
    } elseif ($_GET['ajax'] === 'adminkyc') {
        echo json_encode(kyc_get_data($db, $uid)); // full KYC (prefilled if none yet)
    } else {
        echo json_encode(['error' => 'unknown']);
    }
    exit;
}

/* ============================================================
   POST HANDLERS  (only features that the current system supports)
   ============================================================ */

// --- Add a note against a user ---
if (isset($_POST['add_note'])) {
    ul_need('note');   /* writing a note */
    $tid   = intval($_POST['target_user_id']);
    $title = sanitize($_POST['note_title'] ?? '');
    $desc  = sanitize($_POST['note_description'] ?? '');
    if ($tid > 0 && $title !== '') {
        $db->insert("INSERT INTO user_notes (user_id, title, description, created_by, created_by_name) VALUES (?, ?, ?, ?, ?)",
            [$tid, $title, $desc, $me['id'], $me['name']]);
        $_SESSION['flash_success'] = "Note added successfully!";
    } else {
        $_SESSION['flash_error'] = "Note title is required.";
    }
    redirect($UL_SELF);
}

// --- Admin: save full KYC details for a user (from the Update modal) ---
if (isset($_POST['admin_kyc_save'])) {
    ul_need('kyc');   /* editing a KYC record */
    $tid = intval($_POST['target_user_id']);
    if ($tid > 0) {
        kyc_admin_save($db, $tid, '../uploads/kyc/', $me);
        $_SESSION['flash_success'] = "KYC details updated successfully!";
    }
    redirect($UL_SELF);
}

// --- KYC approve / reject (logged to update history) ---
if (isset($_POST['kyc_action'])) {
    ul_need('kyc');   /* approving or rejecting KYC */
    $tid    = intval($_POST['target_user_id']);
    $act    = $_POST['kyc_action']; // 'approved' or 'rejected'
    $remark = sanitize($_POST['kyc_remark'] ?? '');
    if (in_array($act, ['approved', 'rejected'])) {
        $db->insert("UPDATE kyc_details SET status = ?, admin_remark = ? WHERE user_id = ?", [$act, $remark, $tid]);
        $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'KYC Status', 'pending', ?, ?, ?)",
            [$tid, ucfirst($act) . ($remark ? " ($remark)" : ''), $me['id'], $me['name']]);
        $_SESSION['flash_success'] = "KYC " . ucfirst($act) . " successfully!";
    }
    redirect($UL_SELF);
}

/* ==========================================================================
   CREATE A NEW USER FROM THE ADMIN PANEL
   Everything the list shows can be filled in here. The account is stamped
   with `created_by` / `created_by_name`, so the list always shows which
   admin or staff member opened it.
   ========================================================================== */
if (isset($_POST['create_user'])) {
    ul_need('create');   /* adding an account */
    $nu_name   = sanitize($_POST['name'] ?? '');
    $nu_mobile = preg_replace('/[^0-9]/', '', (string)($_POST['mobile'] ?? ''));
    $nu_email  = sanitize($_POST['email'] ?? '');
    $nu_gender = in_array($_POST['gender'] ?? '', ['male', 'female', 'other'], true) ? $_POST['gender'] : 'male';
    $nu_type   = in_array($_POST['user_type'] ?? '', ['customer', 'seller', 'admin'], true) ? $_POST['user_type'] : 'customer';
    $nu_pass   = (string)($_POST['password'] ?? '');
    $nu_pass2  = (string)($_POST['password_confirm'] ?? '');
    $nu_status = ((int)($_POST['status'] ?? 1) === 1) ? 1 : 0;
    $nu_sub    = ((int)($_POST['is_subscribed'] ?? 0) === 1) ? 1 : 0;
    $nu_role   = (int)($_POST['role_id'] ?? 0);
    $nu_biz    = sanitize($_POST['business_name'] ?? '');

    /* referrer — accepts WBMCZ0004, 0004 or a plain user id */
    $nu_ref = null;
    $ref_in = strtoupper(trim((string)($_POST['referral_code'] ?? '')));
    if ($ref_in !== '') {
        $ref_id = (strpos($ref_in, 'WBMCZ') === 0) ? (int)str_replace('WBMCZ', '', $ref_in) : (int)preg_replace('/[^0-9]/', '', $ref_in);
        if ($ref_id > 0) {
            $rchk = $db->select("SELECT id FROM users WHERE id = ?", [$ref_id]);
            if (!empty($rchk)) { $nu_ref = $ref_id; }
        }
    }

    /* ---- validation ---- */
    $errs = [];
    if ($nu_name === '')                              { $errs[] = 'Name is required.'; }
    if (strlen($nu_mobile) < 10)                      { $errs[] = 'A valid 10-digit mobile number is required.'; }
    if (strlen($nu_pass) < 6)                         { $errs[] = 'The password must be at least 6 characters.'; }
    if ($nu_pass !== $nu_pass2)                       { $errs[] = 'The two passwords do not match.'; }
    if ($ref_in !== '' && $nu_ref === null)           { $errs[] = 'That referral code does not belong to any member — leave it blank if you are not sure.'; }
    if ($nu_email !== '' && !filter_var($nu_email, FILTER_VALIDATE_EMAIL)) { $errs[] = 'The email address is not valid.'; }
    if (empty($errs)) {
        $dup = $db->select("SELECT id, name FROM users WHERE mobile = ?", [$nu_mobile]);
        if (!empty($dup)) { $errs[] = 'Mobile ' . $nu_mobile . ' is already registered (ID ' . (int)$dup[0]['id'] . ' — ' . $dup[0]['name'] . ').'; }
    }

    if (!empty($errs)) {
        $_SESSION['flash_error'] = implode(' ', $errs);
        redirect($UL_SELF);
    }

    $new_id = $db->insert(
        "INSERT INTO users (name, mobile, call_number, whatsapp_number, email, gender, password, user_type,
                            status, is_subscribed, referred_by, role_id,
                            state, district, pincode, village, post_office, block_city, landmark)
         VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
        [
            $nu_name, $nu_mobile,
            sanitize($_POST['call_number'] ?? ''), sanitize($_POST['whatsapp_number'] ?? ''),
            $nu_email, $nu_gender, password_hash($nu_pass, PASSWORD_DEFAULT), $nu_type,
            $nu_status, $nu_sub, $nu_ref, ($nu_type === 'admin' && $nu_role > 0) ? $nu_role : null,
            sanitize($_POST['state'] ?? ''), sanitize($_POST['district'] ?? ''), sanitize($_POST['pincode'] ?? ''),
            sanitize($_POST['village'] ?? ''), sanitize($_POST['post_office'] ?? ''),
            sanitize($_POST['block_city'] ?? ''), sanitize($_POST['landmark'] ?? ''),
        ]
    );

    if (!$new_id) {
        $_SESSION['flash_error'] = 'The account could not be created. Please try again.';
        redirect($UL_SELF);
    }

    /* who opened the account */
    try {
        $db->insert("UPDATE users SET created_by = ?, created_by_name = ?, created_via = 'admin' WHERE id = ?",
                    [$me['id'], $me['name'], $new_id]);
    } catch (\Throwable $e) { /* columns arrive with testsmigration.php */ }

    /* a seller also needs its row in `sellers` */
    if ($nu_type === 'seller') {
        try {
            $db->insert("INSERT INTO sellers (user_id, name, phone, email, business_name, status) VALUES (?, ?, ?, ?, ?, 1)",
                        [$new_id, $nu_name, $nu_mobile, $nu_email, ($nu_biz !== '' ? $nu_biz : $nu_name . ' Business')]);
        } catch (\Throwable $e) {}
    }

    /* audit trail + welcome note */
    try {
        $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name)
                     VALUES (?, 'Account Created', '', ?, ?, ?)",
                    [$new_id, 'Added from the admin panel by ' . $me['name'], $me['id'], $me['name']]);
    } catch (\Throwable $e) {}

    if (function_exists('notify_send')) {
        try {
            notify_send($db, $new_id, 'Welcome to ' . getSetting('company_name', 'WBMCZ'),
                        'Your account has been created by our team. Log in with your mobile number ' . $nu_mobile . '.');
        } catch (\Throwable $e) {}
    }

    $_SESSION['flash_success'] = 'User created — ' . $nu_name . ' (' . userCode($new_id) . ', ID ' . (int)$new_id . '). Added by ' . $me['name'] . '.';
    redirect($UL_SELF);
}

// --- Update user details (logs every changed field to update history) ---
if (isset($_POST['update_user'])) {
    ul_need('edit');   /* editing an account */
    $tid = intval($_POST['target_user_id']);
    $old_row = $db->select("SELECT * FROM users WHERE id = ?", [$tid]);
    if (!empty($old_row)) {
        $old = $old_row[0];
        $fields = [
            'name' => 'Name', 'mobile' => 'Mobile', 'call_number' => 'Call Number',
            'whatsapp_number' => 'WhatsApp Number', 'email' => 'Email', 'gender' => 'Gender',
            'state' => 'State', 'district' => 'District', 'pincode' => 'Pincode',
            'village' => 'Village', 'post_office' => 'Post Office', 'block_city' => 'Block/City', 'landmark' => 'Landmark',
        ];
        $changed = 0;
        foreach ($fields as $col => $label) {
            if (!isset($_POST[$col])) continue;
            $newv = sanitize($_POST[$col]);
            $oldv = isset($old[$col]) ? (string)$old[$col] : '';
            if ($oldv !== (string)$newv) {
                $db->insert("UPDATE users SET `$col` = ? WHERE id = ?", [$newv, $tid]); // $col is from fixed whitelist
                $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, ?, ?, ?, ?, ?)",
                    [$tid, $label, $oldv, $newv, $me['id'], $me['name']]);
                $changed++;
            }
        }
        /* ---- account fields (type / status / subscription) -------------
           An admin can never block or demote their own account from here. */
        $self_edit = ((int)$tid === (int)$me['id']);
        if ($self_edit) { unset($_POST['user_type'], $_POST['status']); }

        if (isset($_POST['user_type'])) {
            $nt = sanitize($_POST['user_type']);
            if (in_array($nt, ['customer', 'seller', 'admin'], true) && $nt !== (string)$old['user_type']) {
                $db->insert("UPDATE users SET user_type = ? WHERE id = ?", [$nt, $tid]);
                if ($nt === 'seller') {                      // keep the sellers table in sync
                    $chk = $db->select("SELECT id FROM sellers WHERE user_id = ?", [$tid]);
                    if (empty($chk)) {
                        $db->insert("INSERT INTO sellers (user_id, name, phone, email, business_name, status) VALUES (?, ?, ?, ?, ?, 1)",
                            [$tid, $old['name'], $old['mobile'], $old['email'], $old['name'] . ' Business']);
                    } else {
                        $db->insert("UPDATE sellers SET status = 1 WHERE user_id = ?", [$tid]);
                    }
                }
                $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'User Type', ?, ?, ?, ?)",
                    [$tid, ucfirst((string)$old['user_type']), ucfirst($nt), $me['id'], $me['name']]);
                $changed++;
            }
        }
        if (isset($_POST['status'])) {
            $ns = ((int)$_POST['status'] === 1) ? 1 : 0;
            if ($ns !== (int)($old['status'] ?? 1)) {
                $db->insert("UPDATE users SET status = ? WHERE id = ?", [$ns, $tid]);
                $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'Account Status', ?, ?, ?, ?)",
                    [$tid, ((int)($old['status'] ?? 1) === 1 ? 'Active' : 'Blocked'), ($ns === 1 ? 'Active' : 'Blocked'), $me['id'], $me['name']]);
                $changed++;
            }
        }
        if (isset($_POST['is_subscribed'])) {
            $nb = ((int)$_POST['is_subscribed'] === 1) ? 1 : 0;
            if ($nb !== (int)($old['is_subscribed'] ?? 0)) {
                $db->insert("UPDATE users SET is_subscribed = ? WHERE id = ?", [$nb, $tid]);
                $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'Subscription', ?, ?, ?, ?)",
                    [$tid, ((int)($old['is_subscribed'] ?? 0) === 1 ? 'Yes' : 'No'), ($nb === 1 ? 'Yes' : 'No'), $me['id'], $me['name']]);
                $changed++;
            }
        }

        // Optional profile picture change
        if (!empty($_FILES['profile_pic']['name']) && is_uploaded_file($_FILES['profile_pic']['tmp_name'])) {
            $ext = strtolower(pathinfo($_FILES['profile_pic']['name'], PATHINFO_EXTENSION));
            if (in_array($ext, ['jpg', 'jpeg', 'png', 'webp', 'gif'])) {
                $fname = 'user_' . $tid . '_' . time() . '.' . $ext;
                if (move_uploaded_file($_FILES['profile_pic']['tmp_name'], '../uploads/profiles/' . $fname)) {
                    $db->insert("UPDATE users SET profile_pic = ? WHERE id = ?", [$fname, $tid]);
                    $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'Profile Picture', ?, ?, ?, ?)",
                        [$tid, $old['profile_pic'] ?? '', $fname, $me['id'], $me['name']]);
                    $changed++;
                }
            }
        }
        $_SESSION['flash_success'] = $changed > 0 ? "User updated ($changed field" . ($changed > 1 ? 's' : '') . " changed)." : "No changes were made.";
    }
    redirect($UL_SELF);
}

/* --- SOFT DELETE a single user -------------------------------------------
   The row is never removed: `deleted_at` is stamped, so orders, wallet rows,
   commissions and referral links all stay intact and the account can be put
   back with one click from User Management → Deleted Users. ---------------- */
if (isset($_POST['delete_user'])) {
    ul_need('delete');   /* deleting an account */
    $tid    = (int)$_POST['target_user_id'];
    $reason = trim(sanitize($_POST['delete_reason'] ?? ''));

    if ($tid === (int)$me['id']) {
        $_SESSION['flash_error'] = "You cannot delete your own account.";
    } else {
        $row = $db->select("SELECT id, name, user_type, deleted_at FROM users WHERE id = ?", [$tid]);
        if (empty($row)) {
            $_SESSION['flash_error'] = "User not found.";
        } elseif (!empty($row[0]['deleted_at'])) {
            $_SESSION['flash_error'] = "That user is already deleted.";
        } else {
            $db->insert("UPDATE users SET deleted_at = NOW(), deleted_by = ?, delete_reason = ?, status = 0 WHERE id = ?",
                        [$me['id'], $reason, $tid]);
            if ((string)$row[0]['user_type'] === 'seller') {
                try { $db->insert("UPDATE sellers SET status = 0 WHERE user_id = ?", [$tid]); } catch (\Throwable $e) {}
            }
            $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'Account Deleted', 'Active', ?, ?, ?)",
                        [$tid, ('Deleted' . ($reason ? " — $reason" : '')), $me['id'], $me['name']]);
            $_SESSION['flash_success'] = 'User "' . $row[0]['name'] . '" moved to Deleted Users. You can restore it any time.';
        }
    }
    redirect($UL_SELF);
}

/* --- RESTORE a soft-deleted user ----------------------------------------- */
if (isset($_POST['restore_user'])) {
    ul_need('restore');   /* restoring a deleted account */
    $tid = (int)$_POST['target_user_id'];
    $row = $db->select("SELECT id, name, user_type FROM users WHERE id = ?", [$tid]);
    if (!empty($row)) {
        $db->insert("UPDATE users SET deleted_at = NULL, deleted_by = NULL, delete_reason = NULL, status = 1 WHERE id = ?", [$tid]);
        if ((string)$row[0]['user_type'] === 'seller') {
            try { $db->insert("UPDATE sellers SET status = 1 WHERE user_id = ?", [$tid]); } catch (\Throwable $e) {}
        }
        $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'Account Restored', 'Deleted', 'Active', ?, ?)",
                    [$tid, $me['id'], $me['name']]);
        $_SESSION['flash_success'] = 'User "' . $row[0]['name'] . '" restored.';
    }
    redirect($UL_SELF);
}

/* --- BULK ACTIONS on the rows ticked in the list -------------------------
   The ids arrive as a comma separated list in a single hidden field, because
   the table rows already contain their own <form> elements and HTML does not
   allow one form inside another.
   ------------------------------------------------------------------------ */
if (isset($_POST['bulk_action'])) {
    /* One bar, several different powers behind it — so the key is chosen by
       which button was pressed, not by the bar as a whole. */
    $__bulk_needs = [
        'activate' => 'block', 'suspend' => 'block',
        'make_customer' => 'edit', 'make_seller' => 'edit',
        'subscribe' => 'upgrade', 'unsubscribe' => 'upgrade',
        'delete' => 'delete', 'restore' => 'restore',
        /* wiping a row for good is its own permission — somebody who may move
           an account to the bin should not automatically be able to burn it */
        'purge' => 'purge',
    ];
    ul_need($__bulk_needs[(string)($_POST['bulk_action'] ?? '')] ?? 'edit');
    $bulk_ids = array_values(array_unique(array_filter(
        array_map('intval', explode(',', (string)($_POST['bulk_ids'] ?? ''))),
        function ($v) { return $v > 0; }
    )));
    $act  = sanitize($_POST['bulk_action']);
    $done = 0; $skipped = 0;

    foreach ($bulk_ids as $bid) {
        $row = $db->select("SELECT id, name, mobile, email, user_type, status, is_subscribed, deleted_at FROM users WHERE id = ?", [$bid]);
        if (empty($row)) { continue; }
        $r = $row[0];

        /* never let an admin lock themselves out, and never demote staff */
        $is_self  = ((int)$bid === (int)$me['id']);
        $is_staff = ((string)$r['user_type'] === 'admin');

        switch ($act) {
            case 'activate':
                if ((int)($r['status'] ?? 1) === 1) { break; }
                $db->insert("UPDATE users SET status = 1 WHERE id = ?", [$bid]);
                $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'Account Status', 'Blocked', 'Active', ?, ?)", [$bid, $me['id'], $me['name']]);
                $done++;
                break;

            case 'suspend':
                if ($is_self) { $skipped++; break; }
                if ((int)($r['status'] ?? 1) === 0) { break; }
                $db->insert("UPDATE users SET status = 0 WHERE id = ?", [$bid]);
                $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'Account Status', 'Active', 'Blocked', ?, ?)", [$bid, $me['id'], $me['name']]);
                $done++;
                break;

            case 'make_customer':
            case 'make_seller':
                if ($is_staff) { $skipped++; break; }
                $nt = ($act === 'make_seller') ? 'seller' : 'customer';
                if ((string)$r['user_type'] === $nt) { break; }
                $db->insert("UPDATE users SET user_type = ? WHERE id = ?", [$nt, $bid]);
                if ($nt === 'seller') {
                    $chk = $db->select("SELECT id FROM sellers WHERE user_id = ?", [$bid]);
                    if (empty($chk)) {
                        $db->insert("INSERT INTO sellers (user_id, name, phone, email, business_name, status) VALUES (?, ?, ?, ?, ?, 1)",
                            [$bid, $r['name'], $r['mobile'], $r['email'], $r['name'] . ' Business']);
                    } else {
                        $db->insert("UPDATE sellers SET status = 1 WHERE user_id = ?", [$bid]);
                    }
                }
                $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'User Type', ?, ?, ?, ?)",
                    [$bid, ucfirst((string)$r['user_type']), ucfirst($nt), $me['id'], $me['name']]);
                $done++;
                break;

            /* ------------------------------------------------------------
               PERMANENT DELETE

               The row goes from `users` for good. Everything attached to it —
               orders, wallet history, commission — is left alone on purpose:
               those are the company's record of money that changed hands, and
               they should not vanish because somebody tidied up an account.

               Only rows already in the bin can be erased, so it always takes
               two deliberate steps. There is no single click anywhere that
               turns a live account into nothing.
               ------------------------------------------------------------ */
            case 'purge':
                if ($is_self) { $skipped++; break; }
                if (empty($r['deleted_at'])) { $skipped++; break; }   /* not in the bin */
                try {
                    $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name)
                                 VALUES (?, 'Account Erased', ?, 'Permanently deleted', ?, ?)",
                        [$bid, (string)$r['name'] . ' · ' . (string)$r['mobile'], $me['id'], $me['name']]);
                } catch (\Throwable $e) {}
                try {
                    $db->insert("DELETE FROM users WHERE id = ? AND deleted_at IS NOT NULL", [$bid]);
                    $done++;
                } catch (\Throwable $e) { $skipped++; }
                break;

            case 'delete':
                if ($is_self) { $skipped++; break; }
                if (!empty($r['deleted_at'])) { break; }
                $db->insert("UPDATE users SET deleted_at = NOW(), deleted_by = ?, delete_reason = 'Bulk delete', status = 0 WHERE id = ?", [$me['id'], $bid]);
                if ((string)$r['user_type'] === 'seller') {
                    try { $db->insert("UPDATE sellers SET status = 0 WHERE user_id = ?", [$bid]); } catch (\Throwable $e) {}
                }
                $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'Account Deleted', 'Active', 'Deleted (bulk)', ?, ?)", [$bid, $me['id'], $me['name']]);
                $done++;
                break;

            case 'restore':
                if (empty($r['deleted_at'])) { break; }
                $db->insert("UPDATE users SET deleted_at = NULL, deleted_by = NULL, delete_reason = NULL, status = 1 WHERE id = ?", [$bid]);
                if ((string)$r['user_type'] === 'seller') {
                    try { $db->insert("UPDATE sellers SET status = 1 WHERE user_id = ?", [$bid]); } catch (\Throwable $e) {}
                }
                $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'Account Restored', 'Deleted', 'Active', ?, ?)", [$bid, $me['id'], $me['name']]);
                $done++;
                break;

            case 'subscribe':
            case 'unsubscribe':
                $nb = ($act === 'subscribe') ? 1 : 0;
                if ((int)($r['is_subscribed'] ?? 0) === $nb) { break; }
                $db->insert("UPDATE users SET is_subscribed = ? WHERE id = ?", [$nb, $bid]);
                $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'Subscription', ?, ?, ?, ?)",
                    [$bid, ($nb ? 'No' : 'Yes'), ($nb ? 'Yes' : 'No'), $me['id'], $me['name']]);
                $done++;
                break;
        }
    }

    $_SESSION['flash_success'] = $done . ' user(s) updated' . ($skipped ? ", $skipped skipped (protected account)" : '') . '.';
    redirect($UL_SELF);
}

// --- Activate / Suspend user (existing capability: users.status) ---
if (isset($_POST['toggle_status'])) {
    ul_need('block');   /* blocking or unblocking */
    $tid = sanitize($_POST['target_user_id']);
    $cur = sanitize($_POST['current_status']);
    $new = ($cur == 1) ? 0 : 1;
    $db->insert("UPDATE users SET status = ? WHERE id = ?", [$new, $tid]);
    $_SESSION['flash_success'] = 'Status updated successfully!';
    redirect($UL_SELF);
}

// --- Change role: Customer / Seller (existing capability in users.php) ---
if (isset($_POST['change_role'])) {
    ul_need('edit');   /* changing a staff role */
    $tid = sanitize($_POST['target_user_id']);
    $new_role = sanitize($_POST['new_role']); // 'customer' or 'seller'
    if (in_array($new_role, ['customer', 'seller'])) {
        $db->insert("UPDATE users SET user_type = ? WHERE id = ?", [$new_role, $tid]);
        if ($new_role == 'seller') {
            $check = $db->select("SELECT id FROM sellers WHERE user_id = ?", [$tid]);
            if (empty($check)) {
                $u = $db->select("SELECT * FROM users WHERE id = ?", [$tid])[0];
                $db->insert("INSERT INTO sellers (user_id, name, phone, email, business_name, status) VALUES (?, ?, ?, ?, ?, 1)",
                    [$tid, $u['name'], $u['mobile'], $u['email'], $u['name'] . ' Business']);
            } else {
                $db->insert("UPDATE sellers SET status = 1 WHERE user_id = ?", [$tid]);
            }
        }
        $_SESSION['flash_success'] = "User type changed to " . ucfirst($new_role) . " successfully!";
        redirect($UL_SELF);
    }
}

// --- Wallet credit / debit with a mandatory reason ---
if (isset($_POST['wallet_transfer'])) {
    ul_need('wallet');   /* moving money */
    $tid     = intval($_POST['target_user_id']);
    $amount  = round(floatval($_POST['transfer_amount']), 2);
    $action  = ($_POST['transfer_action'] ?? 'credit') === 'debit' ? 'debit' : 'credit';
    $wallet  = ($_POST['transfer_wallet'] ?? 'main') === 'virtual' ? WALLET_VIRTUAL : WALLET_MAIN;
    $reason  = trim(sanitize($_POST['transfer_reason'] ?? ''));
    $note    = trim(sanitize($_POST['transfer_note'] ?? ''));

    $full_reason = $reason . ($note !== '' ? ' — ' . $note : '');

    if ($tid <= 0 || $amount <= 0) {
        $_SESSION['flash_error'] = "Please enter a valid amount.";
    } elseif ($reason === '') {
        $_SESSION['flash_error'] = "A reason is required for every credit or debit.";
    } elseif ($action === 'credit') {
        wallet_credit($db, $tid, $wallet, $amount, [
            'category'    => 'admin',
            'description' => 'Admin credit — ' . $full_reason,
            'created_by'  => $user_id,
        ]);
        try {
            $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'Wallet Credit', '', ?, ?, ?)",
                [$tid, '₹' . number_format($amount, 2) . ' (' . ($wallet === WALLET_VIRTUAL ? 'virtual' : 'main') . ') — ' . $full_reason, $user_id, $me['name'] ?? 'Admin']);
        } catch (\Throwable $e) {}
        if (function_exists('notify_send')) {
            notify_send($db, $tid, 'Wallet credited',
                '₹' . number_format($amount, 2) . ' has been added to your ' . ($wallet === WALLET_VIRTUAL ? 'virtual' : 'main') . ' wallet. Reason: ' . $full_reason,
                'wallet', 'wallet.php#wallet_history', $user_id);
        }
        $_SESSION['flash_success'] = "₹" . number_format($amount, 2) . " credited. Reason: " . htmlspecialchars($full_reason);
    } else {
        $bal  = wallet_balances($db, $tid);
        $have = ($wallet === WALLET_VIRTUAL) ? $bal['virtual'] : $bal['main'];
        if ($have + 0.001 < $amount) {
            $_SESSION['flash_error'] = "That wallet only holds ₹" . number_format($have, 2) . ".";
        } else {
            $col = ($wallet === WALLET_VIRTUAL) ? 'bonus_wallet' : 'wallet_balance';
            $db->insert("UPDATE users SET `$col` = `$col` - ? WHERE id = ?", [$amount, $tid]); // whitelisted
            $nb = wallet_balances($db, $tid);
            wallet__ledger($db, $tid, $wallet, 'debit', $amount,
                ($wallet === WALLET_VIRTUAL) ? $nb['virtual'] : $nb['main'],
                ['category' => 'admin', 'description' => 'Admin debit — ' . $full_reason, 'created_by' => $user_id]);
            wallet__legacy($db, $tid, 'debit', $amount, 'Admin debit — ' . $full_reason);
            try {
                $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'Wallet Debit', '', ?, ?, ?)",
                    [$tid, '₹' . number_format($amount, 2) . ' (' . ($wallet === WALLET_VIRTUAL ? 'virtual' : 'main') . ') — ' . $full_reason, $user_id, $me['name'] ?? 'Admin']);
            } catch (\Throwable $e) {}
            if (function_exists('notify_send')) {
                notify_send($db, $tid, 'Wallet debited',
                    '₹' . number_format($amount, 2) . ' has been deducted from your ' . ($wallet === WALLET_VIRTUAL ? 'virtual' : 'main') . ' wallet. Reason: ' . $full_reason,
                    'wallet', 'wallet.php#wallet_history', $user_id);
            }
            $_SESSION['flash_success'] = "₹" . number_format($amount, 2) . " debited. Reason: " . htmlspecialchars($full_reason);
        }
    }
    redirect($UL_SELF);
}

// --- Reset Password: admin enters a new password (logged to update history) ---
if (isset($_POST['reset_password'])) {
    ul_need('password');   /* resetting a password */
    $tid = intval($_POST['target_user_id']);
    $newpass = $_POST['new_password'] ?? '';
    if (strlen($newpass) >= 4) {
        $hashed = password_hash($newpass, PASSWORD_DEFAULT);
        $db->insert("UPDATE users SET password = ? WHERE id = ?", [$hashed, $tid]);
        $db->insert("INSERT INTO user_update_history (user_id, field_label, old_value, new_value, updated_by, updated_by_name) VALUES (?, 'Password', '••••••••', 'Password was reset', ?, ?)",
            [$tid, $me['id'], $me['name']]);
        $_SESSION['flash_success'] = "Password updated successfully!";
    } else {
        $_SESSION['flash_error'] = "Password must be at least 4 characters.";
    }
    redirect($UL_SELF);
}

/* ============================================================
   FETCH DATA
   ============================================================ */
$user_data = $db->select("SELECT * FROM users WHERE id = ?", [$user_id]);
$user = !empty($user_data) ? $user_data[0] : null;
if (!$user) { session_destroy(); redirect('login.php'); }

/* ---------------- STICKY FILTERS ---------------- */
$UL_DEFAULTS = ['search' => '', 'kyc' => '', 'sub' => '', 'status' => '', 'joined' => '', 'from' => '', 'to' => '', 'wallet' => '', 'ref' => '', 'state' => '', 'district' => '', 'types' => 'customer,seller,admin', 'trash' => ''];

/* ---- The audience this front door was built for ----
   Translates the sidebar's role deep-link into the sticky filter fields this
   page already understands, then lets alist_filters() do the rest. --------- */
/* The audience belongs to the page. It is written into the filter fields on
   every load — not just when a link carries ?role= — so there is no way to
   widen the list from the address bar. */
$WB_ROLE_VIEW  = $WB_SCOPE;
$_GET['types'] = $WB_AUD[2];
if ($WB_AUD[3] !== '') { $_GET['sub'] = $WB_AUD[3]; }
/* A page that IS the recycle bin forces it on. Everywhere else the Deleted
   tile is allowed to turn it on, because that only ever narrows the same
   audience — it can never show somebody a list they were not given. */
if ($WB_AUD[4] !== '') { $_GET['trash'] = $WB_AUD[4]; }
if ($WB_SCOPE === 'deleted') {
    foreach (['status', 'kyc', 'joined', 'from', 'to', 'wallet', 'ref'] as $__k) { $_GET[$__k] = ''; }
}

$UL = alist_filters($UL_FKEY, $UL_DEFAULTS);

$search_query = $UL['search'];

// User-type filter (Customer / Seller / Staff). Staff = user_type 'admin'.
$allowed_types = ['customer', 'seller', 'admin'];
$type_labels   = ['customer' => 'Customer', 'seller' => 'Seller', 'admin' => 'Staff'];
$selected_types = array_values(array_intersect(array_filter(explode(',', (string)$UL['types'])), $allowed_types));
if (empty($selected_types)) $selected_types = $allowed_types;

$type_ph = implode(',', array_fill(0, count($selected_types), '?'));
$where_clause = "u.user_type IN ($type_ph)";
$params = $selected_types;

/* whatever else this audience needs — the employee / admin split, so far */
if (!empty($WB_AUD[5])) { $where_clause .= ' ' . $WB_AUD[5]; }

/* The audience on its own, before any of the tiles or filters below. The tile
   counts are taken over this, so they stay still while you filter. */
$UL_BASE_WHERE  = $where_clause;
$UL_BASE_PARAMS = $params;

/* Recycle bin: `trash=1` shows ONLY soft-deleted accounts, every other view
   hides them completely. */
$UL_TRASH = ((string)$UL['trash'] === '1');
$where_clause .= $UL_TRASH ? " AND u.deleted_at IS NOT NULL" : " AND u.deleted_at IS NULL";

if ($search_query !== '') {
    $where_clause .= " AND (u.id = ? OR u.name LIKE ? OR u.mobile LIKE ? OR u.email LIKE ?)";
    $like = "%$search_query%";
    $params[] = intval(str_replace(['#', 'WBMCZ'], '', $search_query));
    $params[] = $like; $params[] = $like; $params[] = $like;
}
if ($UL['kyc'] === 'approved')      { $where_clause .= " AND k.status = 'approved'"; }
elseif ($UL['kyc'] === 'pending')   { $where_clause .= " AND k.status = 'pending'"; }
elseif ($UL['kyc'] === 'rejected')  { $where_clause .= " AND k.status = 'rejected'"; }
elseif ($UL['kyc'] === 'none')      { $where_clause .= " AND k.id IS NULL"; }

if ($UL['sub'] === 'yes')      { $where_clause .= " AND u.is_subscribed = 1"; }
elseif ($UL['sub'] === 'no')   { $where_clause .= " AND (u.is_subscribed = 0 OR u.is_subscribed IS NULL)"; }

if ($UL['status'] === '1')     { $where_clause .= " AND u.status = 1"; }
elseif ($UL['status'] === '0') { $where_clause .= " AND u.status = 0"; }

if ($UL['joined'] === 'today')     { $where_clause .= " AND DATE(u.created_at) = CURDATE()"; }
elseif ($UL['joined'] === '7')     { $where_clause .= " AND u.created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)"; }
elseif ($UL['joined'] === '30')    { $where_clause .= " AND u.created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)"; }
elseif ($UL['joined'] === 'month') { $where_clause .= " AND u.created_at >= DATE_FORMAT(NOW(), '%Y-%m-01')"; }
elseif ($UL['joined'] === 'year')  { $where_clause .= " AND u.created_at >= DATE_FORMAT(NOW(), '%Y-01-01')"; }
elseif ($UL['joined'] === 'custom') { /* kept so older links still open */ }

/* The two date boxes are on the bar in their own right now, rather than hiding
   behind a "custom" choice. Either end may be left blank, so "from 01 Aug" and
   "up to 31 Aug" each work alone, and they narrow whatever Time already chose
   instead of replacing it. */
$__from = trim((string)$UL['from']);
$__to   = trim((string)$UL['to']);
if ($__from !== '' && preg_match('/^\d{4}-\d{2}-\d{2}$/', $__from)) {
    $where_clause .= " AND DATE(u.created_at) >= ?";
    $params[] = $__from;
}
if ($__to !== '' && preg_match('/^\d{4}-\d{2}-\d{2}$/', $__to)) {
    $where_clause .= " AND DATE(u.created_at) <= ?";
    $params[] = $__to;
}

if ($UL['wallet'] === 'zero')       { $where_clause .= " AND COALESCE(u.wallet_balance,0) = 0"; }
elseif ($UL['wallet'] === 'nonzero'){ $where_clause .= " AND COALESCE(u.wallet_balance,0) > 0"; }

/* where they are — the district list narrows to whatever state is chosen */
if (trim((string)$UL['state']) !== '')    { $where_clause .= " AND u.state = ?";    $params[] = trim((string)$UL['state']); }
if (trim((string)$UL['district']) !== '') { $where_clause .= " AND u.district = ?"; $params[] = trim((string)$UL['district']); }

/* referral: brought in by nobody, or brought somebody in themselves */
if ($UL['ref'] === 'none')      { $where_clause .= " AND (u.referred_by IS NULL OR u.referred_by = 0)"; }
elseif ($UL['ref'] === 'by')    { $where_clause .= " AND EXISTS (SELECT 1 FROM users rr WHERE rr.referred_by = u.id AND rr.deleted_at IS NULL)"; }
elseif ($UL['ref'] === 'joined'){ $where_clause .= " AND u.referred_by IS NOT NULL AND u.referred_by <> 0"; }

/* ---------------------------------------------------------------------------
   THE TILE ROW

   Nine numbers across the top of the list, and every one of them is a filter:
   click "Subscription" and the list below becomes the subscribed ones. They are
   counted over this page's audience only — the Sellers page counts sellers —
   and NOT over the filters underneath, so the row does not shuffle about while
   you are working in it.
   --------------------------------------------------------------------------- */
$ULT = ['total'=>0,'free'=>0,'sub'=>0,'kyc_none'=>0,'kyc_wait'=>0,'kyc_ok'=>0,'kyc_no'=>0,
        'ref_none'=>0,'ref_by'=>0,'deleted'=>0,'active'=>0,'blocked'=>0,'month'=>0];
try {
    $__bp = $UL_BASE_PARAMS;
    $__r = $db->select(
        "SELECT COUNT(*) t,
                SUM(COALESCE(u.is_subscribed,0) = 1) sb,
                SUM(COALESCE(u.is_subscribed,0) <> 1) fr,
                SUM(COALESCE(u.status,1) = 1) ac,
                SUM(COALESCE(u.status,1) = 0) bl,
                SUM(u.created_at >= DATE_FORMAT(NOW(), '%Y-%m-01')) mn,
                SUM(u.referred_by IS NULL OR u.referred_by = 0) rn,
                SUM(k.id IS NULL) kn,
                SUM(k.status = 'pending') kw,
                SUM(k.status = 'approved') ka,
                SUM(k.status = 'rejected') kr
           FROM users u LEFT JOIN kyc_details k ON k.user_id = u.id
          WHERE $UL_BASE_WHERE AND u.deleted_at IS NULL", $__bp);
    if (!empty($__r)) {
        $x = $__r[0];
        $ULT['total']    = (int)$x['t'];  $ULT['sub']      = (int)$x['sb'];
        $ULT['free']     = (int)$x['fr']; $ULT['active']   = (int)$x['ac'];
        $ULT['blocked']  = (int)$x['bl']; $ULT['month']    = (int)$x['mn'];
        $ULT['ref_none'] = (int)$x['rn']; $ULT['kyc_none'] = (int)$x['kn'];
        $ULT['kyc_wait'] = (int)$x['kw']; $ULT['kyc_ok']   = (int)$x['ka'];
        $ULT['kyc_no']   = (int)$x['kr'];
    }
    $__r = $db->select(
        "SELECT COUNT(*) n FROM users u
          WHERE $UL_BASE_WHERE AND u.deleted_at IS NULL
            AND EXISTS (SELECT 1 FROM users rr WHERE rr.referred_by = u.id AND rr.deleted_at IS NULL)", $UL_BASE_PARAMS);
    if (!empty($__r)) { $ULT['ref_by'] = (int)$__r[0]['n']; }

    $__r = $db->select(
        "SELECT COUNT(*) n FROM users u WHERE $UL_BASE_WHERE AND u.deleted_at IS NOT NULL", $UL_BASE_PARAMS);
    if (!empty($__r)) { $ULT['deleted'] = (int)$__r[0]['n']; }
} catch (\Throwable $e) {}

/* Sellers hold company money, so their page carries three more — and those
   three lead to the screens where the money is actually dealt with. */
$ULM = ['collect'=>0.0,'verify'=>0,'dues'=>0.0];
if ($WB_SCOPE === 'seller') {
    try {
        $__r = $db->select("SELECT COALESCE(SUM(amount),0) a FROM seller_collections WHERE LOWER(status)='approved'");
        $ULM['collect'] = !empty($__r) ? (float)$__r[0]['a'] : 0.0;
        $__r = $db->select("SELECT COUNT(*) n FROM seller_collections WHERE LOWER(status)='pending'");
        $ULM['verify'] = !empty($__r) ? (int)$__r[0]['n'] : 0;
        $__r = $db->select("SELECT COALESCE(SUM(amount),0) a FROM seller_settlements WHERE direction='in'");
        $ULM['dues'] = $ULM['collect'] - (!empty($__r) ? (float)$__r[0]['a'] : 0.0);
        if ($ULM['dues'] < 0) { $ULM['dues'] = 0.0; }
    } catch (\Throwable $e) {}
}

/* The states and districts that actually appear in THIS page's audience — no
   point offering "Kerala" on a list where nobody lives there. The districts
   narrow to the chosen state, so the second box is never a wall of 700 names. */
$UL_STATES = []; $UL_DISTRICTS = [];
try {
    foreach ($db->select("SELECT DISTINCT u.state s FROM users u
                           WHERE $UL_BASE_WHERE AND u.state IS NOT NULL AND u.state <> ''
                           ORDER BY u.state", $UL_BASE_PARAMS) as $r) { $UL_STATES[] = (string)$r['s']; }

    $__dp = $UL_BASE_PARAMS; $__dw = '';
    if (trim((string)$UL['state']) !== '') { $__dw = " AND u.state = ?"; $__dp[] = trim((string)$UL['state']); }
    foreach ($db->select("SELECT DISTINCT u.district d FROM users u
                           WHERE $UL_BASE_WHERE $__dw AND u.district IS NOT NULL AND u.district <> ''
                           ORDER BY u.district", $__dp) as $r) { $UL_DISTRICTS[] = (string)$r['d']; }
} catch (\Throwable $e) {}

/* A tile link keeps what you searched for and replaces the rest, so one click
   never leaves two half-filters fighting each other. */
$ul_tile = function (array $over) use ($UL, $UL_DEFAULTS, $UL_PAGE, $UL_FKEY) {
    $f = $UL_DEFAULTS;
    $f['search'] = $UL['search'];
    foreach ($over as $k => $v) { $f[$k] = $v; }
    return alist_url($UL_PAGE, $UL_FKEY, $f, []);
};
$ul_on = function (array $over) use ($UL) {
    foreach (['sub','kyc','ref','trash','status'] as $k) {
        $want = (string)($over[$k] ?? '');
        if ((string)$UL[$k] !== $want) { return false; }
    }
    return true;
};

/* ---------------- STATS ---------------- */
$ULS = ['total'=>0,'customer'=>0,'seller'=>0,'staff'=>0,'today'=>0,'week'=>0,'sub'=>0,
        'kyc_pending'=>0,'kyc_approved'=>0,'kyc_none'=>0,'wallet'=>0,'virtual'=>0,'blocked'=>0,'deleted'=>0];
try {
    $r = $db->select("SELECT COUNT(*) t,
        SUM(user_type='customer') c, SUM(user_type='seller') s, SUM(user_type='admin') a,
        SUM(DATE(created_at)=CURDATE()) td, SUM(created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)) wk,
        SUM(COALESCE(is_subscribed,0)=1) sb, SUM(COALESCE(status,1)=0) bl,
        COALESCE(SUM(wallet_balance),0) wl, COALESCE(SUM(bonus_wallet),0) vw
        FROM users WHERE deleted_at IS NULL");
    $__d = $db->select("SELECT COUNT(*) d FROM users WHERE deleted_at IS NOT NULL");
    if (!empty($__d)) { $ULS['deleted'] = (int)$__d[0]['d']; }
    if (!empty($r)) { $x=$r[0];
        $ULS['total']=(int)$x['t']; $ULS['customer']=(int)$x['c']; $ULS['seller']=(int)$x['s'];
        $ULS['staff']=(int)$x['a']; $ULS['today']=(int)$x['td']; $ULS['week']=(int)$x['wk'];
        $ULS['sub']=(int)$x['sb']; $ULS['blocked']=(int)$x['bl'];
        $ULS['wallet']=(float)$x['wl']; $ULS['virtual']=(float)$x['vw'];
    }
    $r = $db->select("SELECT SUM(status='pending') p, SUM(status='approved') a FROM kyc_details");
    if (!empty($r)) { $ULS['kyc_pending']=(int)$r[0]['p']; $ULS['kyc_approved']=(int)$r[0]['a']; }
    $r = $db->select("SELECT COUNT(*) n FROM users u LEFT JOIN kyc_details k ON k.user_id=u.id WHERE k.id IS NULL");
    if (!empty($r)) { $ULS['kyc_none']=(int)$r[0]['n']; }
} catch (\Throwable $e) {}
// LEFT JOIN self (referrer = "Created By") and kyc_details (status + address source)
/* ---------------- CSV EXPORT ---------------- */
if (isset($_GET['export'])) {
    ul_need('export');   /* taking the list off the site */
    /* The export is the list you are looking at, not the table.
         · with rows ticked  → exactly those rows
         · with none ticked  → every row the current filters allow
       Either way it starts from $where_clause, which already carries the
       audience, the search and every filter above. */
    $ex_where  = $where_clause;
    $ex_params = $params;

    $ex_ids = array_values(array_unique(array_filter(
        array_map('intval', explode(',', (string)($_GET['ids'] ?? ''))),
        function ($n) { return $n > 0; })));
    if (!empty($ex_ids)) {
        $ex_ids   = array_slice($ex_ids, 0, 5000);
        $ex_where .= ' AND u.id IN (' . implode(',', array_fill(0, count($ex_ids), '?')) . ')';
        $ex_params = array_merge($ex_params, $ex_ids);
    }

    $ex = $db->select(
        "SELECT u.*, r.name AS ref_name, k.status AS kyc_status
         FROM users u
         LEFT JOIN users r ON u.referred_by = r.id
         LEFT JOIN kyc_details k ON k.user_id = u.id
         WHERE $ex_where ORDER BY u.id DESC LIMIT 10000", $ex_params);
    alist_export_csv('user_list', [
        'ID' => 'id',
        'Code' => function ($r) { return 'WBMCZ' . str_pad($r['id'], 4, '0', STR_PAD_LEFT); },
        'Name' => 'name', 'Mobile' => 'mobile', 'Email' => 'email',
        'Type' => function ($r) { return $r['user_type'] === 'admin' ? 'Staff' : ucfirst($r['user_type']); },
        'Status' => function ($r) { return ((int)($r['status'] ?? 1) === 1) ? 'Active' : 'Blocked'; },
        'KYC' => function ($r) { return $r['kyc_status'] ?: 'not submitted'; },
        'Subscribed' => function ($r) { return !empty($r['is_subscribed']) ? 'Yes' : 'No'; },
        'Main Wallet' => function ($r) { return number_format((float)($r['wallet_balance'] ?? 0), 2, '.', ''); },
        'Virtual Wallet' => function ($r) { return number_format((float)($r['bonus_wallet'] ?? 0), 2, '.', ''); },
        'State' => 'state', 'District' => 'district', 'Pincode' => 'pincode',
        'Referred By' => 'ref_name',
        'Added By' => function ($r) { return !empty($r['created_by_name']) ? $r['created_by_name'] : 'Self registered'; },
        'Joined' => 'created_at',
    ], $ex);
}

/* ---------------- PAGINATION — 100 rows per page ----------------
   Only one page worth of rows is read from the database, so the list stays
   fast even with tens of thousands of users. ------------------------------ */
$UL_PER_PAGE   = 100;
$ul_total_rows = 0;
try {
    $__cr = $db->select(
        "SELECT COUNT(*) AS c
         FROM users u
         LEFT JOIN kyc_details k ON k.user_id = u.id
         WHERE $where_clause", $params);
    $ul_total_rows = !empty($__cr) ? (int)$__cr[0]['c'] : 0;
} catch (\Throwable $e) { $ul_total_rows = 0; }

$ul_pages  = max(1, (int)ceil($ul_total_rows / $UL_PER_PAGE));
$ul_page   = isset($_GET['p']) ? max(1, (int)$_GET['p']) : 1;
if ($ul_page > $ul_pages) { $ul_page = $ul_pages; }
$ul_offset = ($ul_page - 1) * $UL_PER_PAGE;
$ul_from   = $ul_total_rows ? ($ul_offset + 1) : 0;
$ul_to     = min($ul_offset + $UL_PER_PAGE, $ul_total_rows);

/* page link helper — keeps every active filter */
function ul_page_url($n, $UL) {
    global $UL_PAGE, $UL_FKEY;
    return alist_url($UL_PAGE, $UL_FKEY, $UL, ['p' => (int)$n]);
}

$customers = $db->select(
    "SELECT u.*, r.name AS ref_name, r.id AS ref_id,
            k.id AS kyc_id, k.status AS kyc_status,
            k.village AS k_village, k.post_office AS k_post_office, k.block_city AS k_block_city,
            k.landmark AS k_landmark, k.district AS k_district, k.state AS k_state, k.pincode AS k_pincode
     FROM users u
     LEFT JOIN users r ON u.referred_by = r.id
     LEFT JOIN kyc_details k ON k.user_id = u.id
     WHERE $where_clause ORDER BY u.id DESC
     LIMIT " . (int)$UL_PER_PAGE . " OFFSET " . (int)$ul_offset, $params);

/* ids on this page — used by the "select all on this page" tick box */
$ul_page_ids = array_map(function ($r) { return (int)$r['id']; }, $customers);

$raw_logo = getSetting('company_logo', 'assets/images/logo.png');
$company_logo = (strpos($raw_logo, 'http') === 0) ? $raw_logo : '../' . ltrim($raw_logo, '/');
$company_name = getSetting('company_name', 'WBMCZ');
$profile_image_url = !empty($user['profile_pic']) ? '../uploads/profiles/' . $user['profile_pic'] : null;

// Helper: build the WBMCZ user code (matches refer.php convention)
function userCode($id) { return 'WBMCZ' . str_pad($id, 4, '0', STR_PAD_LEFT); }

// The "admin created by" label — using the logged-in admin as a stand-in.
// # PENDING: there is no `created_by` column in the users table (see report).
$created_by_code = userCode($user['id']);
$created_by_name = strtoupper($user['name']);
?>
<!DOCTYPE html>
<html lang="<?php echo $current_lang; ?>">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>User List - <?php echo $company_name; ?></title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
    <style>
        body { font-family: 'Inter', sans-serif; }
        .hide-scrollbar::-webkit-scrollbar { display: none; }
        /* PDF-style compact cell buttons */
        .cell-btn { display:block; width:100%; text-align:center; font-size:10px; font-weight:700; padding:3px 6px; border-radius:4px; color:#fff; white-space:nowrap; }
        .pending-tag { display:inline-block; font-size:9px; font-weight:700; color:#b45309; background:#fef3c7; border:1px dashed #f59e0b; padding:1px 6px; border-radius:9999px; }
        table.ul td { vertical-align: top; }
        /* Full gridlines around every cell (PDF-style) */
        table.ul { border: 2px solid #cbd5e1; }
        table.ul th, table.ul td { border: 1px solid #e2e8f0; }

        /* ---------- FROZEN COLUMNS ----------
           The table is far wider than any screen, and once you scroll right to
           the wallet or the action buttons you can no longer see whose row you
           are on. The tick box and the name stay put instead, the way a frozen
           pane does in a spreadsheet.

           The two are pinned at 0 and at 44px — the width of the tick column —
           and the header cells sit one layer higher so they stay above the body
           when you scroll down as well as across. */
        table.ul th:nth-child(1), table.ul td:nth-child(1) {
            position: sticky; left: 0; z-index: 3; background: #fff; width: 44px; min-width: 44px;
        }
        table.ul th:nth-child(2), table.ul td:nth-child(2) {
            position: sticky; left: 44px; z-index: 3; background: #fff;
        }
        /* ---------- FROZEN HEADER ROW ----------
           The column names stay at the top of the box while the rows run under
           them, so on row 80 you can still read which column you are in. The
           box gets a height for the same reason a spreadsheet pane does: the
           header can only stay still if something else is doing the scrolling.

           Layers, lowest first: ordinary cells, the two frozen columns (3),
           the header row (6), and the two header cells where they cross (8). */
        #ulScroll { max-height: calc(100vh - 210px); }
        table.ul thead th { position: sticky; top: 0; z-index: 6; background: #f8fafc; }
        table.ul thead th:nth-child(1), table.ul thead th:nth-child(2) { z-index: 8; background: #f8fafc; }
        #ulScroll::-webkit-scrollbar { width: 11px; }
        /* a hairline so the frozen pair reads as a pane edge, not a join */
        table.ul th:nth-child(2), table.ul td:nth-child(2) { box-shadow: 6px 0 6px -6px rgba(15,23,42,.18); }
        table.ul tbody tr:hover td:nth-child(1),
        table.ul tbody tr:hover td:nth-child(2) { background: #f8fafc; }
        .fld { width:100%; border:1px solid #cbd5e1; border-radius:0.5rem; padding:0.5rem 0.75rem; font-size:0.875rem; outline:none; }
        .fld:focus { box-shadow:0 0 0 2px rgba(16,185,129,0.4); border-color:#10b981; }
        .lbl { display:block; font-size:0.7rem; font-weight:700; color:#475569; text-transform:uppercase; letter-spacing:0.03em; margin-bottom:0.25rem; }
        .filein { width:100%; font-size:0.7rem; color:#64748b; }
        .filein::file-selector-button { margin-right:0.5rem; padding:0.25rem 0.5rem; border-radius:0.375rem; border:0; background:#ecfdf5; color:#047857; font-weight:600; font-size:0.7rem; }

        /* ---------- bulk selection ---------- */
        .ul-check { width:16px; height:16px; accent-color:#4f46e5; cursor:pointer; }
        .ul-bulkbar { display:flex; flex-wrap:wrap; align-items:center; gap:.6rem; margin-bottom:.85rem;
                      padding:.7rem .9rem; border-radius:.9rem; background:#eef2ff; border:1px solid #c7d2fe; }
        .ul-bulk-count { font-size:12px; font-weight:800; color:#3730a3; white-space:nowrap; }
        .ul-bulk-btn { display:inline-flex; align-items:center; gap:.35rem; padding:.4rem .75rem; border-radius:.55rem;
                       color:#fff; font-size:11px; font-weight:700; white-space:nowrap; }
        .ul-bulk-clear { margin-left:auto; font-size:11px; font-weight:700; color:#4338ca; }
        .ul-bulk-clear:hover { text-decoration:underline; }

        /* ---------- top horizontal scroll bar for the wide table ---------- */
        .ul-topscroll { overflow-x:auto; overflow-y:hidden; height:14px; border-bottom:1px solid #e2e8f0; background:#f8fafc; }
        .ul-topscroll > div { height:1px; }
        .ul-topscroll::-webkit-scrollbar,
        #ulScroll::-webkit-scrollbar { height:11px; }
        .ul-topscroll::-webkit-scrollbar-thumb,
        #ulScroll::-webkit-scrollbar-thumb { background:#94a3b8; border-radius:99px; }
        .ul-topscroll::-webkit-scrollbar-thumb:hover,
        #ulScroll::-webkit-scrollbar-thumb:hover { background:#64748b; }
        .ul-topscroll::-webkit-scrollbar-track,
        #ulScroll::-webkit-scrollbar-track { background:#f1f5f9; }

        /* ---------- pager ---------- */
        .ul-pager { display:flex; flex-wrap:wrap; align-items:center; gap:.6rem; margin-top:1rem;
                    padding:.75rem .9rem; background:#fff; border:1px solid #e2e8f0; border-radius:.9rem; }
        .ul-pager-info { font-size:11px; font-weight:700; color:#94a3b8; white-space:nowrap; }
        .ul-pager-btns { display:flex; flex-wrap:wrap; align-items:center; gap:.3rem; margin:0 auto; }
        .ul-pg { display:inline-flex; align-items:center; gap:.3rem; min-width:2rem; justify-content:center;
                 padding:.35rem .6rem; border-radius:.5rem; font-size:12px; font-weight:700;
                 color:#475569; background:#f8fafc; border:1px solid #e2e8f0; }
        .ul-pg:hover { background:#eef2ff; color:#4338ca; border-color:#c7d2fe; }
        .ul-pg.is-now { background:#4f46e5; color:#fff; border-color:#4f46e5; }
        .ul-pg.is-off { opacity:.4; pointer-events:none; }
        .ul-pg-gap { padding:0 .2rem; color:#cbd5e1; font-weight:800; }
        .ul-pager-jump { display:flex; align-items:center; gap:.35rem; font-size:11px; font-weight:700; color:#94a3b8; }
        .ul-pager-jump input { width:4.5rem; padding:.3rem .5rem; border:1px solid #e2e8f0; border-radius:.5rem; font-size:12px; }
        .ul-pager-jump button { padding:.35rem .6rem; border-radius:.5rem; background:#0f172a; color:#fff; font-size:11px; }
    </style>
</head>
<body class="bg-gray-50" x-data="userListApp()">
<div class="flex h-screen overflow-hidden">

    <!-- ================= SIDEBAR ================= -->
        <?php include __DIR__ . '/sidebar.php'; ?>
    <!-- ================= MAIN ================= -->
    <div class="flex-1 flex flex-col min-w-0 bg-gray-100 overflow-hidden">
        <header class="h-20 bg-white text-slate-800 flex items-center justify-between px-4 lg:px-8 shadow-sm border-b border-gray-200 z-40 relative">
            <div class="flex items-center">
                <button @click="sidebarOpen = !sidebarOpen" class="p-2 mr-3 text-slate-500 hover:text-emerald-600 rounded-lg hover:bg-gray-100 transition-colors">
                    <i class="fas fa-bars text-xl"></i>
                </button>
                <h2 class="text-xl font-bold hidden md:block text-slate-800">User List</h2>
            </div>
            <div class="flex items-center space-x-4 ml-auto">
                <a href="../index.php" target="_blank" class="hidden sm:flex items-center text-sm font-semibold text-gray-500 hover:text-emerald-600 transition-colors">
                    <i class="fas fa-external-link-alt mr-2"></i> Visit Site
                </a>
                <?php if(!empty($profile_image_url) && file_exists($profile_image_url)): ?>
                    <img src="<?php echo $profile_image_url; ?>" class="w-10 h-10 rounded-full border-2 border-emerald-100 object-cover">
                <?php else: ?>
                    <div class="w-10 h-10 rounded-full bg-emerald-100 border-2 border-emerald-200 text-emerald-600 flex items-center justify-center text-lg font-bold"><?php echo strtoupper(substr($user['name'],0,1)); ?></div>
                <?php endif; ?>
            </div>
        </header>

        <main class="flex-1 overflow-y-auto p-4 md:p-6 relative">
            <div class="mb-5 flex flex-wrap items-start justify-between gap-3">
                <div>
                    <h2 class="text-2xl font-bold text-slate-800 mb-1">User List Management</h2>
                    <p class="text-gray-500 text-sm">All users — customers, sellers &amp; staff — with profile, address, subscription, wallet &amp; quick actions.</p>
                </div>
                <?php if (!$UL_TRASH): ?>
                <button type="button" @click="openAddUser()"
                        class="inline-flex items-center gap-2 px-5 py-3 rounded-xl bg-gradient-to-r from-indigo-600 to-blue-600 text-white text-sm font-bold shadow hover:shadow-lg transition">
                    <i class="fas fa-user-plus"></i> Add New User
                </button>
                <?php endif; ?>
            </div>

            <!-- ===== THE TILE ROW — every number is a filter ===== -->
            <?php
            /* Staff have no subscription, no KYC and no referrals, so their page
               gets the four numbers that mean something for staff instead of
               five zeros that mean nothing. */
            $IS_STAFF_LIST = in_array($WB_SCOPE, ['employee', 'admin', 'staff'], true);

            if ($IS_STAFF_LIST) {
                $UL_TILES = [
                    ['Total ' . $WB_AUD[0], $ULT['total'],   [],                'indigo', 'fa-users',         'everyone on this list'],
                    ['Active',              $ULT['active'],  ['status' => '1'], 'emerald','fa-circle-check',  'can sign in'],
                    ['Blocked',             $ULT['blocked'], ['status' => '0'], 'rose',   'fa-ban',           'sign-in turned off'],
                    ['Joined this month',   $ULT['month'],   [],                'blue',   'fa-user-plus',     'since the 1st'],
                    ['Deleted',             $ULT['deleted'], ['trash' => '1'],  'slate',  'fa-trash-can',     'removed, still restorable'],
                ];
            } else {
                $UL_TILES = [
                    ['Total ' . $WB_AUD[0], $ULT['total'],    [],                    'indigo', 'fa-users',        'everyone on this list'],
                    ['Free User',           $ULT['free'],     ['sub' => 'no'],       'sky',    'fa-user',         'no subscription'],
                    ['Subscription User',   $ULT['sub'],      ['sub' => 'yes'],      'violet', 'fa-crown',        'paying members'],
                    ['Pending KYC',         $ULT['kyc_none'], ['kyc' => 'none'],     'rose',   'fa-user-slash',   'nothing submitted yet'],
                    ['KYC Request',         $ULT['kyc_wait'], ['kyc' => 'pending'],  'amber',  'fa-id-card',      'sent in, waiting on us'],
                    ['Complete KYC',        $ULT['kyc_ok'],   ['kyc' => 'approved'], 'emerald','fa-circle-check', 'approved'],
                    ['No Referral',         $ULT['ref_none'], ['ref' => 'none'],     'orange', 'fa-user-minus',   'nobody brought them in'],
                    ['Referrers User',      $ULT['ref_by'],   ['ref' => 'by'],       'teal',   'fa-share-nodes',  'have brought somebody in'],
                    ['Delete User',         $ULT['deleted'],  ['trash' => '1'],      'slate',  'fa-trash-can',    'removed, still restorable'],
                ];
                if ($ULT['kyc_no'] > 0) {
                    /* only worth a tile when there is something in it */
                    array_splice($UL_TILES, 6, 0, [['KYC Rejected', $ULT['kyc_no'], ['kyc' => 'rejected'], 'rose', 'fa-circle-xmark', 'sent back to them']]);
                }
            }

            $UL_TONE = [
                'indigo' => 'bg-indigo-50 text-indigo-600 border-indigo-100',
                'sky'    => 'bg-sky-50 text-sky-600 border-sky-100',
                'violet' => 'bg-violet-50 text-violet-600 border-violet-100',
                'rose'   => 'bg-rose-50 text-rose-600 border-rose-100',
                'amber'  => 'bg-amber-50 text-amber-600 border-amber-100',
                'emerald'=> 'bg-emerald-50 text-emerald-600 border-emerald-100',
                'orange' => 'bg-orange-50 text-orange-600 border-orange-100',
                'teal'   => 'bg-teal-50 text-teal-600 border-teal-100',
                'blue'   => 'bg-blue-50 text-blue-600 border-blue-100',
                'slate'  => 'bg-slate-100 text-slate-600 border-slate-200',
            ];
            ?>
            <div class="grid grid-cols-2 sm:grid-cols-3 xl:grid-cols-5 gap-2.5 mb-3">
                <?php foreach ($UL_TILES as $t):
                    $on = $ul_on($t[2]);
                    $tone = $UL_TONE[$t[3]] ?? $UL_TONE['slate']; ?>
                    <a href="<?php echo $ul_tile($t[2]); ?>"
                       class="block bg-white rounded-xl border p-3.5 transition-all hover:shadow-sm <?php echo $on ? 'border-indigo-400 ring-2 ring-indigo-100' : 'border-slate-200 hover:border-slate-300'; ?>">
                        <span class="w-8 h-8 rounded-lg border flex items-center justify-center <?php echo $tone; ?> mb-2"><i class="fas <?php echo $t[4]; ?> text-xs"></i></span>
                        <p class="text-lg font-extrabold text-slate-800 leading-none"><?php echo number_format((int)$t[1]); ?></p>
                        <p class="text-[11px] font-bold text-slate-600 mt-1"><?php echo htmlspecialchars($t[0]); ?></p>
                        <p class="text-[9.5px] text-slate-400 leading-tight mt-0.5"><?php echo htmlspecialchars($t[5]); ?></p>
                    </a>
                <?php endforeach; ?>
            </div>

            <?php if ($WB_SCOPE === 'seller'): ?>
            <!-- Sellers hold company money. These three lead to where it is dealt with. -->
            <div class="grid grid-cols-1 sm:grid-cols-3 gap-2.5 mb-3">
                <a href="order_manage.php?tab=collections" class="block bg-white rounded-xl border border-slate-200 hover:border-emerald-300 p-3.5 transition-all hover:shadow-sm">
                    <span class="w-8 h-8 rounded-lg border flex items-center justify-center bg-emerald-50 text-emerald-600 border-emerald-100 mb-2"><i class="fas fa-sack-dollar text-xs"></i></span>
                    <p class="text-lg font-extrabold text-slate-800 leading-none">₹<?php echo number_format($ULM['collect'], 2); ?></p>
                    <p class="text-[11px] font-bold text-slate-600 mt-1">Seller Collection</p>
                    <p class="text-[9.5px] text-slate-400 mt-0.5">taken from customers and verified</p>
                </a>
                <a href="activity_task.php?role=office&amp;tab=verify_collect" class="block bg-white rounded-xl border border-slate-200 hover:border-amber-300 p-3.5 transition-all hover:shadow-sm">
                    <span class="w-8 h-8 rounded-lg border flex items-center justify-center bg-amber-50 text-amber-600 border-amber-100 mb-2"><i class="fas fa-receipt text-xs"></i></span>
                    <p class="text-lg font-extrabold text-slate-800 leading-none"><?php echo number_format($ULM['verify']); ?></p>
                    <p class="text-[11px] font-bold text-slate-600 mt-1">Verify Collection</p>
                    <p class="text-[9.5px] text-slate-400 mt-0.5">said to be taken, not checked yet</p>
                </a>
                <a href="activity_task.php?role=office&amp;tab=seller_dues" class="block bg-white rounded-xl border border-slate-200 hover:border-rose-300 p-3.5 transition-all hover:shadow-sm">
                    <span class="w-8 h-8 rounded-lg border flex items-center justify-center bg-rose-50 text-rose-600 border-rose-100 mb-2"><i class="fas fa-hand-holding-dollar text-xs"></i></span>
                    <p class="text-lg font-extrabold text-slate-800 leading-none <?php echo $ULM['dues'] > 0 ? 'text-rose-600' : ''; ?>">₹<?php echo number_format($ULM['dues'], 2); ?></p>
                    <p class="text-[11px] font-bold text-slate-600 mt-1">Seller Dues</p>
                    <p class="text-[9.5px] text-slate-400 mt-0.5">verified, not yet handed over</p>
                </a>
            </div>
            <?php endif; ?>

            <div class="grid grid-cols-2 gap-2.5 mb-5">
                <div class="al-stat"><div class="al-stat-ico bg-slate-50 text-slate-600 border-slate-100"><i class="fas fa-wallet"></i></div>
                    <div><p class="al-stat-k">Total Main Wallet</p><p class="al-stat-v text-slate-700">₹<?php echo number_format($ULS['wallet'], 2); ?></p></div></div>
                <div class="al-stat"><div class="al-stat-ico bg-amber-50 text-amber-600 border-amber-100"><i class="fas fa-gift"></i></div>
                    <div><p class="al-stat-k">Total Virtual Wallet</p><p class="al-stat-v text-amber-600">₹<?php echo number_format($ULS['virtual'], 2); ?></p></div></div>
            </div>

            <?php /* No "filter active" banner here. The page's own audience is
                      written into the filter fields on every load, so the banner
                      spent most of its life announcing a filter nobody chose.
                      What is actually switched on is visible in the boxes and in
                      the count line under them. */ ?>

            <!-- ===== FILTERS ===== -->
            <form method="GET" class="al-panel p-3 mb-5">
                <input type="hidden" name="f" value="users">
                <!-- keeps you inside the recycle bin when you press Apply -->
                <input type="hidden" name="trash" value="<?php echo $UL_TRASH ? '1' : ''; ?>">
                <?php
                /* ------------------------------------------------------------
                   THE FILTER BAR

                   One line, in the order you read a list in: who, when, where.
                   Search · the two dates · State · District · Time.

                   The User Type box has gone. Every one of these pages already
                   IS a type — User, Seller, Employees, Admin — and the box could
                   only ever contradict the page you were on.

                   The four narrower questions (KYC, subscription, account state,
                   wallet) sit under "More filters", open already whenever one of
                   them is on, so nothing can be switched on without being seen.
                   ------------------------------------------------------------ */
                $__more_on = ($UL['kyc'] !== '' || $UL['sub'] !== '' || $UL['status'] !== '' || $UL['wallet'] !== '');
                ?>
                <div x-data="{ more: <?php echo $__more_on ? 'true' : 'false'; ?> }">
                <div class="grid grid-cols-2 lg:grid-cols-4 xl:grid-cols-8 gap-2 items-end">
                    <div class="col-span-2">
                        <label class="al-l">Search</label>
                        <div class="relative">
                            <i class="fas fa-search absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 text-xs"></i>
                            <input name="search" value="<?php echo htmlspecialchars($UL['search']); ?>" placeholder="ID, code, name, phone or email" class="al-f pl-9">
                        </div>
                    </div>
                    <div class="col-span-2">
                        <label class="al-l">From &mdash; To</label>
                        <div class="flex gap-2">
                            <input type="date" name="from" value="<?php echo htmlspecialchars($UL['from']); ?>" title="From this date" class="al-f">
                            <input type="date" name="to"   value="<?php echo htmlspecialchars($UL['to']); ?>"   title="Up to this date" class="al-f">
                        </div>
                    </div>
                    <div><label class="al-l">State</label>
                        <select name="state" class="al-f" onchange="this.form.district.value=''">
                            <option value="">All states</option>
                            <?php foreach ($UL_STATES as $st): ?>
                                <option value="<?php echo esc($st); ?>" <?php echo $UL['state'] === $st ? 'selected' : ''; ?>><?php echo esc($st); ?></option>
                            <?php endforeach; ?>
                        </select></div>
                    <div><label class="al-l">District</label>
                        <select name="district" class="al-f">
                            <option value="">All districts<?php echo trim((string)$UL['state']) !== '' ? ' in ' . esc($UL['state']) : ''; ?></option>
                            <?php foreach ($UL_DISTRICTS as $dt): ?>
                                <option value="<?php echo esc($dt); ?>" <?php echo $UL['district'] === $dt ? 'selected' : ''; ?>><?php echo esc($dt); ?></option>
                            <?php endforeach; ?>
                        </select></div>
                    <div><label class="al-l">Time</label>
                        <select name="joined" class="al-f">
                            <option value="">All time</option>
                            <option value="today"  <?php echo $UL['joined']==='today'?'selected':''; ?>>Today</option>
                            <option value="7"      <?php echo $UL['joined']==='7'?'selected':''; ?>>Last 7 days</option>
                            <option value="30"     <?php echo $UL['joined']==='30'?'selected':''; ?>>Last 30 days</option>
                            <option value="month"  <?php echo $UL['joined']==='month'?'selected':''; ?>>This month</option>
                            <option value="year"   <?php echo $UL['joined']==='year'?'selected':''; ?>>This year</option>
                        </select></div>
                    <div class="flex gap-2">
                        <button class="al-btn al-btn-apply flex-1"><i class="fas fa-search"></i> Search</button>
                        <a href="<?php echo esc($UL_PAGE); ?>?reset=1" class="al-btn al-btn-ghost" title="Clear every filter">Reset</a>
                    </div>
                </div>

                <!-- the narrower questions, folded away until they are wanted -->
                <div x-show="more" style="display:none" class="grid grid-cols-2 lg:grid-cols-4 xl:grid-cols-8 gap-2 items-end mt-2 pt-2 border-t border-slate-100">
                    <div><label class="al-l">KYC</label>
                        <select name="kyc" class="al-f">
                            <option value="">Any</option>
                            <option value="pending"  <?php echo $UL['kyc']==='pending'?'selected':''; ?>>Pending</option>
                            <option value="approved" <?php echo $UL['kyc']==='approved'?'selected':''; ?>>Approved</option>
                            <option value="rejected" <?php echo $UL['kyc']==='rejected'?'selected':''; ?>>Rejected</option>
                            <option value="none"     <?php echo $UL['kyc']==='none'?'selected':''; ?>>Not submitted</option>
                        </select></div>
                    <div><label class="al-l">Subscription</label>
                        <select name="sub" class="al-f">
                            <option value="">Any</option>
                            <option value="yes" <?php echo $UL['sub']==='yes'?'selected':''; ?>>Subscribed</option>
                            <option value="no"  <?php echo $UL['sub']==='no'?'selected':''; ?>>Not subscribed</option>
                        </select></div>
                    <div><label class="al-l">Account</label>
                        <select name="status" class="al-f">
                            <option value="">Any</option>
                            <option value="1" <?php echo $UL['status']==='1'?'selected':''; ?>>Active</option>
                            <option value="0" <?php echo $UL['status']==='0'?'selected':''; ?>>Blocked</option>
                        </select></div>
                    <div><label class="al-l">Wallet</label>
                        <select name="wallet" class="al-f">
                            <option value="">Any</option>
                            <option value="nonzero" <?php echo $UL['wallet']==='nonzero'?'selected':''; ?>>Has balance</option>
                            <option value="zero"    <?php echo $UL['wallet']==='zero'?'selected':''; ?>>Zero balance</option>
                        </select></div>
                </div>

                <div class="flex flex-wrap items-center gap-3 mt-2">
                    <button type="button" @click="more = !more" class="text-[11px] font-bold text-indigo-600 hover:underline">
                        <i class="fas" :class="more ? 'fa-chevron-up' : 'fa-chevron-down'"></i>
                        <span x-text="more ? 'Fewer filters' : 'More filters'">More filters</span>
                    </button>
                    <?php if (ul_can('export')): ?>
                    <a href="<?php echo alist_url($UL_PAGE,$UL_FKEY,$UL,['export'=>1]); ?>" class="al-btn al-btn-csv"><i class="fas fa-file-csv"></i> Export CSV</a>
                    <span class="text-[10px] text-slate-400 leading-tight">Exports the list exactly as it is filtered now. Tick rows first to export only those.</span>
                    <?php endif; ?>
                </div>
                </div>
                <p class="text-[11px] text-slate-400 mt-2">
                    Showing <b class="text-slate-600"><?php echo $ul_from; ?>–<?php echo $ul_to; ?></b>
                    of <b class="text-slate-600"><?php echo number_format($ul_total_rows); ?></b> user(s)
                    &middot; page <b class="text-slate-600"><?php echo $ul_page; ?></b> of <?php echo $ul_pages; ?>
                    (<?php echo $UL_PER_PAGE; ?> per page).
                    Filters stay applied until you press Reset.
                </p>
            </form>

            <?php if ($success_msg): ?>
                <div class="mb-4 bg-emerald-50 border border-emerald-200 text-emerald-700 px-4 py-3 rounded-xl flex items-center shadow-sm"><i class="fas fa-check-circle text-xl mr-3"></i><span class="font-medium"><?php echo $success_msg; ?></span></div>
            <?php endif; ?>
            <?php if ($error_msg): ?>
                <div class="mb-4 bg-rose-50 border border-rose-200 text-rose-700 px-4 py-3 rounded-xl flex items-center shadow-sm"><i class="fas fa-exclamation-circle text-xl mr-3"></i><span class="font-medium"><?php echo $error_msg; ?></span></div>
            <?php endif; ?>

            <?php echo alist_styles(); ?>

            <?php if ($UL_TRASH): ?>
            <div class="mb-4 flex flex-wrap items-center gap-3 bg-slate-800 text-white px-4 py-3 rounded-xl">
                <i class="fas fa-trash-can text-lg text-rose-300"></i>
                <div class="min-w-0 flex-1">
                    <p class="font-extrabold text-sm">Deleted Users</p>
                    <p class="text-[11px] text-white/60">
                        These accounts cannot log in and are hidden everywhere else. Nothing was erased —
                        orders, wallet and commission history are intact, so a restore puts everything back.
                    </p>
                </div>
                <a href="users_all.php" class="px-4 py-2 rounded-lg bg-white/10 hover:bg-white/20 text-xs font-bold whitespace-nowrap">
                    <i class="fas fa-arrow-left mr-1"></i> Back to live users
                </a>
            </div>
            <?php endif; ?>

            <!-- ===== BULK ACTION BAR (appears as soon as a row is ticked) ===== -->
            <div class="ul-bulkbar" x-show="sel.length > 0" style="display:none;" x-transition>
                <span class="ul-bulk-count"><i class="fas fa-check-double mr-1.5"></i><span x-text="sel.length"></span> selected</span>
                <form method="POST" class="flex flex-wrap items-center gap-2"
                      @submit="if (!confirm('Apply this action to ' + sel.length + ' selected user(s)?')) $event.preventDefault()">
                    <input type="hidden" name="bulk_ids" :value="sel.join(',')">
                    <?php if ($UL_TRASH): ?>
                        <?php if (ul_can('restore')): ?>
                        <button type="submit" name="bulk_action" value="restore" class="ul-bulk-btn bg-emerald-600 hover:bg-emerald-700"><i class="fas fa-rotate-left"></i> Restore</button>
                        <?php if (ul_can('purge')): ?>
                        <button type="submit" name="bulk_action" value="purge" class="ul-bulk-btn bg-black hover:bg-slate-800"
                                onclick="return confirm('Erase the ticked account(s) for good?\n\nThis cannot be undone. Their orders, wallet history and commission records are kept — only the account itself goes.')">
                            <i class="fas fa-fire"></i> Delete for ever
                        </button>
                        <?php endif; ?>
                        <?php endif; ?>
                    <?php else: ?>
                        <?php if (ul_can('block')): ?>
                        <button type="submit" name="bulk_action" value="activate"      class="ul-bulk-btn bg-emerald-600 hover:bg-emerald-700"><i class="fas fa-circle-check"></i> Activate</button>
                        <?php endif; ?>
                        <?php if (ul_can('block')): ?>
                        <button type="submit" name="bulk_action" value="suspend"       class="ul-bulk-btn bg-rose-600 hover:bg-rose-700"><i class="fas fa-ban"></i> Suspend</button>
                        <?php endif; ?>
                        <?php if (ul_can('edit')): ?>
                        <button type="submit" name="bulk_action" value="make_customer" class="ul-bulk-btn bg-blue-600 hover:bg-blue-700"><i class="fas fa-user"></i> Make Customer</button>
                        <?php endif; ?>
                        <?php if (ul_can('edit')): ?>
                        <button type="submit" name="bulk_action" value="make_seller"   class="ul-bulk-btn bg-amber-600 hover:bg-amber-700"><i class="fas fa-store"></i> Make Seller</button>
                        <?php endif; ?>
                        <?php if (ul_can('upgrade')): ?>
                        <button type="submit" name="bulk_action" value="subscribe"     class="ul-bulk-btn bg-fuchsia-600 hover:bg-fuchsia-700"><i class="fas fa-gem"></i> Subscribe</button>
                        <?php endif; ?>
                        <?php if (ul_can('upgrade')): ?>
                        <button type="submit" name="bulk_action" value="unsubscribe"   class="ul-bulk-btn bg-slate-600 hover:bg-slate-700"><i class="fas fa-xmark"></i> Unsubscribe</button>
                        <?php endif; ?>
                        <?php if (ul_can('delete')): ?>
                        <button type="submit" name="bulk_action" value="delete"        class="ul-bulk-btn bg-red-700 hover:bg-red-800"><i class="fas fa-trash"></i> Delete</button>
                        <?php endif; ?>
                    <?php endif; ?>
                </form>
                <?php if (ul_can('export')): ?>
                <a href="#" @click.prevent="window.location = '<?php echo alist_url($UL_PAGE,$UL_FKEY,$UL,['export'=>1]); ?>&ids=' + sel.join(',')"
                   class="ul-bulk-btn bg-emerald-600 hover:bg-emerald-700"><i class="fas fa-file-csv"></i> Export <span x-text="sel.length"></span> selected</a>
                <?php endif; ?>
                <button type="button" @click="sel = []" class="ul-bulk-clear"><i class="fas fa-xmark mr-1"></i>Clear</button>
            </div>

            <!-- ===== DESKTOP TABLE ===== -->
            <div class="hidden lg:block bg-white rounded-2xl shadow-sm border-2 border-slate-300 overflow-hidden">

                <!-- top scroll bar: mirrors the table's horizontal scrolling so you can
                     slide the columns without going to the bottom of the page -->
                <div class="ul-topscroll" id="ulTopScroll"><div id="ulTopScrollInner"></div></div>

                <div class="overflow-x-auto wbfz" id="ulScroll">
                    <table class="ul w-full text-left border-collapse text-xs" id="ulTable">
                        <thead>
                            <tr class="bg-slate-50 text-[10px] uppercase text-slate-500 tracking-wider">
                                <th class="p-3 font-semibold border-b border-gray-200 w-9">
                                    <input type="checkbox" class="ul-check" title="Select all on this page"
                                           :checked="allOnPage()" @change="toggleAll($event.target.checked)">
                                </th>
                                <?php if (ul_col('profile')): ?><th class="p-3 font-semibold border-b border-gray-200">Profile</th><?php endif; ?>
                                <?php if (ul_col('details')): ?><th class="p-3 font-semibold border-b border-gray-200">User Details</th><?php endif; ?>
                                <?php if (ul_col('address')): ?><th class="p-3 font-semibold border-b border-gray-200">Village / Locality<br>Post Office<br>Block / City / Municipality<br>Landmark</th><?php endif; ?>
                                <?php if (ul_col('region')): ?><th class="p-3 font-semibold border-b border-gray-200">State, District,<br>Pin Code</th><?php endif; ?>
                                <?php if (ul_col('type')): ?><th class="p-3 font-semibold border-b border-gray-200">User Type,<br>Date &amp; Time</th><?php endif; ?>
                                <?php if (ul_col('created_by')): ?><th class="p-3 font-semibold border-b border-gray-200">Created By</th><?php endif; ?>
                                <?php if (ul_col('kyc')): ?><th class="p-3 font-semibold border-b border-gray-200">KYC Status</th><?php endif; ?>
                                <?php if (ul_col('subscription')): ?><th class="p-3 font-semibold border-b border-gray-200">Subscription</th><?php endif; ?>
                                <?php if (ul_col('balance')): ?><th class="p-3 font-semibold border-b border-gray-200">Balance</th><?php endif; ?>
                                <?php if (ul_col('transfer') && ul_can('wallet')): ?><th class="p-3 font-semibold border-b border-gray-200 min-w-[140px]">Transfer</th><?php endif; ?>
                                <?php if (ul_col('quick')): ?><th class="p-3 font-semibold border-b border-gray-200 min-w-[110px]">Quick Response</th><?php endif; ?>
                                <?php if (ul_col('notes')): ?><th class="p-3 font-semibold border-b border-gray-200 min-w-[110px]">Notes</th><?php endif; ?>
                                <?php if (ul_col('update')): ?><th class="p-3 font-semibold border-b border-gray-200 min-w-[120px]">Update</th><?php endif; ?>
                                <?php if (ul_col('action')): ?><th class="p-3 font-semibold border-b border-gray-200 min-w-[130px]">Action</th><?php endif; ?>
                            </tr>
                        </thead>
                        <tbody class="divide-y divide-gray-100">
                        <?php if(!empty($customers)): foreach($customers as $c):
                            $code = userCode($c['id']);
                            $call = !empty($c['call_number']) ? $c['call_number'] : $c['mobile'];
                            $wa   = !empty($c['whatsapp_number']) ? $c['whatsapp_number'] : $c['mobile'];
                            // Address: prefer KYC-submitted address, else registration data
                            $has_kyc   = !empty($c['kyc_id']);
                            $pick = function($kkey, $ukey) use ($c, $has_kyc) {
                                if ($has_kyc && !empty($c[$kkey])) return $c[$kkey];
                                return $c[$ukey] ?? '';
                            };
                            $a_village = $pick('k_village', 'village');
                            $a_post    = $pick('k_post_office', 'post_office');
                            $a_block   = $pick('k_block_city', 'block_city');
                            $a_land    = $pick('k_landmark', 'landmark');
                            $a_state   = $pick('k_state', 'state');
                            $a_dist    = $pick('k_district', 'district');
                            $a_pin     = $pick('k_pincode', 'pincode');
                            $kyc_status = $c['kyc_status'] ?? '';
                            $jsName = htmlspecialchars(addslashes($c['name']), ENT_QUOTES);
                        ?>
                            <tr class="hover:bg-slate-50/50 transition align-top" :class="isSel(<?php echo (int)$c['id']; ?>) ? 'bg-indigo-50/60' : ''">
                                <!-- BULK SELECT -->
                                <td class="p-3">
                                    <input type="checkbox" class="ul-check"
                                           :checked="isSel(<?php echo (int)$c['id']; ?>)"
                                           @change="toggleOne(<?php echo (int)$c['id']; ?>)">
                                </td>
                                <?php if (ul_col('profile')): ?>
                                <!-- PROFILE (existing: profile_pic) -->
                                <td class="p-3">
                                    <?php if(!empty($c['profile_pic']) && file_exists('../uploads/profiles/'.$c['profile_pic'])): ?>
                                        <img src="../uploads/profiles/<?php echo $c['profile_pic']; ?>" class="w-12 h-12 rounded-lg object-cover border border-gray-200">
                                    <?php else: ?>
                                        <div class="w-12 h-12 rounded-lg bg-indigo-100 text-indigo-600 flex items-center justify-center font-bold"><?php echo strtoupper(substr($c['name'],0,1)); ?></div>
                                    <?php endif; ?>
                                </td>
                                <?php endif; ?>
<?php if (ul_col('details')): ?>
                                <!-- USER DETAILS (existing: code, name, mobile, email) -->
                                <td class="p-3">
                                    <p class="font-bold text-slate-800"><?php echo $code; ?></p>
                                    <p class="font-semibold text-slate-700 uppercase"><?php echo htmlspecialchars($c['name']); ?></p>
                                    <p class="text-slate-500"><?php echo htmlspecialchars($c['mobile']); ?></p>
                                    <p class="text-slate-500 lowercase"><?php echo htmlspecialchars($c['email']); ?></p>
                                </td>
                                <?php endif; ?>
<?php if (ul_col('address')): ?>
                                <!-- ADDRESS BLOCK (from KYC if submitted, else registration) -->
                                <td class="p-3 text-slate-700 leading-5">
                                    <p><?php echo !empty($a_village) ? htmlspecialchars($a_village) : '<span class="text-slate-300">—</span>'; ?></p>
                                    <p><?php echo !empty($a_post) ? htmlspecialchars($a_post) : '<span class="text-slate-300">—</span>'; ?></p>
                                    <p><?php echo !empty($a_block) ? htmlspecialchars($a_block) : '<span class="text-slate-300">—</span>'; ?></p>
                                    <p class="text-slate-500"><?php echo !empty($a_land) ? htmlspecialchars($a_land) : '<span class="text-slate-300">—</span>'; ?></p>
                                </td>
                                <?php endif; ?>
<?php if (ul_col('region')): ?>
                                <!-- STATE / DISTRICT / PIN (from KYC if submitted, else registration) -->
                                <td class="p-3 text-slate-700">
                                    <p class="font-semibold"><?php echo !empty($a_state) ? htmlspecialchars($a_state) : '<span class="text-slate-400">—</span>'; ?></p>
                                    <p><?php echo !empty($a_dist) ? htmlspecialchars($a_dist) : '<span class="text-slate-400">—</span>'; ?></p>
                                    <p class="text-slate-500"><?php echo !empty($a_pin) ? htmlspecialchars($a_pin) : '<span class="text-slate-400">—</span>'; ?></p>
                                </td>
                                <?php endif; ?>
<?php if (ul_col('type')): ?>
                                <!-- USER TYPE + DATE/TIME (existing) ; "Approved" line is # -->
                                <td class="p-3">
                                    <?php
                                        $utype = $type_labels[$c['user_type']] ?? ucfirst($c['user_type']);
                                        $utype_col = $c['user_type']==='customer' ? 'text-blue-600' : ($c['user_type']==='seller' ? 'text-emerald-600' : 'text-purple-600');
                                    ?>
                                    <p class="font-semibold uppercase <?php echo $utype_col; ?>"><?php echo $utype; ?></p>
                                    <p class="text-slate-500"><?php echo date('d/m/Y', strtotime($c['created_at'])); ?></p>
                                    <p class="text-slate-500"><?php echo date('h:i A', strtotime($c['created_at'])); ?></p>
                                    <?php $__act = ((int)($c['status'] ?? 1) === 1); ?>
                                    <span class="inline-block mt-1 px-2 py-0.5 rounded-full text-[9px] font-black uppercase <?php echo $__act ? 'bg-emerald-100 text-emerald-700' : 'bg-rose-100 text-rose-700'; ?>">
                                        <?php echo $__act ? 'Approved' : 'Blocked'; ?>
                                    </span>
                                </td>
                                <?php endif; ?>
<?php if (ul_col('created_by')): ?>
                                <!-- CREATED BY — the admin who opened the account, else the referrer -->
                                <td class="p-3">
                                    <?php if (!empty($c['created_by'])): ?>
                                        <p class="font-bold text-slate-800"><?php echo userCode((int)$c['created_by']); ?></p>
                                        <p class="text-slate-600 uppercase"><?php echo htmlspecialchars($c['created_by_name'] ?? ''); ?></p>
                                        <span class="inline-block mt-1 px-2 py-0.5 rounded-full text-[9px] font-black uppercase bg-indigo-100 text-indigo-700">Assigned by admin</span>
                                        <?php if (!empty($c['ref_id'])): ?>
                                            <p class="text-[10px] text-slate-400 mt-1">Ref: <?php echo userCode($c['ref_id']); ?></p>
                                        <?php endif; ?>
                                    <?php elseif (!empty($c['ref_id'])): ?>
                                        <p class="font-bold text-slate-800"><?php echo userCode($c['ref_id']); ?></p>
                                        <p class="text-slate-600 uppercase"><?php echo htmlspecialchars($c['ref_name']); ?></p>
                                        <span class="inline-block mt-1 px-2 py-0.5 rounded-full text-[9px] font-black uppercase bg-emerald-100 text-emerald-700">Referral</span>
                                    <?php else: ?>
                                        <span class="text-slate-400 text-[11px]">Direct / Self</span>
                                    <?php endif; ?>
                                </td>
                                <?php endif; ?>
<?php if (ul_col('kyc')): ?>
                                <!-- KYC STATUS (from kyc_details; click to review) -->
                                <td class="p-3">
                                    <?php
                                        $kyc_map = [
                                            'approved' => ['Approved', 'bg-emerald-100 text-emerald-700 border-emerald-200'],
                                            'pending'  => ['Pending',  'bg-amber-100 text-amber-700 border-amber-200'],
                                            'rejected' => ['Rejected', 'bg-rose-100 text-rose-700 border-rose-200'],
                                        ];
                                    ?>
                                    <?php if($has_kyc && isset($kyc_map[$kyc_status])): ?>
                                        <button type="button" <?php echo ul_can('kyc') ? '' : 'disabled title="You have not been given KYC approval"'; ?> @click="openKyc(<?php echo $c['id']; ?>, '<?php echo $jsName ?? ''; ?>')" class="text-[10px] font-bold px-2.5 py-1 rounded-full uppercase border whitespace-nowrap <?php echo $kyc_map[$kyc_status][1]; ?> hover:shadow">
                                            <?php echo $kyc_map[$kyc_status][0]; ?> <i class="fas fa-eye ml-0.5"></i>
                                        </button>
                                    <?php else: ?>
                                        <span class="text-[10px] font-bold px-2.5 py-1 rounded-full uppercase border bg-slate-100 text-slate-400 border-slate-200 whitespace-nowrap">Not submitted</span>
                                    <?php endif; ?>
                                </td>
                                <?php endif; ?>
<?php if (ul_col('subscription')): ?>
                                <!-- SUBSCRIPTION (existing: is_subscribed) -->
                                <td class="p-3">
                                    <?php if(!empty($c['is_subscribed']) && $c['is_subscribed'] == 1): ?>
                                        <span class="bg-emerald-100 text-emerald-700 text-[10px] font-bold px-2.5 py-1 rounded-full uppercase border border-emerald-200">Yes</span>
                                    <?php else: ?>
                                        <span class="bg-slate-100 text-slate-500 text-[10px] font-bold px-2.5 py-1 rounded-full uppercase border border-slate-200">No</span>
                                    <?php endif; ?>
                                </td>
                                <?php endif; ?>
<?php if (ul_col('balance')): ?>
                                <!-- BALANCE (existing: wallet_balance) -->
                                <td class="p-3">
                                    <span class="font-bold text-emerald-600 whitespace-nowrap">₹<?php echo number_format($c['wallet_balance'], 2); ?></span>
                                </td>
                                <?php endif; ?>
<?php if (ul_col('transfer') && ul_can('wallet')): ?>
                                <!-- TRANSFER (existing: credit wallet + log txn ; Transfer Type = #) -->
                                <td class="p-3">
                                    <button type="button" @click="openMoney(<?php echo (int)$c['id']; ?>, '<?php echo htmlspecialchars(addslashes($c['name']), ENT_QUOTES); ?>', <?php echo (float)$c['wallet_balance']; ?>, <?php echo (float)($c['bonus_wallet'] ?? 0); ?>)"
                                            class="cell-btn bg-blue-600 hover:bg-blue-700 w-full"><i class="fas fa-right-left mr-1"></i>Credit / Debit</button>
                                </td>
                                <?php endif; ?>
<?php if (ul_col('quick')): ?>
                                <!-- QUICK RESPONSE (existing: call/whatsapp/email links ; Chatbot = #) -->
                                <td class="p-3 space-y-1">
                                    <a href="tel:<?php echo htmlspecialchars($call); ?>" class="cell-btn bg-slate-500 hover:bg-slate-600"><i class="fas fa-phone-alt mr-1"></i>Call</a>
                                    <a href="https://wa.me/91<?php echo preg_replace('/\D/','',$wa); ?>" target="_blank" class="cell-btn bg-green-500 hover:bg-green-600"><i class="fab fa-whatsapp mr-1"></i>Whatsapp</a>
                                    <a href="mailto:<?php echo htmlspecialchars($c['email']); ?>" class="cell-btn bg-rose-600 hover:bg-rose-700"><i class="fas fa-envelope mr-1"></i>Email</a>
                                    <span class="cell-btn bg-purple-300 cursor-not-allowed" title="# Chatbot integration pending"># Chatbot</span>
                                </td>
                                <?php endif; ?>
<?php if (ul_col('notes')): ?>
                                <!-- NOTES (working: user_notes table) -->
                                <td class="p-3 space-y-1">
                                    <button type="button" @click="openNotesHistory(<?php echo $c['id']; ?>, '<?php echo $jsName; ?>')" class="cell-btn bg-cyan-500 hover:bg-cyan-600"><i class="fas fa-clock-rotate-left mr-1"></i>History</button>
                                    <?php if (ul_can('note')): ?><button type="button" @click="openNewNote(<?php echo $c['id']; ?>, '<?php echo $jsName; ?>')" class="cell-btn bg-amber-500 hover:bg-amber-600"><i class="fas fa-plus mr-1"></i>New Notes</button><?php endif; ?>
                                </td>
                                <?php endif; ?>
<?php if (ul_col('update')): ?>
                                <!-- UPDATE (working: update form, history log, reset password) -->
                                <td class="p-3 space-y-1">
                                    <?php if (ul_can('edit')): ?><button type="button" @click="openEditUser(<?php echo $c['id']; ?>, '<?php echo $jsName; ?>')" class="cell-btn bg-indigo-600 hover:bg-indigo-700"><i class="fas fa-user-pen mr-1"></i>Edit Details</button><?php endif; ?>
                                    <button type="button" @click="openUpdateHistory(<?php echo $c['id']; ?>, '<?php echo $jsName; ?>')" class="cell-btn bg-orange-500 hover:bg-orange-600"><i class="fas fa-clock-rotate-left mr-1"></i>Update History</button>
                                    <button type="button" @click="openUpdateForm(<?php echo $c['id']; ?>, '<?php echo $jsName; ?>')" class="cell-btn bg-lime-600 hover:bg-lime-700"><i class="fas fa-pen mr-1"></i>Update KYC</button>
                                    <?php if (ul_can('password')): ?><button type="button" @click="openReset(<?php echo $c['id']; ?>, '<?php echo $jsName; ?>')" class="cell-btn bg-red-600 hover:bg-red-700"><i class="fas fa-key mr-1"></i>Reset Password</button><?php endif; ?>
                                    <?php /* Open this member's own dashboard and work inside it. Staff
                                             accounts are left out on purpose — see admin/switch_user.php. */ ?>
                                    <?php if ((string)$c['user_type'] !== 'admin' && empty($c['deleted_at'])): ?>
                                    <a href="switch_user.php?uid=<?php echo (int)$c['id']; ?>"
                                       onclick="return confirm('Open <?php echo $jsName; ?>\'s dashboard as them? A gold bar will show until you come back.')"
                                       class="cell-btn bg-amber-500 hover:bg-amber-600 block text-center"><i class="fas fa-right-to-bracket mr-1"></i>Switch Mode</a>
                                    <?php endif; ?>
                                </td>
                                <?php endif; ?>
<?php if (ul_col('action')): ?>
                                <!-- ACTION (account status + role change + delete) -->
                                <td class="p-3 space-y-1">
                                    <?php if ($UL_TRASH): ?>
                                        <span class="cell-btn bg-slate-500 cursor-default">
                                            <i class="fas fa-trash-can mr-1"></i>Deleted
                                        </span>
                                        <p class="text-[9px] text-slate-400 leading-tight py-0.5">
                                            <?php echo !empty($c['deleted_at']) ? date('d M Y, h:i A', strtotime($c['deleted_at'])) : ''; ?>
                                            <?php if (!empty($c['delete_reason'])): ?><br><?php echo htmlspecialchars($c['delete_reason']); ?><?php endif; ?>
                                        </p>
                                        <form method="POST" onsubmit="return confirm('Restore this user? They will be able to log in again.');">
                                            <input type="hidden" name="target_user_id" value="<?php echo (int)$c['id']; ?>">
                                            <button type="submit" name="restore_user" class="cell-btn bg-emerald-600 hover:bg-emerald-700"><i class="fas fa-rotate-left mr-1"></i>Restore</button>
                                        </form>
                                    <?php else: ?>
                                    <?php $__ok = ((int)($c['status'] ?? 1) === 1); ?>
                                    <span class="cell-btn <?php echo $__ok ? 'bg-emerald-500' : 'bg-rose-500'; ?> cursor-default">
                                        <i class="fas <?php echo $__ok ? 'fa-circle-check' : 'fa-ban'; ?> mr-1"></i><?php echo $__ok ? 'Approved' : 'Blocked'; ?>
                                    </span>
                                    <form method="POST" onsubmit="return confirm('Change this user type?');" class="space-y-1">
                                        <input type="hidden" name="target_user_id" value="<?php echo $c['id']; ?>">
                                        <select name="new_role" class="w-full border border-gray-300 rounded px-2 py-1 text-xs">
                                            <option value="customer">Customer</option>
                                            <option value="seller">Seller</option>
                                        </select>
                                        <button type="submit" name="change_role" class="cell-btn bg-blue-600 hover:bg-blue-700">SUBMIT</button>
                                    </form>
                                    <form method="POST" class="pt-1">
                                        <input type="hidden" name="target_user_id" value="<?php echo $c['id']; ?>">
                                        <input type="hidden" name="current_status" value="<?php echo $c['status']; ?>">
                                        <button type="submit" name="toggle_status" class="cell-btn <?php echo $c['status']==1 ? 'bg-emerald-500 hover:bg-emerald-600' : 'bg-rose-500 hover:bg-rose-600'; ?>">
                                            <?php echo $c['status']==1 ? 'Active (Suspend)' : 'Suspended (Activate)'; ?>
                                        </button>
                                    </form>

                                    <?php if ((int)$c['id'] !== (int)$me['id']): ?>
                                    <form method="POST" class="pt-1"
                                          onsubmit="return confirm('Delete <?php echo $jsName; ?>?\n\nThe account is moved to Deleted Users — orders, wallet and commission history stay intact and you can restore it later.');">
                                        <input type="hidden" name="target_user_id" value="<?php echo (int)$c['id']; ?>">
                                        <input type="text" name="delete_reason" placeholder="Reason (optional)"
                                               class="w-full border border-gray-300 rounded px-2 py-1 text-[10px] mb-1">
                                        <?php if (ul_can('delete')): ?><button type="submit" name="delete_user" class="cell-btn bg-red-700 hover:bg-red-800"><i class="fas fa-trash mr-1"></i>Delete</button><?php endif; ?>
                                    </form>
                                    <?php endif; ?>
                                    <?php endif; /* end $UL_TRASH */ ?>
                                </td>
                                <?php endif; ?>
                            </tr>
                        <?php endforeach; else: ?>
                            <tr><td colspan="<?php echo (int)$UL_COLS; ?>" class="p-12 text-center text-gray-500">
                                <div class="w-16 h-16 bg-gray-50 rounded-full flex items-center justify-center mx-auto mb-4 text-gray-400 text-2xl border border-gray-100"><i class="fas fa-users-slash"></i></div>
                                <p class="text-lg font-medium">No users found.</p>
                            </td></tr>
                        <?php endif; ?>
                        </tbody>
                    </table>
                </div>
            </div>

            <!-- ===== MOBILE / TABLET CARDS ===== -->
            <div class="lg:hidden space-y-3">
            <?php if(!empty($customers)): foreach($customers as $c):
                $mcall = !empty($c['call_number']) ? $c['call_number'] : $c['mobile'];
                $mwa   = !empty($c['whatsapp_number']) ? $c['whatsapp_number'] : $c['mobile'];
                $mact  = ((int)($c['status'] ?? 1) === 1);
                $mtype = $type_labels[$c['user_type']] ?? ucfirst($c['user_type']);
                $mtcol = $c['user_type']==='customer' ? 'blue' : ($c['user_type']==='seller' ? 'emerald' : 'purple');
                $mkyc  = $c['kyc_status'] ?? '';
                $mkcol = $mkyc==='approved' ? 'emerald' : ($mkyc==='pending' ? 'amber' : ($mkyc==='rejected' ? 'rose' : 'slate'));
                $mvill = $c['k_village'] ?: ($c['village'] ?? '');
                $mdist = $c['k_district'] ?: ($c['district'] ?? '');
                $mstate= $c['k_state'] ?: ($c['state'] ?? '');
                $mpin  = $c['k_pincode'] ?: ($c['pincode'] ?? '');
                $maddr = trim(implode(', ', array_filter([$mvill, $mdist, $mstate, $mpin])));
            ?>
                <div class="bg-white rounded-2xl border border-slate-200 shadow-sm overflow-hidden">
                    <!-- header -->
                    <div class="p-3.5 flex items-start gap-3 border-b border-slate-100">
                        <div class="w-11 h-11 rounded-xl bg-slate-100 flex items-center justify-center text-sm font-black text-slate-500 flex-shrink-0 overflow-hidden">
                            <?php if(!empty($c['profile_pic'])): ?>
                                <img src="../uploads/profiles/<?php echo htmlspecialchars($c['profile_pic']); ?>" class="w-full h-full object-cover" alt="">
                            <?php else: ?><?php echo strtoupper(substr($c['name'], 0, 2)); ?><?php endif; ?>
                        </div>
                        <div class="min-w-0 flex-1">
                            <div class="flex flex-wrap items-center gap-1.5 mb-0.5">
                                <span class="font-mono text-[10px] font-bold text-slate-400"><?php echo userCode($c['id']); ?></span>
                                <span class="px-1.5 py-0.5 rounded text-[9px] font-black uppercase bg-<?php echo $mtcol; ?>-50 text-<?php echo $mtcol; ?>-600"><?php echo $mtype; ?></span>
                                <span class="px-1.5 py-0.5 rounded text-[9px] font-black uppercase <?php echo $mact ? 'bg-emerald-100 text-emerald-700' : 'bg-rose-100 text-rose-700'; ?>"><?php echo $mact ? 'Approved' : 'Blocked'; ?></span>
                            </div>
                            <p class="font-extrabold text-slate-800 text-sm leading-tight truncate"><?php echo htmlspecialchars($c['name']); ?></p>
                            <p class="text-[11px] text-slate-500 truncate"><?php echo htmlspecialchars($c['mobile']); ?><?php if(!empty($c['email'])): ?> · <?php echo htmlspecialchars($c['email']); ?><?php endif; ?></p>
                        </div>
                    </div>

                    <!-- facts -->
                    <div class="grid grid-cols-2 gap-px bg-slate-100">
                        <div class="bg-white p-2.5">
                            <p class="text-[9px] font-black uppercase tracking-wider text-slate-400">Main Wallet</p>
                            <p class="text-sm font-black text-emerald-600">₹<?php echo number_format((float)$c['wallet_balance'], 2); ?></p>
                        </div>
                        <div class="bg-white p-2.5">
                            <p class="text-[9px] font-black uppercase tracking-wider text-slate-400">Virtual Wallet</p>
                            <p class="text-sm font-black text-amber-600">₹<?php echo number_format((float)($c['bonus_wallet'] ?? 0), 2); ?></p>
                        </div>
                        <div class="bg-white p-2.5">
                            <p class="text-[9px] font-black uppercase tracking-wider text-slate-400">KYC</p>
                            <p class="text-[11px] font-bold text-<?php echo $mkcol; ?>-600 capitalize"><?php echo $mkyc ?: 'not submitted'; ?></p>
                        </div>
                        <div class="bg-white p-2.5">
                            <p class="text-[9px] font-black uppercase tracking-wider text-slate-400">Subscription</p>
                            <p class="text-[11px] font-bold <?php echo !empty($c['is_subscribed']) ? 'text-fuchsia-600' : 'text-slate-400'; ?>"><?php echo !empty($c['is_subscribed']) ? 'Subscribed' : 'Not subscribed'; ?></p>
                        </div>
                    </div>

                    <?php if($maddr !== '' || !empty($c['ref_id']) || !empty($c['created_by'])): ?>
                    <div class="px-3 py-2 border-t border-slate-100 space-y-0.5">
                        <?php if($maddr !== ''): ?>
                            <p class="text-[10px] text-slate-500"><i class="fas fa-location-dot w-3 text-slate-300 mr-1"></i><?php echo htmlspecialchars($maddr); ?></p>
                        <?php endif; ?>
                        <?php if(!empty($c['created_by'])): ?>
                            <p class="text-[10px] text-indigo-600"><i class="fas fa-user-shield w-3 text-indigo-300 mr-1"></i>Added by <b><?php echo htmlspecialchars($c['created_by_name'] ?? ''); ?></b> (<?php echo userCode((int)$c['created_by']); ?>)</p>
                        <?php endif; ?>
                        <?php if(!empty($c['ref_id'])): ?>
                            <p class="text-[10px] text-slate-500"><i class="fas fa-user-plus w-3 text-slate-300 mr-1"></i>Referred by <b><?php echo htmlspecialchars($c['ref_name']); ?></b> (<?php echo userCode($c['ref_id']); ?>)</p>
                        <?php endif; ?>
                        <p class="text-[10px] text-slate-400"><i class="fas fa-clock w-3 text-slate-300 mr-1"></i>Joined <?php echo date('d M Y, h:i A', strtotime($c['created_at'])); ?></p>
                    </div>
                    <?php endif; ?>

                    <!-- actions -->
                    <div class="p-2.5 border-t border-slate-100 bg-slate-50/60 space-y-2">
                        <button type="button" @click="openMoney(<?php echo (int)$c['id']; ?>, '<?php echo htmlspecialchars(addslashes($c['name']), ENT_QUOTES); ?>', <?php echo (float)$c['wallet_balance']; ?>, <?php echo (float)($c['bonus_wallet'] ?? 0); ?>)"
                                class="w-full py-2.5 rounded-xl bg-blue-600 hover:bg-blue-700 text-white text-xs font-bold">
                            <i class="fas fa-right-left mr-1.5"></i>Credit / Debit
                        </button>

                        <div class="grid grid-cols-3 gap-1.5">
                            <a href="tel:<?php echo htmlspecialchars($mcall); ?>" class="py-2 rounded-lg bg-white border border-slate-200 text-slate-600 text-[11px] font-bold text-center"><i class="fas fa-phone"></i></a>
                            <a href="https://wa.me/91<?php echo preg_replace('/\D/','',$mwa); ?>" target="_blank" class="py-2 rounded-lg bg-green-500 text-white text-[11px] font-bold text-center"><i class="fab fa-whatsapp"></i></a>
                            <a href="mailto:<?php echo htmlspecialchars($c['email']); ?>" class="py-2 rounded-lg bg-rose-500 text-white text-[11px] font-bold text-center"><i class="fas fa-envelope"></i></a>
                        </div>

                        <div class="grid grid-cols-2 gap-1.5">
                            <button type="button" @click="openUpdateForm(<?php echo $c['id']; ?>, '<?php echo htmlspecialchars(addslashes($c['name']), ENT_QUOTES); ?>')" class="py-2 rounded-lg bg-lime-600 text-white text-[11px] font-bold"><i class="fas fa-pen mr-1"></i>Update</button>
                            <button type="button" @click="openUpdateHistory(<?php echo $c['id']; ?>, '<?php echo htmlspecialchars(addslashes($c['name']), ENT_QUOTES); ?>')" class="py-2 rounded-lg bg-orange-500 text-white text-[11px] font-bold"><i class="fas fa-clock-rotate-left mr-1"></i>History</button>
                            <button type="button" @click="openNewNote(<?php echo $c['id']; ?>, '<?php echo htmlspecialchars(addslashes($c['name']), ENT_QUOTES); ?>')" class="py-2 rounded-lg bg-amber-500 text-white text-[11px] font-bold"><i class="fas fa-plus mr-1"></i>Note</button>
                            <button type="button" @click="openNotesHistory(<?php echo $c['id']; ?>, '<?php echo htmlspecialchars(addslashes($c['name']), ENT_QUOTES); ?>')" class="py-2 rounded-lg bg-cyan-500 text-white text-[11px] font-bold"><i class="fas fa-note-sticky mr-1"></i>Notes</button>
                        </div>

                        <?php if ($UL_TRASH): ?>
                        <form method="POST" onsubmit="return confirm('Restore this user?');">
                            <input type="hidden" name="target_user_id" value="<?php echo $c['id']; ?>">
                            <button type="submit" name="restore_user" class="w-full py-2 rounded-lg text-white text-[11px] font-bold bg-emerald-600">
                                <i class="fas fa-rotate-left mr-1"></i>Restore this account
                            </button>
                        </form>
                        <?php else: ?>
                        <form method="POST">
                            <input type="hidden" name="target_user_id" value="<?php echo $c['id']; ?>">
                            <input type="hidden" name="current_status" value="<?php echo $c['status']; ?>">
                            <button type="submit" name="toggle_status" class="w-full py-2 rounded-lg text-white text-[11px] font-bold <?php echo $mact ? 'bg-emerald-500' : 'bg-rose-500'; ?>">
                                <?php echo $mact ? 'Active — tap to suspend' : 'Suspended — tap to activate'; ?>
                            </button>
                        </form>
                        <?php if ((int)$c['id'] !== (int)$me['id']): ?>
                        <form method="POST" class="mt-1.5"
                              onsubmit="return confirm('Delete this user?\n\nThe account moves to Deleted Users and can be restored later.');">
                            <input type="hidden" name="target_user_id" value="<?php echo $c['id']; ?>">
                            <button type="submit" name="delete_user" class="w-full py-2 rounded-lg text-white text-[11px] font-bold bg-red-700">
                                <i class="fas fa-trash mr-1"></i>Delete user
                            </button>
                        </form>
                        <?php endif; ?>
                        <?php endif; ?>
                    </div>
                </div>
            <?php endforeach; else: ?>
                <div class="bg-white rounded-2xl border border-slate-200 p-12 text-center text-slate-400">
                    <i class="fas fa-users-slash text-3xl mb-3 block text-slate-300"></i>
                    <p class="text-sm font-semibold text-slate-500">No users found</p>
                </div>
            <?php endif; ?>
            </div>

            <?php
            /* ===================== PAGER (shared by desktop + mobile) ===================== */
            if ($ul_pages > 1):
                /* window of page numbers around the current one */
                $pw_start = max(1, $ul_page - 2);
                $pw_end   = min($ul_pages, $ul_page + 2);
                if ($pw_end - $pw_start < 4) {
                    $pw_start = max(1, min($pw_start, $ul_pages - 4));
                    $pw_end   = min($ul_pages, max($pw_end, $pw_start + 4));
                }
            ?>
            <nav class="ul-pager" aria-label="User list pages">
                <span class="ul-pager-info">
                    <?php echo $ul_from; ?>–<?php echo $ul_to; ?> of <?php echo number_format($ul_total_rows); ?>
                </span>

                <div class="ul-pager-btns">
                    <?php if ($ul_page > 1): ?>
                        <a href="<?php echo ul_page_url(1, $UL); ?>" class="ul-pg" title="First"><i class="fas fa-angles-left"></i></a>
                        <a href="<?php echo ul_page_url($ul_page - 1, $UL); ?>" class="ul-pg"><i class="fas fa-angle-left"></i> Prev</a>
                    <?php else: ?>
                        <span class="ul-pg is-off"><i class="fas fa-angles-left"></i></span>
                        <span class="ul-pg is-off"><i class="fas fa-angle-left"></i> Prev</span>
                    <?php endif; ?>

                    <?php if ($pw_start > 1): ?><span class="ul-pg-gap">…</span><?php endif; ?>
                    <?php for ($pn = $pw_start; $pn <= $pw_end; $pn++): ?>
                        <?php if ($pn === $ul_page): ?>
                            <span class="ul-pg is-now"><?php echo $pn; ?></span>
                        <?php else: ?>
                            <a href="<?php echo ul_page_url($pn, $UL); ?>" class="ul-pg"><?php echo $pn; ?></a>
                        <?php endif; ?>
                    <?php endfor; ?>
                    <?php if ($pw_end < $ul_pages): ?><span class="ul-pg-gap">…</span><?php endif; ?>

                    <?php if ($ul_page < $ul_pages): ?>
                        <a href="<?php echo ul_page_url($ul_page + 1, $UL); ?>" class="ul-pg">Next <i class="fas fa-angle-right"></i></a>
                        <a href="<?php echo ul_page_url($ul_pages, $UL); ?>" class="ul-pg" title="Last"><i class="fas fa-angles-right"></i></a>
                    <?php else: ?>
                        <span class="ul-pg is-off">Next <i class="fas fa-angle-right"></i></span>
                        <span class="ul-pg is-off"><i class="fas fa-angles-right"></i></span>
                    <?php endif; ?>
                </div>

                <form method="GET" class="ul-pager-jump">
                    <?php foreach ($UL as $__k => $__v): if ($__v === '' || $__v === null) continue; ?>
                        <input type="hidden" name="<?php echo htmlspecialchars($__k); ?>" value="<?php echo htmlspecialchars((string)$__v); ?>">
                    <?php endforeach; ?>
                    <input type="hidden" name="f" value="users">
                    <label>Go to</label>
                    <input type="number" name="p" min="1" max="<?php echo $ul_pages; ?>" value="<?php echo $ul_page; ?>">
                    <button type="submit"><i class="fas fa-arrow-right"></i></button>
                </form>
            </nav>
            <?php endif; ?>

            <div class="mt-4 bg-emerald-50 border border-emerald-200 rounded-xl p-4 text-xs text-emerald-800">
                <p class="font-bold mb-1"><i class="fas fa-circle-check mr-1"></i> Everything on this page is live</p>
                <p>Address, KYC, Subscription, Balance, Notes and Update History all read real data.
                   <b>Credit / Debit</b> now asks for a mandatory reason, and the account status column shows
                   <b>Approved</b> or <b>Blocked</b> from the user's real status.
                   Only <b>Chatbot</b> is still pending.</p>
            </div>
        </main>
    </div>
</div>

<!-- ================================================================
     MODALS  (Notes History / New Note / Update History / Update / Reset)
     ================================================================ -->
<template x-teleport="body">
<div x-show="modal" x-transition.opacity class="fixed inset-0 z-[100] flex items-center justify-center p-4" style="display:none;">
    <div class="absolute inset-0 bg-slate-900/60 backdrop-blur-sm" @click="close()"></div>

    <!-- ===== NOTES HISTORY ===== -->
    <!-- ================= CREDIT / DEBIT ================= -->
    <div x-show="modal==='money'" x-transition class="relative w-full sm:max-w-md bg-white rounded-t-3xl sm:rounded-2xl shadow-2xl overflow-hidden max-h-[92vh] flex flex-col">
        <div class="px-5 py-4 flex items-center justify-between flex-shrink-0"
             :style="money.action === 'credit' ? 'background:linear-gradient(135deg,#059669,#047857)' : 'background:linear-gradient(135deg,#e11d48,#be123c)'">
            <div class="min-w-0">
                <h3 class="text-white font-bold text-base"><i class="fas fa-right-left mr-2"></i><span x-text="money.action === 'credit' ? 'Credit Wallet' : 'Debit Wallet'"></span></h3>
                <p class="text-white/70 text-[11px] truncate" x-text="money.name + ' (ID ' + money.id + ')'"></p>
            </div>
            <button @click="modal=null" class="text-white/70 hover:text-white text-3xl leading-none">&times;</button>
        </div>

        <form method="POST" class="p-5 overflow-y-auto space-y-4">
            <input type="hidden" name="target_user_id" :value="money.id">
            <input type="hidden" name="transfer_action" :value="money.action">
            <input type="hidden" name="transfer_wallet" :value="money.wallet">

            <div class="grid grid-cols-2 gap-2">
                <button type="button" @click="money.action='credit'"
                        class="py-2.5 rounded-xl text-xs font-black border-2 transition-all"
                        :class="money.action==='credit' ? 'border-emerald-500 bg-emerald-50 text-emerald-700' : 'border-slate-200 text-slate-500'">
                    <i class="fas fa-plus mr-1"></i> CREDIT
                </button>
                <button type="button" @click="money.action='debit'"
                        class="py-2.5 rounded-xl text-xs font-black border-2 transition-all"
                        :class="money.action==='debit' ? 'border-rose-500 bg-rose-50 text-rose-700' : 'border-slate-200 text-slate-500'">
                    <i class="fas fa-minus mr-1"></i> DEBIT
                </button>
            </div>

            <div>
                <label class="al-l">Which wallet</label>
                <div class="grid grid-cols-2 gap-2">
                    <button type="button" @click="money.wallet='main'"
                            class="p-2.5 rounded-xl border-2 text-left transition-all"
                            :class="money.wallet==='main' ? 'border-indigo-500 bg-indigo-50' : 'border-slate-200'">
                        <span class="block text-[10px] font-bold uppercase text-slate-400">Main</span>
                        <span class="block text-sm font-black text-slate-800">₹<span x-text="money.main.toFixed(2)"></span></span>
                    </button>
                    <button type="button" @click="money.wallet='virtual'"
                            class="p-2.5 rounded-xl border-2 text-left transition-all"
                            :class="money.wallet==='virtual' ? 'border-amber-500 bg-amber-50' : 'border-slate-200'">
                        <span class="block text-[10px] font-bold uppercase text-slate-400">Virtual</span>
                        <span class="block text-sm font-black text-amber-600">₹<span x-text="money.virtual.toFixed(2)"></span></span>
                    </button>
                </div>
            </div>

            <div>
                <label class="al-l">Amount (₹) <span class="text-rose-500">*</span></label>
                <div class="relative">
                    <span class="absolute left-0 top-0 bottom-0 w-10 flex items-center justify-center text-slate-400 font-bold text-base pointer-events-none">₹</span>
                    <input type="number" step="0.01" min="0.01" name="transfer_amount" x-model.number="money.amount" required
                           inputmode="decimal" placeholder="0.00" class="al-f pl-10 text-base font-black"
                           :class="moneyErr() && 'border-rose-400 bg-rose-50'">
                </div>
                <p x-show="moneyErr()" x-cloak class="text-[11px] font-bold text-rose-600 mt-1"><i class="fas fa-circle-exclamation mr-1"></i><span x-text="moneyErr()"></span></p>
                <p x-show="money.amount > 0 && !moneyErr()" x-cloak class="text-[11px] text-slate-500 mt-1">
                    Balance after: <b class="text-slate-800">₹<span x-text="moneyAfter().toFixed(2)"></span></b>
                </p>
            </div>

            <div>
                <label class="al-l">Reason <span class="text-rose-500">*</span></label>
                <input name="transfer_reason" x-model="money.reason" required maxlength="150"
                       placeholder="Why is this being credited / debited?" class="al-f">
                <div class="flex flex-wrap gap-1.5 mt-2">
                    <template x-for="r in (money.action === 'credit' ? reasonsCredit : reasonsDebit)" :key="r">
                        <button type="button" @click="money.reason = r"
                                class="px-2.5 py-1 rounded-lg bg-slate-100 hover:bg-slate-200 text-[10.5px] font-bold text-slate-600" x-text="r"></button>
                    </template>
                </div>
            </div>

            <div>
                <label class="al-l">Extra note <span class="text-slate-400 font-normal normal-case">(optional)</span></label>
                <input name="transfer_note" maxlength="150" placeholder="Order id, ticket no, anything useful" class="al-f">
            </div>

            <div class="bg-slate-50 border border-slate-200 rounded-xl p-3 text-[11px] text-slate-600">
                <i class="fas fa-circle-info mr-1"></i> The reason is <b>required</b>. It is saved in the wallet history,
                the user's update history, and sent to the user as a notification.
            </div>

            <div class="flex gap-2">
                <button type="button" @click="modal=null" class="al-btn al-btn-ghost flex-1 py-3">Cancel</button>
                <button type="submit" name="wallet_transfer" :disabled="!moneyOk()"
                        class="al-btn flex-[2] py-3 text-white disabled:opacity-40 disabled:cursor-not-allowed"
                        :style="money.action === 'credit' ? 'background:#059669' : 'background:#e11d48'">
                    <i class="fas fa-check"></i> <span x-text="(money.action === 'credit' ? 'Credit ₹' : 'Debit ₹') + (Number(money.amount)||0).toFixed(2)"></span>
                </button>
            </div>
        </form>
    </div>

    <div x-show="modal==='notesHistory'" x-transition class="relative w-full max-w-lg bg-white rounded-2xl shadow-2xl overflow-hidden">
        <div class="bg-gradient-to-r from-cyan-500 to-blue-500 px-5 py-4 flex items-center justify-between">
            <h3 class="text-white font-bold text-lg"><i class="fas fa-clock-rotate-left mr-2"></i>Notes History</h3>
            <button @click="close()" class="text-white/80 hover:text-white text-xl"><i class="fas fa-times"></i></button>
        </div>
        <div class="px-5 py-2 bg-cyan-50 text-cyan-800 text-xs font-semibold border-b border-cyan-100"><i class="fas fa-user mr-1"></i><span x-text="curUser.name"></span></div>
        <div class="p-5 max-h-[60vh] overflow-y-auto">
            <template x-if="loading"><p class="text-center text-slate-400 py-6"><i class="fas fa-spinner fa-spin mr-2"></i>Loading...</p></template>
            <!-- List view -->
            <div x-show="!loading && !viewNote">
                <template x-if="notes.length===0"><p class="text-center text-slate-400 py-8"><i class="fas fa-note-sticky text-2xl mb-2 block"></i>No notes yet for this user.</p></template>
                <div class="space-y-2">
                    <template x-for="n in notes" :key="n.id">
                        <div class="flex items-center justify-between gap-3 p-3 rounded-xl border border-slate-100 bg-slate-50 hover:bg-slate-100 transition">
                            <div class="min-w-0">
                                <p class="font-bold text-slate-800 truncate" x-text="n.title"></p>
                                <p class="text-xs text-slate-500 mt-0.5">
                                    <i class="fas fa-user-pen mr-1"></i><span class="font-semibold text-indigo-600" x-text="n.created_by_name || 'Unknown'"></span>
                                    <span class="mx-1">•</span><span x-text="fmtDate(n.created_at)"></span>
                                </p>
                            </div>
                            <button @click="viewNote=n" class="flex-shrink-0 text-xs font-bold text-white bg-cyan-500 hover:bg-cyan-600 px-3 py-1.5 rounded-lg"><i class="fas fa-eye mr-1"></i>View</button>
                        </div>
                    </template>
                </div>
            </div>
            <!-- Single note view -->
            <div x-show="viewNote" class="space-y-3">
                <button @click="viewNote=null" class="text-xs font-semibold text-slate-500 hover:text-cyan-600"><i class="fas fa-arrow-left mr-1"></i>Back to list</button>
                <h4 class="text-lg font-bold text-slate-800" x-text="viewNote?.title"></h4>
                <p class="text-xs text-slate-500"><i class="fas fa-user-pen mr-1"></i><span x-text="viewNote?.created_by_name"></span> <span class="mx-1">•</span> <span x-text="fmtDate(viewNote?.created_at)"></span></p>
                <div class="bg-slate-50 border border-slate-100 rounded-xl p-4 text-sm text-slate-700 whitespace-pre-wrap" x-text="viewNote?.description || '(no description)'"></div>
            </div>
        </div>
    </div>

    <!-- ===== NEW NOTE ===== -->
    <div x-show="modal==='newNote'" x-transition class="relative w-full max-w-md bg-white rounded-2xl shadow-2xl overflow-hidden">
        <div class="bg-gradient-to-r from-amber-500 to-orange-500 px-5 py-4 flex items-center justify-between">
            <h3 class="text-white font-bold text-lg"><i class="fas fa-plus mr-2"></i>New Note</h3>
            <button @click="close()" class="text-white/80 hover:text-white text-xl"><i class="fas fa-times"></i></button>
        </div>
        <form method="POST" class="p-5 space-y-4">
            <input type="hidden" name="target_user_id" :value="curUser.id">
            <div>
                <label class="block text-xs font-semibold text-slate-600 mb-1">Note Title <span class="text-rose-500">*</span></label>
                <input name="note_title" required maxlength="255" class="w-full border border-slate-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-amber-400" placeholder="e.g. Called about pending KYC">
            </div>
            <div>
                <label class="block text-xs font-semibold text-slate-600 mb-1">Description</label>
                <textarea name="note_description" rows="4" class="w-full border border-slate-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-amber-400" placeholder="Write the note details..."></textarea>
            </div>
            <div class="flex justify-end gap-2 pt-1">
                <button type="button" @click="close()" class="px-4 py-2 text-sm font-semibold text-slate-600 hover:bg-slate-100 rounded-lg">Cancel</button>
                <button type="submit" name="add_note" class="px-5 py-2 text-sm font-bold text-white bg-amber-500 hover:bg-amber-600 rounded-lg shadow">Submit</button>
            </div>
        </form>
    </div>

    <!-- ===== UPDATE HISTORY ===== -->
    <div x-show="modal==='updateHistory'" x-transition class="relative w-full max-w-2xl bg-white rounded-2xl shadow-2xl overflow-hidden">
        <div class="bg-gradient-to-r from-orange-500 to-rose-500 px-5 py-4 flex items-center justify-between">
            <h3 class="text-white font-bold text-lg"><i class="fas fa-clock-rotate-left mr-2"></i>Update History</h3>
            <button @click="close()" class="text-white/80 hover:text-white text-xl"><i class="fas fa-times"></i></button>
        </div>
        <div class="px-5 py-2 bg-orange-50 text-orange-800 text-xs font-semibold border-b border-orange-100"><i class="fas fa-user mr-1"></i><span x-text="curUser.name"></span></div>
        <div class="p-5 max-h-[60vh] overflow-y-auto">
            <template x-if="loading"><p class="text-center text-slate-400 py-6"><i class="fas fa-spinner fa-spin mr-2"></i>Loading...</p></template>
            <template x-if="!loading && history.length===0"><p class="text-center text-slate-400 py-8"><i class="fas fa-clock-rotate-left text-2xl mb-2 block"></i>No updates recorded yet.</p></template>
            <div x-show="!loading && history.length" class="overflow-x-auto">
                <table class="w-full text-left text-xs">
                    <thead><tr class="text-slate-500 uppercase text-[10px] border-b">
                        <th class="py-2 pr-2">Field</th><th class="py-2 px-2">Old</th><th class="py-2 px-2">New</th><th class="py-2 px-2">By</th><th class="py-2 pl-2">When</th>
                    </tr></thead>
                    <tbody class="divide-y divide-slate-100">
                        <template x-for="h in history" :key="h.id">
                            <tr>
                                <td class="py-2 pr-2 font-bold text-slate-700" x-text="h.field_label"></td>
                                <td class="py-2 px-2 text-rose-500 max-w-[120px] truncate" x-text="h.old_value || '—'"></td>
                                <td class="py-2 px-2 text-emerald-600 max-w-[120px] truncate" x-text="h.new_value || '—'"></td>
                                <td class="py-2 px-2 font-semibold text-indigo-600" x-text="h.updated_by_name || '—'"></td>
                                <td class="py-2 pl-2 text-slate-500 whitespace-nowrap" x-text="fmtDate(h.updated_at)"></td>
                            </tr>
                        </template>
                    </tbody>
                </table>
            </div>
        </div>
    </div>

    <!-- ===== ADD NEW USER ===== -->
    <div x-show="modal==='addUser'" x-transition class="relative w-full max-w-3xl bg-white rounded-2xl shadow-2xl overflow-hidden max-h-[92vh] flex flex-col">
        <div class="bg-gradient-to-r from-indigo-600 to-blue-600 px-5 py-4 flex items-center justify-between flex-shrink-0">
            <div class="min-w-0">
                <h3 class="text-white font-bold text-lg"><i class="fas fa-user-plus mr-2"></i>Add New User</h3>
                <p class="text-white/70 text-[11px]">The account is created immediately and stamped with your name.</p>
            </div>
            <button @click="close()" class="text-white/80 hover:text-white text-2xl leading-none">&times;</button>
        </div>

        <form method="POST" class="flex flex-col overflow-hidden" @submit="if (!addOk()) { $event.preventDefault(); alert('Please check the password fields.'); }">
            <div class="p-5 overflow-y-auto space-y-5">

                <!-- who is adding -->
                <div class="flex items-center gap-3 bg-indigo-50 border border-indigo-100 rounded-xl px-4 py-3">
                    <i class="fas fa-user-shield text-indigo-500 text-lg"></i>
                    <div class="text-[11.5px] leading-relaxed text-indigo-800">
                        <b>Assigned by:</b> <?php echo htmlspecialchars($me['name']); ?>
                        (<?php echo userCode((int)$me['id']); ?>) &middot;
                        <?php echo date('d M Y, h:i A'); ?><br>
                        <span class="text-indigo-500">This is saved with the account and shown in the <b>Created By</b> column.</span>
                    </div>
                </div>

                <!-- Basic -->
                <div>
                    <p class="text-[11px] font-bold uppercase tracking-wide text-indigo-600 mb-2 border-b pb-1"><i class="fas fa-user mr-1"></i>Basic Details</p>
                    <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
                        <div><label class="lbl">Full Name <span class="text-rose-500">*</span></label>
                            <input name="name" x-model="newu.name" class="fld" required placeholder="As per documents"></div>
                        <div><label class="lbl">Gender</label>
                            <select name="gender" x-model="newu.gender" class="fld">
                                <option value="male">Male</option><option value="female">Female</option><option value="other">Other</option>
                            </select>
                        </div>
                        <div><label class="lbl">Mobile (login number) <span class="text-rose-500">*</span></label>
                            <input name="mobile" x-model="newu.mobile" class="fld" required inputmode="numeric" maxlength="15" placeholder="10-digit number"></div>
                        <div><label class="lbl">Email</label>
                            <input type="email" name="email" x-model="newu.email" class="fld" placeholder="Optional"></div>
                        <div><label class="lbl">Call Number</label>
                            <input name="call_number" x-model="newu.call_number" class="fld" placeholder="Falls back to mobile"></div>
                        <div><label class="lbl">WhatsApp Number</label>
                            <input name="whatsapp_number" x-model="newu.whatsapp_number" class="fld" placeholder="Falls back to mobile"></div>
                    </div>
                </div>

                <!-- Login -->
                <div>
                    <p class="text-[11px] font-bold uppercase tracking-wide text-rose-600 mb-2 border-b pb-1"><i class="fas fa-key mr-1"></i>Login Password</p>
                    <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
                        <div><label class="lbl">Password <span class="text-rose-500">*</span></label>
                            <input :type="showPass ? 'text' : 'password'" name="password" x-model="newu.password" class="fld" required minlength="6" autocomplete="new-password"></div>
                        <div><label class="lbl">Confirm Password <span class="text-rose-500">*</span></label>
                            <input :type="showPass ? 'text' : 'password'" name="password_confirm" x-model="newu.password_confirm" class="fld" required minlength="6" autocomplete="new-password"></div>
                    </div>
                    <div class="flex flex-wrap items-center gap-3 mt-2">
                        <label class="flex items-center gap-1.5 text-[11px] font-bold text-slate-500">
                            <input type="checkbox" x-model="showPass" class="rounded"> Show password
                        </label>
                        <button type="button" @click="genPass()" class="text-[11px] font-bold text-indigo-600 hover:underline">
                            <i class="fas fa-wand-magic-sparkles mr-1"></i>Suggest a strong one
                        </button>
                        <span class="text-[11px] font-bold text-rose-500" x-text="passErr()"></span>
                    </div>
                </div>

                <!-- Account -->
                <div>
                    <p class="text-[11px] font-bold uppercase tracking-wide text-emerald-600 mb-2 border-b pb-1"><i class="fas fa-id-badge mr-1"></i>Account</p>
                    <div class="grid grid-cols-1 md:grid-cols-3 gap-3">
                        <div><label class="lbl">User Type</label>
                            <select name="user_type" x-model="newu.user_type" class="fld">
                                <option value="customer">Customer</option>
                                <option value="seller">Seller</option>
                                <option value="admin">Staff / Admin</option>
                            </select>
                        </div>
                        <div><label class="lbl">Account Status</label>
                            <select name="status" x-model="newu.status" class="fld">
                                <option value="1">Active</option>
                                <option value="0">Blocked</option>
                            </select>
                        </div>
                        <div><label class="lbl">Subscription</label>
                            <select name="is_subscribed" x-model="newu.is_subscribed" class="fld">
                                <option value="0">Not subscribed</option>
                                <option value="1">Subscribed (Pro)</option>
                            </select>
                        </div>
                    </div>

                    <div class="grid grid-cols-1 md:grid-cols-2 gap-3 mt-3">
                        <div x-show="newu.user_type === 'seller'" style="display:none">
                            <label class="lbl">Business Name</label>
                            <input name="business_name" x-model="newu.business_name" class="fld" placeholder="Shown on the seller profile">
                        </div>
                        <div x-show="newu.user_type === 'admin'" style="display:none">
                            <label class="lbl">Staff Role</label>
                            <select name="role_id" x-model="newu.role_id" class="fld">
                                <option value="0">Full access (no role)</option>
                                <?php foreach ($ul_roles as $r): ?>
                                    <option value="<?php echo (int)$r['id']; ?>"><?php echo htmlspecialchars($r['name']); ?></option>
                                <?php endforeach; ?>
                            </select>
                        </div>
                        <div>
                            <label class="lbl">Referred By <span class="text-slate-400 normal-case font-medium">(optional)</span></label>
                            <input name="referral_code" x-model="newu.referral_code" class="fld" placeholder="e.g. WBMCZ0004 or a user ID">
                            <p class="text-[10px] text-slate-400 mt-1">Leave blank when nobody referred this member.</p>
                        </div>
                    </div>
                </div>

                <!-- Address -->
                <div>
                    <p class="text-[11px] font-bold uppercase tracking-wide text-blue-600 mb-2 border-b pb-1"><i class="fas fa-location-dot mr-1"></i>Address</p>
                    <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
                        <div><label class="lbl">Village / Locality</label><input name="village" x-model="newu.village" class="fld"></div>
                        <div><label class="lbl">Post Office</label><input name="post_office" x-model="newu.post_office" class="fld"></div>
                        <div><label class="lbl">Block / City / Municipality</label><input name="block_city" x-model="newu.block_city" class="fld"></div>
                        <div><label class="lbl">Landmark</label><input name="landmark" x-model="newu.landmark" class="fld"></div>
                        <div><label class="lbl">District</label><input name="district" x-model="newu.district" class="fld"></div>
                        <div><label class="lbl">State</label><input name="state" x-model="newu.state" class="fld"></div>
                        <div><label class="lbl">Pin Code</label><input name="pincode" x-model="newu.pincode" class="fld" inputmode="numeric" maxlength="6"></div>
                    </div>
                </div>

                <p class="text-[10px] text-slate-400">
                    <i class="fas fa-circle-info mr-1"></i>The member can log in straight away with this mobile number and password.
                    KYC can be filled in afterwards from <b>Update KYC</b>.
                </p>
            </div>

            <div class="flex justify-end gap-2 px-5 py-4 border-t bg-slate-50 flex-shrink-0">
                <button type="button" @click="close()" class="px-4 py-2 text-sm font-semibold text-slate-600 hover:bg-slate-200 rounded-lg">Cancel</button>
                <button type="submit" name="create_user" value="1" class="px-5 py-2 text-sm font-bold text-white bg-indigo-600 hover:bg-indigo-700 rounded-lg shadow">
                    <i class="fas fa-user-plus mr-1"></i>Create User
                </button>
            </div>
        </form>
    </div>

    <!-- ===== EDIT USER DETAILS (everything the list shows) ===== -->
    <div x-show="modal==='editUser'" x-transition class="relative w-full max-w-3xl bg-white rounded-2xl shadow-2xl overflow-hidden max-h-[92vh] flex flex-col">
        <div class="bg-gradient-to-r from-indigo-600 to-blue-600 px-5 py-4 flex items-center justify-between flex-shrink-0">
            <div class="min-w-0">
                <h3 class="text-white font-bold text-lg"><i class="fas fa-user-pen mr-2"></i>Edit User Details</h3>
                <p class="text-white/70 text-[11px] truncate" x-text="curUser.name + ' (ID ' + curUser.id + ')'"></p>
            </div>
            <button @click="close()" class="text-white/80 hover:text-white text-2xl leading-none">&times;</button>
        </div>

        <form method="POST" enctype="multipart/form-data" class="flex flex-col overflow-hidden">
            <input type="hidden" name="target_user_id" :value="curUser.id">

            <div class="p-5 overflow-y-auto space-y-5">
                <template x-if="loading"><p class="text-center text-slate-400 py-6"><i class="fas fa-spinner fa-spin mr-2"></i>Loading...</p></template>

                <div x-show="!loading" class="space-y-5">

                    <!-- Basic -->
                    <div>
                        <p class="text-[11px] font-bold uppercase tracking-wide text-indigo-600 mb-2 border-b pb-1"><i class="fas fa-user mr-1"></i>Basic Details</p>
                        <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
                            <div><label class="lbl">Full Name</label><input name="name" x-model="euser.name" class="fld" required></div>
                            <div><label class="lbl">Gender</label>
                                <select name="gender" x-model="euser.gender" class="fld">
                                    <option value="">&mdash;</option><option value="male">Male</option><option value="female">Female</option><option value="other">Other</option>
                                </select>
                            </div>
                            <div><label class="lbl">Mobile (login number)</label><input name="mobile" x-model="euser.mobile" class="fld" required></div>
                            <div><label class="lbl">Email</label><input type="email" name="email" x-model="euser.email" class="fld"></div>
                            <div><label class="lbl">Call Number</label><input name="call_number" x-model="euser.call_number" class="fld" placeholder="Falls back to mobile"></div>
                            <div><label class="lbl">WhatsApp Number</label><input name="whatsapp_number" x-model="euser.whatsapp_number" class="fld" placeholder="Falls back to mobile"></div>
                        </div>
                    </div>

                    <!-- Address -->
                    <div>
                        <p class="text-[11px] font-bold uppercase tracking-wide text-blue-600 mb-2 border-b pb-1"><i class="fas fa-location-dot mr-1"></i>Address</p>
                        <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
                            <div><label class="lbl">Village / Locality</label><input name="village" x-model="euser.village" class="fld"></div>
                            <div><label class="lbl">Post Office</label><input name="post_office" x-model="euser.post_office" class="fld"></div>
                            <div><label class="lbl">Block / City / Municipality</label><input name="block_city" x-model="euser.block_city" class="fld"></div>
                            <div><label class="lbl">Landmark</label><input name="landmark" x-model="euser.landmark" class="fld"></div>
                            <div><label class="lbl">District</label><input name="district" x-model="euser.district" class="fld"></div>
                            <div><label class="lbl">State</label><input name="state" x-model="euser.state" class="fld"></div>
                            <div><label class="lbl">Pin Code</label><input name="pincode" x-model="euser.pincode" class="fld"></div>
                        </div>
                        <p class="text-[10px] text-slate-400 mt-1.5">
                            <i class="fas fa-circle-info mr-1"></i>When a user has submitted KYC the list shows the KYC address &mdash; change that from <b>Update KYC</b>.
                        </p>
                    </div>

                    <!-- Account -->
                    <div>
                        <p class="text-[11px] font-bold uppercase tracking-wide text-emerald-600 mb-2 border-b pb-1"><i class="fas fa-id-badge mr-1"></i>Account</p>
                        <div class="grid grid-cols-1 md:grid-cols-3 gap-3">
                            <div><label class="lbl">User Type</label>
                                <select name="user_type" x-model="euser.user_type" class="fld">
                                    <option value="customer">Customer</option>
                                    <option value="seller">Seller</option>
                                    <option value="admin">Staff / Admin</option>
                                </select>
                            </div>
                            <div><label class="lbl">Account Status</label>
                                <select name="status" x-model="euser.status" class="fld">
                                    <option value="1">Active</option>
                                    <option value="0">Blocked</option>
                                </select>
                            </div>
                            <div><label class="lbl">Subscription</label>
                                <select name="is_subscribed" x-model="euser.is_subscribed" class="fld">
                                    <option value="1">Subscribed (Pro)</option>
                                    <option value="0">Not subscribed</option>
                                </select>
                            </div>
                        </div>
                    </div>

                    <!-- Photo -->
                    <div>
                        <p class="text-[11px] font-bold uppercase tracking-wide text-amber-600 mb-2 border-b pb-1"><i class="fas fa-image mr-1"></i>Profile Picture</p>
                        <div class="flex items-center gap-3">
                            <template x-if="euser.profile_pic">
                                <img :src="'../uploads/profiles/' + euser.profile_pic" class="w-14 h-14 rounded-xl object-cover border border-slate-200" alt="">
                            </template>
                            <input type="file" name="profile_pic" accept="image/*" class="filein flex-1">
                        </div>
                    </div>

                    <p class="text-[10px] text-slate-400">
                        <i class="fas fa-clock-rotate-left mr-1"></i>Every changed field is written to this user's Update History.
                    </p>
                </div>
            </div>

            <div class="flex justify-end gap-2 px-5 py-4 border-t bg-slate-50 flex-shrink-0">
                <button type="button" @click="close()" class="px-4 py-2 text-sm font-semibold text-slate-600 hover:bg-slate-200 rounded-lg">Cancel</button>
                <button type="submit" name="update_user" class="px-5 py-2 text-sm font-bold text-white bg-indigo-600 hover:bg-indigo-700 rounded-lg shadow"><i class="fas fa-save mr-1"></i>Save Changes</button>
            </div>
        </form>
    </div>

    <!-- ===== UPDATE FORM (full KYC editor) ===== -->
    <div x-show="modal==='updateForm'" x-transition class="relative w-full max-w-3xl bg-white rounded-2xl shadow-2xl overflow-hidden max-h-[90vh] flex flex-col">
        <div class="bg-gradient-to-r from-lime-600 to-emerald-600 px-5 py-4 flex items-center justify-between flex-shrink-0">
            <h3 class="text-white font-bold text-lg"><i class="fas fa-pen mr-2"></i>Update KYC — <span x-text="curUser.name"></span></h3>
            <button @click="close()" class="text-white/80 hover:text-white text-2xl leading-none">&times;</button>
        </div>
        <form method="POST" enctype="multipart/form-data" class="flex flex-col overflow-hidden">
            <input type="hidden" name="target_user_id" :value="curUser.id">
            <div class="p-5 overflow-y-auto space-y-5">
                <template x-if="loading"><p class="text-center text-slate-400 py-6"><i class="fas fa-spinner fa-spin mr-2"></i>Loading...</p></template>
                <div x-show="!loading" class="space-y-5">
                    <!-- Personal -->
                    <div>
                        <p class="text-[11px] font-bold uppercase tracking-wide text-amber-600 mb-2 border-b pb-1"><i class="fas fa-user mr-1"></i>Personal Details</p>
                        <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
                            <div><label class="lbl">Name</label><input name="full_name" x-model="form.full_name" class="fld"></div>
                            <div><label class="lbl">Gender</label><select name="gender" x-model="form.gender" class="fld"><option value="male">Male</option><option value="female">Female</option><option value="other">Other</option></select></div>
                            <div><label class="lbl">D.O.B</label><input type="date" name="dob" x-model="form.dob" class="fld"></div>
                            <div><label class="lbl">Father Name</label><input name="father_name" x-model="form.father_name" class="fld"></div>
                            <div><label class="lbl">Email</label><input name="email" x-model="form.email" class="fld"></div>
                            <div><label class="lbl">Aadhar Number</label><input name="aadhar_number" x-model="form.aadhar_number" class="fld"></div>
                            <div><label class="lbl">Pancard Number</label><input name="pancard_number" x-model="form.pancard_number" class="fld"></div>
                        </div>
                        <div class="grid grid-cols-2 md:grid-cols-4 gap-2 mt-2">
                            <div><label class="lbl">Aadhar Front</label><input type="file" name="aadhar_front" class="filein"></div>
                            <div><label class="lbl">Aadhar Back</label><input type="file" name="aadhar_back" class="filein"></div>
                            <div><label class="lbl">Pan Card</label><input type="file" name="pan_card" class="filein"></div>
                            <div><label class="lbl">Photo</label><input type="file" name="photo" class="filein"></div>
                        </div>
                    </div>
                    <!-- Address -->
                    <div>
                        <p class="text-[11px] font-bold uppercase tracking-wide text-blue-600 mb-2 border-b pb-1"><i class="fas fa-location-dot mr-1"></i>Address Details</p>
                        <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
                            <div><label class="lbl">Village / Locality</label><input name="village" x-model="form.village" class="fld"></div>
                            <div><label class="lbl">Post Office</label><input name="post_office" x-model="form.post_office" class="fld"></div>
                            <div><label class="lbl">Block / City / Municipality</label><input name="block_city" x-model="form.block_city" class="fld"></div>
                            <div><label class="lbl">Landmark</label><input name="landmark" x-model="form.landmark" class="fld"></div>
                            <div><label class="lbl">District</label><input name="district" x-model="form.district" class="fld"></div>
                            <div><label class="lbl">State</label><input name="state" x-model="form.state" class="fld"></div>
                            <div><label class="lbl">Pin Code</label><input name="pincode" x-model="form.pincode" class="fld"></div>
                            <div><label class="lbl">Address Proof</label><input type="file" name="address_proof" class="filein"></div>
                        </div>
                    </div>
                    <!-- Bank -->
                    <div>
                        <p class="text-[11px] font-bold uppercase tracking-wide text-rose-600 mb-2 border-b pb-1"><i class="fas fa-building-columns mr-1"></i>Bank Details</p>
                        <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
                            <div><label class="lbl">Bank Name</label><input name="bank_name" x-model="form.bank_name" class="fld"></div>
                            <div><label class="lbl">Branch Name</label><input name="branch_name" x-model="form.branch_name" class="fld"></div>
                            <div><label class="lbl">Account Number</label><input name="account_number" x-model="form.account_number" class="fld"></div>
                            <div><label class="lbl">IFSC Code</label><input name="ifsc_code" x-model="form.ifsc_code" class="fld"></div>
                            <div><label class="lbl">Bank Passbook</label><input type="file" name="bank_passbook" class="filein"></div>
                        </div>
                    </div>
                    <!-- Business -->
                    <div>
                        <p class="text-[11px] font-bold uppercase tracking-wide text-emerald-600 mb-2 border-b pb-1"><i class="fas fa-store mr-1"></i>Business Details</p>
                        <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
                            <div><label class="lbl">Business / Shop Name</label><input name="business_name" x-model="form.business_name" class="fld"></div>
                            <div><label class="lbl">Business Phone</label><input name="business_phone" x-model="form.business_phone" class="fld"></div>
                            <div><label class="lbl">Business Email</label><input name="business_email" x-model="form.business_email" class="fld"></div>
                            <div><label class="lbl">Village / Locality</label><input name="biz_village" x-model="form.biz_village" class="fld"></div>
                            <div><label class="lbl">Post Office</label><input name="biz_post_office" x-model="form.biz_post_office" class="fld"></div>
                            <div><label class="lbl">Block / City / Municipality</label><input name="biz_block_city" x-model="form.biz_block_city" class="fld"></div>
                            <div><label class="lbl">Landmark</label><input name="biz_landmark" x-model="form.biz_landmark" class="fld"></div>
                            <div><label class="lbl">District</label><input name="biz_district" x-model="form.biz_district" class="fld"></div>
                            <div><label class="lbl">State</label><input name="biz_state" x-model="form.biz_state" class="fld"></div>
                            <div><label class="lbl">Pin Code</label><input name="biz_pincode" x-model="form.biz_pincode" class="fld"></div>
                            <div><label class="lbl">Business Proof</label><input type="file" name="business_proof" class="filein"></div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="flex justify-end gap-2 px-5 py-4 border-t bg-slate-50 flex-shrink-0">
                <button type="button" @click="close()" class="px-4 py-2 text-sm font-semibold text-slate-600 hover:bg-slate-200 rounded-lg">Cancel</button>
                <button type="submit" name="admin_kyc_save" class="px-5 py-2 text-sm font-bold text-white bg-emerald-600 hover:bg-emerald-700 rounded-lg shadow">Save All Changes</button>
            </div>
        </form>
    </div>

    <!-- ===== RESET PASSWORD ===== -->
    <div x-show="modal==='reset'" x-transition class="relative w-full max-w-md bg-white rounded-2xl shadow-2xl overflow-hidden">
        <div class="bg-gradient-to-r from-rose-500 to-red-600 px-5 py-4 flex items-center justify-between">
            <h3 class="text-white font-bold text-lg"><i class="fas fa-key mr-2"></i>Reset Password</h3>
            <button @click="close()" class="text-white/80 hover:text-white text-xl"><i class="fas fa-times"></i></button>
        </div>
        <form method="POST" class="p-5 space-y-4">
            <input type="hidden" name="target_user_id" :value="curUser.id">
            <p class="text-xs text-slate-500">Set a new password for <span class="font-bold text-slate-700" x-text="curUser.name"></span>. This action is recorded in the update history.</p>
            <div>
                <label class="block text-xs font-semibold text-slate-600 mb-1">New Password <span class="text-rose-500">*</span></label>
                <input type="text" name="new_password" required minlength="4" class="w-full border border-slate-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-rose-400" placeholder="Enter new password">
            </div>
            <div class="flex justify-end gap-2 pt-1">
                <button type="button" @click="close()" class="px-4 py-2 text-sm font-semibold text-slate-600 hover:bg-slate-100 rounded-lg">Cancel</button>
                <button type="submit" name="reset_password" class="px-5 py-2 text-sm font-bold text-white bg-red-600 hover:bg-red-700 rounded-lg shadow">Submit</button>
            </div>
        </form>
    </div>

    <!-- ===== KYC REVIEW ===== -->
    <div x-show="modal==='kyc'" x-transition class="relative w-full max-w-3xl bg-white rounded-2xl shadow-2xl overflow-hidden">
        <div class="bg-gradient-to-r from-blue-600 to-indigo-600 px-5 py-4 flex items-center justify-between">
            <h3 class="text-white font-bold text-lg"><i class="fas fa-id-card mr-2"></i>KYC Verification</h3>
            <button @click="close()" class="text-white/80 hover:text-white text-xl"><i class="fas fa-times"></i></button>
        </div>
        <div class="px-5 py-2 bg-blue-50 text-blue-800 text-xs font-semibold border-b border-blue-100 flex items-center justify-between">
            <span><i class="fas fa-user mr-1"></i><span x-text="curUser.name"></span></span>
            <span class="uppercase px-2 py-0.5 rounded-full text-[10px]"
                  :class="kyc?.status==='approved' ? 'bg-emerald-100 text-emerald-700' : (kyc?.status==='rejected' ? 'bg-rose-100 text-rose-700' : 'bg-amber-100 text-amber-700')"
                  x-text="kyc?.status || '—'"></span>
        </div>
        <div class="p-5 max-h-[70vh] overflow-y-auto">
            <template x-if="loading"><p class="text-center text-slate-400 py-6"><i class="fas fa-spinner fa-spin mr-2"></i>Loading...</p></template>
            <template x-if="!loading && !kyc"><p class="text-center text-slate-400 py-8">No KYC submitted by this user.</p></template>
            <div x-show="!loading && kyc" class="space-y-5 text-sm">
                <!-- Personal -->
                <div>
                    <p class="text-[11px] font-bold uppercase tracking-wide text-amber-600 mb-2 border-b pb-1"><i class="fas fa-user mr-1"></i>Personal Details</p>
                    <div class="grid grid-cols-2 md:grid-cols-3 gap-x-4 gap-y-1.5">
                        <p><span class="text-slate-400">Name:</span> <b x-text="kyc?.full_name || '—'"></b></p>
                        <p><span class="text-slate-400">Gender:</span> <b x-text="kyc?.gender || '—'"></b></p>
                        <p><span class="text-slate-400">DOB:</span> <b x-text="kyc?.dob || '—'"></b></p>
                        <p><span class="text-slate-400">Father:</span> <b x-text="kyc?.father_name || '—'"></b></p>
                        <p><span class="text-slate-400">Email:</span> <b x-text="kyc?.email || '—'"></b></p>
                        <p><span class="text-slate-400">Aadhar:</span> <b x-text="kyc?.aadhar_number || '—'"></b></p>
                        <p><span class="text-slate-400">PAN:</span> <b x-text="kyc?.pancard_number || '—'"></b></p>
                    </div>
                    <div class="flex flex-wrap gap-2 mt-2">
                        <template x-for="f in [['aadhar_front','Aadhar Front'],['aadhar_back','Aadhar Back'],['pan_card','PAN Card'],['photo','Photo']]" :key="f[0]">
                            <span x-show="kyc?.[f[0]]" class="inline-flex items-center gap-1.5 bg-slate-100 rounded-lg px-2 py-1 text-[11px]">
                                <span class="font-semibold text-slate-600" x-text="f[1]"></span>
                                <a :href="'../uploads/kyc/'+kyc?.[f[0]]" target="_blank" class="text-blue-600 hover:text-blue-800 font-bold"><i class="fas fa-eye"></i> View</a>
                                <a :href="'../uploads/kyc/'+kyc?.[f[0]]" :download="kyc?.[f[0]]" class="text-emerald-600 hover:text-emerald-800 font-bold"><i class="fas fa-download"></i> Download</a>
                            </span>
                        </template>
                    </div>
                </div>
                <!-- Address -->
                <div>
                    <p class="text-[11px] font-bold uppercase tracking-wide text-blue-600 mb-2 border-b pb-1"><i class="fas fa-location-dot mr-1"></i>Address Details</p>
                    <div class="grid grid-cols-2 md:grid-cols-3 gap-x-4 gap-y-1.5">
                        <p><span class="text-slate-400">Village:</span> <b x-text="kyc?.village || '—'"></b></p>
                        <p><span class="text-slate-400">Post Office:</span> <b x-text="kyc?.post_office || '—'"></b></p>
                        <p><span class="text-slate-400">Block/City:</span> <b x-text="kyc?.block_city || '—'"></b></p>
                        <p><span class="text-slate-400">Landmark:</span> <b x-text="kyc?.landmark || '—'"></b></p>
                        <p><span class="text-slate-400">District:</span> <b x-text="kyc?.district || '—'"></b></p>
                        <p><span class="text-slate-400">State:</span> <b x-text="kyc?.state || '—'"></b></p>
                        <p><span class="text-slate-400">Pincode:</span> <b x-text="kyc?.pincode || '—'"></b></p>
                    </div>
                    <span x-show="kyc?.address_proof" class="inline-flex items-center gap-1.5 bg-slate-100 rounded-lg px-2 py-1 text-[11px] mt-2">
                        <span class="font-semibold text-slate-600">Address Proof</span>
                        <a :href="'../uploads/kyc/'+kyc?.address_proof" target="_blank" class="text-blue-600 hover:text-blue-800 font-bold"><i class="fas fa-eye"></i> View</a>
                        <a :href="'../uploads/kyc/'+kyc?.address_proof" :download="kyc?.address_proof" class="text-emerald-600 hover:text-emerald-800 font-bold"><i class="fas fa-download"></i> Download</a>
                    </span>
                </div>
                <!-- Bank -->
                <div>
                    <p class="text-[11px] font-bold uppercase tracking-wide text-rose-600 mb-2 border-b pb-1"><i class="fas fa-building-columns mr-1"></i>Bank Details</p>
                    <div class="grid grid-cols-2 md:grid-cols-3 gap-x-4 gap-y-1.5">
                        <p><span class="text-slate-400">Bank:</span> <b x-text="kyc?.bank_name || '—'"></b></p>
                        <p><span class="text-slate-400">Branch:</span> <b x-text="kyc?.branch_name || '—'"></b></p>
                        <p><span class="text-slate-400">Account:</span> <b x-text="kyc?.account_number || '—'"></b></p>
                        <p><span class="text-slate-400">IFSC:</span> <b x-text="kyc?.ifsc_code || '—'"></b></p>
                    </div>
                    <span x-show="kyc?.bank_passbook" class="inline-flex items-center gap-1.5 bg-slate-100 rounded-lg px-2 py-1 text-[11px] mt-2">
                        <span class="font-semibold text-slate-600">Passbook</span>
                        <a :href="'../uploads/kyc/'+kyc?.bank_passbook" target="_blank" class="text-blue-600 hover:text-blue-800 font-bold"><i class="fas fa-eye"></i> View</a>
                        <a :href="'../uploads/kyc/'+kyc?.bank_passbook" :download="kyc?.bank_passbook" class="text-emerald-600 hover:text-emerald-800 font-bold"><i class="fas fa-download"></i> Download</a>
                    </span>
                </div>
                <!-- Business -->
                <div>
                    <p class="text-[11px] font-bold uppercase tracking-wide text-emerald-600 mb-2 border-b pb-1"><i class="fas fa-store mr-1"></i>Business Details</p>
                    <div class="grid grid-cols-2 md:grid-cols-3 gap-x-4 gap-y-1.5">
                        <p><span class="text-slate-400">Business:</span> <b x-text="kyc?.business_name || '—'"></b></p>
                        <p><span class="text-slate-400">Phone:</span> <b x-text="kyc?.business_phone || '—'"></b></p>
                        <p><span class="text-slate-400">Email:</span> <b x-text="kyc?.business_email || '—'"></b></p>
                        <p><span class="text-slate-400">Village:</span> <b x-text="kyc?.biz_village || '—'"></b></p>
                        <p><span class="text-slate-400">Post Office:</span> <b x-text="kyc?.biz_post_office || '—'"></b></p>
                        <p><span class="text-slate-400">Block/City:</span> <b x-text="kyc?.biz_block_city || '—'"></b></p>
                        <p><span class="text-slate-400">Landmark:</span> <b x-text="kyc?.biz_landmark || '—'"></b></p>
                        <p><span class="text-slate-400">District:</span> <b x-text="kyc?.biz_district || '—'"></b></p>
                        <p><span class="text-slate-400">State:</span> <b x-text="kyc?.biz_state || '—'"></b></p>
                        <p><span class="text-slate-400">Pincode:</span> <b x-text="kyc?.biz_pincode || '—'"></b></p>
                    </div>
                    <span x-show="kyc?.business_proof" class="inline-flex items-center gap-1.5 bg-slate-100 rounded-lg px-2 py-1 text-[11px] mt-2">
                        <span class="font-semibold text-slate-600">Business Proof</span>
                        <a :href="'../uploads/kyc/'+kyc?.business_proof" target="_blank" class="text-blue-600 hover:text-blue-800 font-bold"><i class="fas fa-eye"></i> View</a>
                        <a :href="'../uploads/kyc/'+kyc?.business_proof" :download="kyc?.business_proof" class="text-emerald-600 hover:text-emerald-800 font-bold"><i class="fas fa-download"></i> Download</a>
                    </span>
                </div>
                <!-- Approve / Reject -->
                <form method="POST" class="border-t pt-4 mt-2">
                    <input type="hidden" name="target_user_id" :value="curUser.id">
                    <label class="block text-xs font-semibold text-slate-600 mb-1">Remark (optional, shown to user if rejected)</label>
                    <textarea name="kyc_remark" rows="2" class="w-full border border-slate-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400" x-text="kyc?.admin_remark || ''"></textarea>
                    <div class="flex justify-end gap-2 mt-3">
                        <button type="submit" name="kyc_action" value="rejected" class="px-5 py-2 text-sm font-bold text-white bg-rose-600 hover:bg-rose-700 rounded-lg shadow"><i class="fas fa-times mr-1"></i>Reject</button>
                        <button type="submit" name="kyc_action" value="approved" class="px-5 py-2 text-sm font-bold text-white bg-emerald-600 hover:bg-emerald-700 rounded-lg shadow"><i class="fas fa-check mr-1"></i>Approve</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>
</template>

<script>
function userListApp() {
    return {
        sidebarOpen: window.innerWidth >= 768,
        modal: null,
        curUser: { id: null, name: '' },
        notes: [], history: [], viewNote: null,
        form: {}, kyc: null, loading: false,
        euser: {},                                   // "Edit User Details" form model

        /* ---------- bulk selection ---------- */
        sel: [],                                     // ids ticked on this page
        pageIds: <?php echo json_encode($ul_page_ids); ?>,
        isSel(id)    { return this.sel.indexOf(id) > -1; },
        toggleOne(id) {
            const i = this.sel.indexOf(id);
            if (i > -1) this.sel.splice(i, 1); else this.sel.push(id);
        },
        allOnPage()  { return this.pageIds.length > 0 && this.pageIds.every(id => this.sel.includes(id)); },
        toggleAll(on) {
            if (on) { this.pageIds.forEach(id => { if (!this.sel.includes(id)) this.sel.push(id); }); }
            else    { this.sel = this.sel.filter(id => !this.pageIds.includes(id)); }
        },

        money: { id: null, name: '', main: 0, virtual: 0, action: 'credit', wallet: 'main', amount: null, reason: '' },
        reasonsCredit: ['Manual top-up','Refund for a failed order','Promotional bonus','Correction of a wrong debit','Support compensation'],
        reasonsDebit:  ['Wrong credit reversal','Order cancelled','Penalty / policy violation','Duplicate transaction','Manual adjustment'],
        openMoney(id, name, main, virtual) {
            this.money = { id, name, main: Number(main) || 0, virtual: Number(virtual) || 0,
                           action: 'credit', wallet: 'main', amount: null, reason: '' };
            this.modal = 'money';
        },
        moneyMax() { return this.money.wallet === 'virtual' ? this.money.virtual : this.money.main; },
        moneyErr() {
            const a = Number(this.money.amount) || 0;
            if (!this.money.amount) return '';
            if (a <= 0) return 'Enter an amount above zero';
            if (this.money.action === 'debit' && a > this.moneyMax()) return 'That wallet only holds ₹' + this.moneyMax().toFixed(2);
            return '';
        },
        moneyAfter() {
            const a = Number(this.money.amount) || 0;
            const cur = this.moneyMax();
            return this.money.action === 'credit' ? cur + a : Math.max(0, cur - a);
        },
        moneyOk() { return this.money.amount > 0 && !this.moneyErr() && this.money.reason.trim() !== ''; },
        openNotesHistory(id, name) { this.curUser = { id, name }; this.viewNote = null; this.notes = []; this.modal = 'notesHistory'; this.fetchJSON('notes', id, d => this.notes = d); },
        openNewNote(id, name)      { this.curUser = { id, name }; this.modal = 'newNote'; },
        openUpdateHistory(id, name){ this.curUser = { id, name }; this.history = []; this.modal = 'updateHistory'; this.fetchJSON('history', id, d => this.history = d); },
        openUpdateForm(id, name)   { this.curUser = { id, name }; this.form = {}; this.modal = 'updateForm'; this.fetchJSON('adminkyc', id, d => this.form = d || {}); },
        openEditUser(id, name)     { this.curUser = { id, name }; this.euser = {}; this.modal = 'editUser'; this.fetchJSON('user', id, d => this.euser = d || {}); },
        openReset(id, name)        { this.curUser = { id, name }; this.modal = 'reset'; },

        /* ---------- add a brand new user ---------- */
        newu: { user_type: 'customer', gender: 'male', status: '1', is_subscribed: '0',
                password: '', password_confirm: '' },
        showPass: false,
        openAddUser() {
            this.newu = { user_type: 'customer', gender: 'male', status: '1', is_subscribed: '0',
                          password: '', password_confirm: '' };
            this.showPass = false;
            this.modal = 'addUser';
        },
        passErr() {
            if (this.newu.password === '' && this.newu.password_confirm === '') return '';
            if (this.newu.password.length < 6) return 'At least 6 characters';
            if (this.newu.password_confirm !== '' && this.newu.password !== this.newu.password_confirm) return 'The two passwords do not match';
            return '';
        },
        addOk() { return this.newu.password.length >= 6 && this.newu.password === this.newu.password_confirm; },
        genPass() {
            const a = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789@#';
            let o = '';
            for (let i = 0; i < 10; i++) { o += a.charAt(Math.floor(Math.random() * a.length)); }
            this.newu.password = o; this.newu.password_confirm = o; this.showPass = true;
        },
        openKyc(id, name)          { this.curUser = { id, name }; this.kyc = null; this.modal = 'kyc'; this.fetchJSON('kyc', id, d => this.kyc = d); },
        close() { this.modal = null; this.viewNote = null; },
        async fetchJSON(kind, id, cb) {
            this.loading = true;
            try { const r = await fetch('<?php echo esc($UL_PAGE); ?>?ajax=' + kind + '&uid=' + id); cb(await r.json()); }
            catch (e) { cb([]); }
            this.loading = false;
        },
        fmtDate(s) {
            if (!s) return '';
            const d = new Date(s.replace(' ', 'T'));
            if (isNaN(d)) return s;
            return d.toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) + ', ' + d.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
        }
    }
}

/* ---------------------------------------------------------------------------
   Keep the slim scroll bar above the table in sync with the table itself, so
   the columns can be slid from the top of the list as well as the bottom.
   --------------------------------------------------------------------------- */
(function () {
    function initTopScroll() {
        var top   = document.getElementById('ulTopScroll');
        var inner = document.getElementById('ulTopScrollInner');
        var body  = document.getElementById('ulScroll');
        var table = document.getElementById('ulTable');
        if (!top || !inner || !body || !table) return;

        function sizeIt() {
            inner.style.width = table.scrollWidth + 'px';
            /* nothing to scroll → hide the bar entirely */
            top.style.display = (table.scrollWidth > body.clientWidth + 2) ? '' : 'none';
        }

        var lock = false;
        top.addEventListener('scroll', function () {
            if (lock) { lock = false; return; }
            lock = true; body.scrollLeft = top.scrollLeft;
        });
        body.addEventListener('scroll', function () {
            if (lock) { lock = false; return; }
            lock = true; top.scrollLeft = body.scrollLeft;
        });

        sizeIt();
        window.addEventListener('resize', sizeIt);
        if (window.ResizeObserver) { new ResizeObserver(sizeIt).observe(table); }
        setTimeout(sizeIt, 400);   // after web fonts / images settle
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initTopScroll);
    } else {
        initTopScroll();
    }
})();
</script>
</body>
</html>
