<?php
/**
 * modules/manage_user.php
 * Manage User + Tambah User Baru + Matrix Hak Akses
 * Kompatibel untuk include dari index.php?module=manage_user
 */
error_reporting(E_ALL);
ini_set('display_errors', '1');

if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

try {
    if (!isset($conn) || !($conn instanceof mysqli)) {
        $dbPath = __DIR__ . '/../config/database.php';
        $appPath = __DIR__ . '/../config/app.php';
        if (file_exists($dbPath)) require_once $dbPath;
        if (file_exists($appPath)) require_once $appPath;
        if (function_exists('getConnection')) $conn = getConnection();
    }

    if (!isset($conn) || !($conn instanceof mysqli)) {
        echo '<div class="p-6 rounded-2xl bg-red-50 border border-red-200 text-red-700 font-bold">Koneksi database tidak ditemukan.</div>';
        return;
    }

    if (function_exists('checkAuth')) checkAuth();

    if (!function_exists('e')) {
        function e($value) { return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); }
    }
    if (!function_exists('mu_table_exists')) {
        function mu_table_exists(mysqli $conn, string $table): bool {
            $table = $conn->real_escape_string($table);
            $res = $conn->query("SHOW TABLES LIKE '{$table}'");
            return $res && $res->num_rows > 0;
        }
    }
    if (!function_exists('mu_col_exists')) {
        function mu_col_exists(mysqli $conn, string $table, string $column): bool {
            $table = $conn->real_escape_string($table);
            $column = $conn->real_escape_string($column);
            $res = $conn->query("SHOW COLUMNS FROM `{$table}` LIKE '{$column}'");
            return $res && $res->num_rows > 0;
        }
    }
    if (!function_exists('mu_exec_safe')) {
        function mu_exec_safe(mysqli $conn, string $sql) {
            try { return $conn->query($sql); } catch (Throwable $e) { return false; }
        }
    }
    if (!function_exists('mu_rows_safe')) {
        function mu_rows_safe(mysqli $conn, string $sql, array $params = [], string $types = ''): array {
            $stmt = $conn->prepare($sql);
            if (!$stmt) return [];
            if ($params) $stmt->bind_param($types, ...$params);
            if (!$stmt->execute()) { $stmt->close(); return []; }
            $res = $stmt->get_result();
            $rows = [];
            if ($res) while ($row = $res->fetch_assoc()) $rows[] = $row;
            $stmt->close();
            return $rows;
        }
    }
    if (!function_exists('mu_scalar_safe')) {
        function mu_scalar_safe(mysqli $conn, string $sql): int {
            $res = mu_exec_safe($conn, $sql);
            if (!$res) return 0;
            $row = $res->fetch_row();
            return $row ? (int)$row[0] : 0;
        }
    }
    if (!function_exists('mu_redirect_safe')) {
        function mu_redirect_safe(string $extra = ''): void {
            echo '<script>window.location.href="index.php?module=manage_user' . $extra . '";</script>';
            exit;
        }
    }
    if (!function_exists('mu_set_flash')) {
        function mu_set_flash(string $type, string $message): void {
            $_SESSION[$type === 'error' ? 'mu_error' : 'mu_success'] = $message;
        }
    }
    if (!function_exists('mu_insert_dynamic')) {
        function mu_insert_dynamic(mysqli $conn, string $table, array $data): int {
            $cols = [];
            $vals = [];
            $types = '';
            $params = [];
            foreach ($data as $col => $val) {
                if (!mu_col_exists($conn, $table, $col)) continue;
                $cols[] = "`{$col}`";
                $vals[] = '?';
                if (is_int($val)) $types .= 'i';
                elseif (is_float($val)) $types .= 'd';
                else $types .= 's';
                $params[] = $val;
            }
            if (!$cols) return 0;
            $sql = "INSERT INTO `{$table}` (" . implode(',', $cols) . ") VALUES (" . implode(',', $vals) . ")";
            $stmt = $conn->prepare($sql);
            if (!$stmt) return 0;
            $stmt->bind_param($types, ...$params);
            $ok = $stmt->execute();
            $id = $ok ? (int)$conn->insert_id : 0;
            $stmt->close();
            return $id;
        }
    }
    if (!function_exists('mu_update_dynamic')) {
        function mu_update_dynamic(mysqli $conn, string $table, array $data, string $where, array $paramsWhere, string $typesWhere): bool {
            $sets = [];
            $types = '';
            $params = [];
            foreach ($data as $col => $val) {
                if (!mu_col_exists($conn, $table, $col)) continue;
                $sets[] = "`{$col}`=?";
                if (is_int($val)) $types .= 'i';
                elseif (is_float($val)) $types .= 'd';
                else $types .= 's';
                $params[] = $val;
            }
            if (!$sets) return false;
            $sql = "UPDATE `{$table}` SET " . implode(',', $sets) . " WHERE {$where}";
            $stmt = $conn->prepare($sql);
            if (!$stmt) return false;
            $allTypes = $types . $typesWhere;
            $allParams = array_merge($params, $paramsWhere);
            $stmt->bind_param($allTypes, ...$allParams);
            $ok = $stmt->execute();
            $stmt->close();
            return $ok;
        }
    }
    if (!function_exists('mu_seed_role_menu_schema')) {
        function mu_seed_role_menu_schema(mysqli $conn): void {
            mu_exec_safe($conn, "CREATE TABLE IF NOT EXISTS app_roles (
                id INT AUTO_INCREMENT PRIMARY KEY,
                role_name VARCHAR(50) NOT NULL UNIQUE,
                role_label VARCHAR(100) NOT NULL,
                sort_order INT NOT NULL DEFAULT 0,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
            mu_exec_safe($conn, "CREATE TABLE IF NOT EXISTS app_menu_modules (
                id INT AUTO_INCREMENT PRIMARY KEY,
                module_key VARCHAR(120) NOT NULL UNIQUE,
                module_name VARCHAR(180) NOT NULL,
                module_group VARCHAR(100) NOT NULL DEFAULT 'Umum',
                route_path VARCHAR(255) NOT NULL,
                icon VARCHAR(80) NOT NULL DEFAULT 'fas fa-cube',
                sort_order INT NOT NULL DEFAULT 0,
                is_active TINYINT(1) NOT NULL DEFAULT 1,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
            mu_exec_safe($conn, "CREATE TABLE IF NOT EXISTS app_role_menu_permissions (
                id INT AUTO_INCREMENT PRIMARY KEY,
                role_name VARCHAR(50) NOT NULL,
                module_key VARCHAR(120) NOT NULL,
                can_view TINYINT(1) NOT NULL DEFAULT 0,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                UNIQUE KEY uniq_role_module(role_name, module_key),
                INDEX idx_role(role_name),
                INDEX idx_module(module_key)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
            if (mu_table_exists($conn, 'users') && mu_col_exists($conn, 'users', 'role')) {
                mu_exec_safe($conn, "ALTER TABLE users MODIFY role VARCHAR(50) NOT NULL DEFAULT 'viewer'");
            }
            $roles = [
                ['superadmin','Superadmin',1], ['admin','Admin',2], ['editor','Editor',3], ['user','User',4], ['viewer','Viewer',5],
            ];
            $stmt = $conn->prepare("INSERT INTO app_roles(role_name,role_label,sort_order) VALUES(?,?,?) ON DUPLICATE KEY UPDATE role_label=VALUES(role_label), sort_order=VALUES(sort_order)");
            if ($stmt) {
                foreach ($roles as $r) { $stmt->bind_param('ssi', $r[0], $r[1], $r[2]); $stmt->execute(); }
                $stmt->close();
            }
            $modules = [
                ['dashboard','Dashboard','Utama','index.php?module=dashboard','fas fa-home',1],
                ['manage_user','Manage User','Admin','index.php?module=manage_user','fas fa-users-cog',2],
                ['user_profile','Profil Saya','User','index.php?module=user_profile','fas fa-user-circle',3],
                ['data_perawat','Data Perawat','SDM','index.php?module=data_perawat','fas fa-user-nurse',4],
                ['data_perawat_per_unit','Data Perawat per Unit','SDM','index.php?module=data_perawat_per_unit','fas fa-hospital-user',5],
                ['data_staf_baru','Data Staf Baru','SDM','index.php?module=data_staf_baru','fas fa-user-plus',6],
                ['jadwal_orientasi_staf_baru','Jadwal Orientasi Staf Baru','SDM','index.php?module=jadwal_orientasi_staf_baru','fas fa-calendar-alt',7],
                ['rotasi_perawat','Rotasi / Resign','SDM','index.php?module=rotasi_perawat','fas fa-retweet',8],
                ['beban_kerja','Analisis Beban Kerja','Analisis','index.php?module=beban_kerja','fas fa-chart-line',9],
                ['analisis_kunjungan','Analisis Kunjungan','Analisis','index.php?module=analisis_kunjungan','fas fa-chart-bar',10],
                ['laporan_bulanan','Laporan Bulanan','Laporan','index.php?module=laporan_bulanan','fas fa-file-alt',11],
                ['kegiatan_harian','Kegiatan Harian','Laporan','index.php?module=kegiatan_harian','fas fa-clipboard-check',12],
                ['laporan_katim','Laporan Katim','Laporan','index.php?module=laporan_katim','fas fa-clipboard-list',13],
                ['laporan_mod','Laporan MOD','Laporan','index.php?module=laporan_mod','fas fa-user-md',14],
                ['laporan_harian_poliklinik','Laporan Harian Poliklinik','Laporan','index.php?module=laporan_harian_poliklinik','fas fa-stethoscope',15],
                ['patient_safety','Patient Safety','Mutu','index.php?module=patient_safety','fas fa-shield-alt',16],
                ['laporan_rka','Laporan RKA','Laporan','index.php?module=laporan_rka','fas fa-tasks',17],
                ['permasalahan_tindak_lanjut','Permasalahan & Tindak Lanjut','Laporan','index.php?module=permasalahan_tindak_lanjut','fas fa-exclamation-triangle',18],
                ['daftar_spo','Daftar SPO','Utilities','index.php?module=daftar_spo','fas fa-file-medical-alt',19],
                ['google_drive_reader','Google Drive Reader','Utilities','index.php?module=google_drive_reader','fas fa-folder-open',20],
                ['generator_surat','Generator Surat','Utilities','index.php?module=generator_surat','fas fa-file-signature',21],
                ['distribusi_alat','Distribusi Alat','Utilities','index.php?module=distribusi_alat','fas fa-truck',22],
                ['peminjaman_alat','Peminjaman Alat','Utilities','index.php?module=peminjaman_alat','fas fa-handshake-angle',23],
                ['p3k','Penugasan P3K','Utilities','index.php?module=p3k','fas fa-first-aid',24],
                ['activity_log','Aktivitas Log','Admin','index.php?module=activity_log','fas fa-history',25],
                ['struktur_organisasi','Struktur Organisasi','Admin','index.php?module=struktur_organisasi','fas fa-sitemap',26],
                ['rdk','Refleksi Diskusi Kasus','Keperawatan','index.php?module=rdk','fas fa-comments',27],
                ['coaching','Coaching Staf Baru','Keperawatan','index.php?module=coaching','fas fa-user-graduate',28],
                ['logbook_kpi','Logbook & KPI Keperawatan','Keperawatan','index.php?module=logbook_kpi','fas fa-book-medical',29],
                ['kisi_kisi_pfp','Kisi-Kisi Telusur Akreditasi PFP','Akreditasi','index.php?module=kisi_kisi_pfp','fas fa-clipboard-question',30],
            ];
            $stmtM = $conn->prepare("INSERT INTO app_menu_modules(module_key,module_name,module_group,route_path,icon,sort_order,is_active) VALUES(?,?,?,?,?,?,1) ON DUPLICATE KEY UPDATE module_name=VALUES(module_name), module_group=VALUES(module_group), route_path=VALUES(route_path), icon=VALUES(icon), sort_order=VALUES(sort_order), is_active=1");
            if ($stmtM) {
                foreach ($modules as $m) { $stmtM->bind_param('sssssi', $m[0], $m[1], $m[2], $m[3], $m[4], $m[5]); $stmtM->execute(); }
                $stmtM->close();
            }
            mu_exec_safe($conn, "INSERT IGNORE INTO app_role_menu_permissions(role_name,module_key,can_view) SELECT 'superadmin', module_key, 1 FROM app_menu_modules");
            mu_exec_safe($conn, "INSERT IGNORE INTO app_role_menu_permissions(role_name,module_key,can_view) SELECT 'admin', module_key, 1 FROM app_menu_modules");
            mu_exec_safe($conn, "INSERT IGNORE INTO app_role_menu_permissions(role_name,module_key,can_view) SELECT 'editor', module_key, IF(module_key IN ('manage_user'),0,1) FROM app_menu_modules");
            mu_exec_safe($conn, "INSERT IGNORE INTO app_role_menu_permissions(role_name,module_key,can_view) SELECT 'user', module_key, IF(module_key IN ('dashboard','user_profile','laporan_katim','laporan_mod','kegiatan_harian','daftar_spo','google_drive_reader','rdk','coaching','logbook_kpi','kisi_kisi_pfp'),1,0) FROM app_menu_modules");
            mu_exec_safe($conn, "INSERT IGNORE INTO app_role_menu_permissions(role_name,module_key,can_view) SELECT 'viewer', module_key, IF(module_key IN ('dashboard','user_profile','daftar_spo','google_drive_reader','struktur_organisasi'),1,0) FROM app_menu_modules");
        }
    }
    if (!function_exists('mu_get_roles')) {
        function mu_get_roles(mysqli $conn): array {
            $rows = mu_rows_safe($conn, "SELECT role_name, role_label FROM app_roles ORDER BY sort_order ASC, role_label ASC");
            $out = [];
            foreach ($rows as $r) $out[$r['role_name']] = $r['role_label'];
            return $out ?: ['viewer'=>'Viewer','user'=>'User','editor'=>'Editor','admin'=>'Admin','superadmin'=>'Superadmin'];
        }
    }
    if (!function_exists('mu_get_modules')) {
        function mu_get_modules(mysqli $conn): array { return mu_rows_safe($conn, "SELECT * FROM app_menu_modules WHERE is_active=1 ORDER BY sort_order ASC, module_name ASC"); }
    }
    if (!function_exists('mu_get_matrix')) {
        function mu_get_matrix(mysqli $conn): array {
            $rows = mu_rows_safe($conn, "SELECT role_name, module_key, can_view FROM app_role_menu_permissions");
            $matrix = [];
            foreach ($rows as $r) $matrix[$r['role_name']][$r['module_key']] = (int)$r['can_view'];
            return $matrix;
        }
    }
    if (!function_exists('mu_visible_module_names')) {
        function mu_visible_module_names(mysqli $conn, string $role): array {
            return mu_rows_safe($conn, "SELECT m.module_name FROM app_menu_modules m INNER JOIN app_role_menu_permissions p ON p.module_key=m.module_key WHERE m.is_active=1 AND p.role_name=? AND p.can_view=1 ORDER BY m.sort_order ASC", [$role], 's');
        }
    }
    if (!function_exists('mu_create_or_update_user_safe')) {
        function mu_create_or_update_user_safe(mysqli $conn, int $employeeId, string $role, int $isActive): bool {
            $idCol = mu_col_exists($conn, 'employees', 'id') ? 'id' : 'employee_id';
            $empCodeExpr = mu_col_exists($conn, 'employees', 'employee_code') ? 'employee_code' : (mu_col_exists($conn, 'employees', 'nik') ? 'nik' : $idCol);
            $rows = mu_rows_safe($conn, "SELECT {$idCol} AS employee_id, {$empCodeExpr} AS login_code FROM employees WHERE {$idCol}=? LIMIT 1", [$employeeId], 'i');
            if (!$rows) return false;
            $username = trim((string)$rows[0]['login_code']);
            if ($username === '') $username = 'emp' . $employeeId;
            $exists = mu_rows_safe($conn, "SELECT id FROM users WHERE employee_id=? LIMIT 1", [$employeeId], 'i');
            if ($exists) {
                $data = ['role'=>$role, 'is_active'=>$isActive, 'updated_at'=>date('Y-m-d H:i:s')];
                return mu_update_dynamic($conn, 'users', $data, 'employee_id=?', [$employeeId], 'i');
            }
            $hash = password_hash('balimed1', PASSWORD_DEFAULT);
            $data = [
                'employee_id'=>$employeeId,
                'username'=>$username,
                'password_hash'=>$hash,
                'password'=>$hash,
                'role'=>$role,
                'is_active'=>$isActive,
                'access_scope'=>'full',
                'must_change_password'=>1,
                'created_at'=>date('Y-m-d H:i:s'),
                'updated_at'=>date('Y-m-d H:i:s'),
            ];
            return mu_insert_dynamic($conn, 'users', $data) > 0;
        }
    }

    mu_seed_role_menu_schema($conn);

    $roles = mu_get_roles($conn);
    $modules = mu_get_modules($conn);
    $matrix = mu_get_matrix($conn);

    $success = $_SESSION['mu_success'] ?? '';
    $error = $_SESSION['mu_error'] ?? '';
    unset($_SESSION['mu_success'], $_SESSION['mu_error']);

    $unitRows = [];
    if (mu_table_exists($conn, 'units')) {
        $unitRows = mu_rows_safe($conn, "SELECT id, name FROM units WHERE COALESCE(is_active,1)=1 ORDER BY name ASC");
    }

    $positions = ['Perawat Pelaksana','Bidan','Kepala Unit','Katim/PJ Shift','Kasubdiv Keperawatan Rawat Jalan','Kasubdiv Keperawatan Rawat Inap','Kepala Divisi Keperawatan'];
    $professions = ['perawat'=>'Perawat','bidan'=>'Bidan','non medis'=>'Non Medis'];

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $action = $_POST['action'] ?? '';

        if ($action === 'create_new_user_employee') {
            $fullName = trim((string)($_POST['full_name'] ?? ''));
            $nik = trim((string)($_POST['nik'] ?? ''));
            $employeeCode = trim((string)($_POST['employee_code'] ?? ''));
            $email = trim((string)($_POST['email'] ?? ''));
            $phone = trim((string)($_POST['phone'] ?? ''));
            $unitId = (int)($_POST['unit_id'] ?? 0);
            $position = trim((string)($_POST['position_name'] ?? ''));
            $profession = trim((string)($_POST['profession'] ?? 'perawat'));
            $joinDate = trim((string)($_POST['join_date'] ?? ''));
            $role = trim((string)($_POST['role'] ?? 'viewer'));
            $isActive = isset($_POST['is_active']) ? 1 : 0;
            $passwordPlain = trim((string)($_POST['password'] ?? 'balimed1'));
            if ($passwordPlain === '') $passwordPlain = 'balimed1';

            if ($fullName === '' || ($nik === '' && $employeeCode === '')) {
                mu_set_flash('error', 'Nama lengkap wajib diisi, dan minimal NIK/ID karyawan harus diisi.');
                mu_redirect_safe('&show_add=1');
            }
            if (!isset($roles[$role])) $role = 'viewer';
            if ($employeeCode === '') $employeeCode = $nik;
            if ($nik === '') $nik = $employeeCode;
            $loginCode = $nik !== '' ? $nik : $employeeCode;

            $dupSql = "SELECT id FROM employees WHERE ";
            $dupParams = [];
            $dupTypes = '';
            $dupWhere = [];
            if (mu_col_exists($conn, 'employees', 'nik') && $nik !== '') { $dupWhere[] = 'nik=?'; $dupParams[] = $nik; $dupTypes .= 's'; }
            if (mu_col_exists($conn, 'employees', 'employee_code') && $employeeCode !== '') { $dupWhere[] = 'employee_code=?'; $dupParams[] = $employeeCode; $dupTypes .= 's'; }
            if ($dupWhere) {
                $dups = mu_rows_safe($conn, $dupSql . implode(' OR ', $dupWhere) . ' LIMIT 1', $dupParams, $dupTypes);
                if ($dups) {
                    mu_set_flash('error', 'NIK/ID karyawan sudah terdaftar. Silakan cek kembali data user.');
                    mu_redirect_safe('&show_add=1');
                }
            }
            if (mu_table_exists($conn, 'users')) {
                $userDups = mu_rows_safe($conn, "SELECT id FROM users WHERE username=? LIMIT 1", [$loginCode], 's');
                if ($userDups) {
                    mu_set_flash('error', 'Username/NIK sudah dipakai user lain.');
                    mu_redirect_safe('&show_add=1');
                }
            }

            $conn->begin_transaction();
            try {
                $empData = [
                    'full_name'=>$fullName,
                    'name'=>$fullName,
                    'employee_code'=>$employeeCode,
                    'nik'=>$nik,
                    'email'=>$email,
                    'phone'=>$phone,
                    'unit_id'=>$unitId > 0 ? $unitId : null,
                    'position_name'=>$position,
                    'position'=>$position,
                    'profession'=>$profession,
                    'employment_status'=>'aktif',
                    'join_date'=>($joinDate !== '' ? $joinDate : null),
                    'is_active'=>1,
                    'created_at'=>date('Y-m-d H:i:s'),
                    'updated_at'=>date('Y-m-d H:i:s'),
                ];
                // Null integers should be handled by a direct custom insert, not dynamic type nullable.
                if (isset($empData['unit_id']) && $empData['unit_id'] === null) unset($empData['unit_id']);
                if (isset($empData['join_date']) && $empData['join_date'] === null) unset($empData['join_date']);
                $employeeId = mu_insert_dynamic($conn, 'employees', $empData);
                if ($employeeId <= 0) throw new Exception('Gagal menyimpan data karyawan/perawat. Cek struktur tabel employees.');

                $hash = password_hash($passwordPlain, PASSWORD_DEFAULT);
                $userData = [
                    'employee_id'=>$employeeId,
                    'username'=>$loginCode,
                    'password_hash'=>$hash,
                    'password'=>$hash,
                    'role'=>$role,
                    'is_active'=>$isActive,
                    'access_scope'=>'full',
                    'must_change_password'=>1,
                    'created_at'=>date('Y-m-d H:i:s'),
                    'updated_at'=>date('Y-m-d H:i:s'),
                ];
                $userId = mu_insert_dynamic($conn, 'users', $userData);
                if ($userId <= 0) throw new Exception('Data perawat tersimpan, tetapi akun user gagal dibuat.');
                $conn->commit();
                mu_set_flash('success', 'User baru berhasil dibuat. Data otomatis masuk ke Data Perawat dan Data Perawat per Unit. Password awal: ' . $passwordPlain);
            } catch (Throwable $ex) {
                $conn->rollback();
                mu_set_flash('error', 'Gagal membuat user baru: ' . $ex->getMessage());
                mu_redirect_safe('&show_add=1');
            }
            mu_redirect_safe();
        }

        if ($action === 'set_all_viewer') {
            $empIdColRaw = mu_col_exists($conn, 'employees', 'id') ? 'id' : 'employee_id';
            $whereActive = '1=1';
            if (mu_col_exists($conn, 'employees', 'employment_status')) $whereActive = "employment_status='aktif'";
            elseif (mu_col_exists($conn, 'employees', 'is_active')) $whereActive = "is_active=1";
            $rows = mu_rows_safe($conn, "SELECT {$empIdColRaw} AS employee_id FROM employees WHERE {$whereActive}");
            $ok = 0;
            foreach ($rows as $r) if (mu_create_or_update_user_safe($conn, (int)$r['employee_id'], 'viewer', 1)) $ok++;
            mu_set_flash('success', "Selesai. {$ok} karyawan dibuat/diubah menjadi Viewer.");
            mu_redirect_safe();
        }

        if ($action === 'bulk_role') {
            $ids = isset($_POST['selected_employee']) && is_array($_POST['selected_employee']) ? $_POST['selected_employee'] : [];
            $role = $_POST['bulk_role'] ?? 'viewer';
            if (!isset($roles[$role])) $role = 'viewer';
            $active = isset($_POST['bulk_active']) && $_POST['bulk_active'] === '0' ? 0 : 1;
            $ok = 0;
            foreach ($ids as $id) if ((int)$id > 0 && mu_create_or_update_user_safe($conn, (int)$id, $role, $active)) $ok++;
            mu_set_flash('success', "Role berhasil diubah untuk {$ok} data terpilih.");
            mu_redirect_safe();
        }

        if ($action === 'save_role_matrix') {
            $access = isset($_POST['access']) && is_array($_POST['access']) ? $_POST['access'] : [];
            foreach ($roles as $roleName => $roleLabel) {
                foreach ($modules as $m) {
                    $moduleKey = $m['module_key'];
                    $canView = isset($access[$roleName][$moduleKey]) ? 1 : 0;
                    if ($roleName === 'admin' || $roleName === 'superadmin') $canView = 1;
                    $stmt = $conn->prepare("INSERT INTO app_role_menu_permissions(role_name,module_key,can_view) VALUES(?,?,?) ON DUPLICATE KEY UPDATE can_view=VALUES(can_view), updated_at=NOW()");
                    if ($stmt) { $stmt->bind_param('ssi', $roleName, $moduleKey, $canView); $stmt->execute(); $stmt->close(); }
                }
            }
            mu_set_flash('success', 'Checklist hak akses menu berhasil disimpan.');
            mu_redirect_safe();
        }
    }

    if (isset($_GET['reset']) && (int)$_GET['reset'] > 0) {
        $uid = (int)$_GET['reset'];
        $hash = password_hash('balimed1', PASSWORD_DEFAULT);
        if (mu_col_exists($conn, 'users', 'password_hash')) {
            $stmt = $conn->prepare("UPDATE users SET password_hash=?, must_change_password=1 WHERE employee_id=?");
        } else {
            $stmt = $conn->prepare("UPDATE users SET password=?, must_change_password=1 WHERE employee_id=?");
        }
        if ($stmt) { $stmt->bind_param('si', $hash, $uid); $stmt->execute(); $stmt->close(); }
        mu_set_flash('success', 'Password berhasil direset ke balimed1.');
        mu_redirect_safe();
    }

    if (isset($_GET['toggle']) && (int)$_GET['toggle'] > 0) {
        $uid = (int)$_GET['toggle'];
        mu_exec_safe($conn, "UPDATE users SET is_active=IF(is_active=1,0,1) WHERE employee_id={$uid}");
        mu_set_flash('success', 'Status user berhasil diubah.');
        mu_redirect_safe();
    }

    $search = trim((string)($_GET['search'] ?? ''));
    $filterRole = trim((string)($_GET['role'] ?? ''));
    $showAdd = isset($_GET['show_add']) && $_GET['show_add'] === '1';

    $empIdCol = mu_col_exists($conn, 'employees', 'id') ? 'e.id' : 'e.employee_id';
    $empNameCol = mu_col_exists($conn, 'employees', 'full_name') ? 'e.full_name' : (mu_col_exists($conn, 'employees', 'name') ? 'e.name' : "CONCAT('Employee ', {$empIdCol})");
    $empCodeCol = mu_col_exists($conn, 'employees', 'employee_code') ? 'e.employee_code' : (mu_col_exists($conn, 'employees', 'nik') ? 'e.nik' : $empIdCol);
    $nikCol = mu_col_exists($conn, 'employees', 'nik') ? 'e.nik' : $empCodeCol;
    $posCol = mu_col_exists($conn, 'employees', 'position_name') ? 'e.position_name' : (mu_col_exists($conn, 'employees', 'position') ? 'e.position' : "''");
    $emailCol = mu_col_exists($conn, 'employees', 'email') ? 'e.email' : "''";
    $unitJoin = '';
    $unitNameCol = "'-'";
    if (mu_col_exists($conn, 'employees', 'unit_id') && mu_table_exists($conn, 'units') && mu_col_exists($conn, 'units', 'name')) {
        $unitJoin = ' LEFT JOIN units un ON un.id=e.unit_id ';
        $unitNameCol = "COALESCE(un.name,'-')";
    }

    $where = 'WHERE 1=1';
    $params = [];
    $types = '';
    if ($search !== '') {
        $where .= " AND ({$empNameCol} LIKE CONCAT('%',?,'%') OR {$empCodeCol} LIKE CONCAT('%',?,'%') OR {$nikCol} LIKE CONCAT('%',?,'%') OR u.username LIKE CONCAT('%',?,'%'))";
        $params = [$search, $search, $search, $search];
        $types = 'ssss';
    }
    if ($filterRole !== '' && isset($roles[$filterRole])) {
        $where .= " AND COALESCE(u.role,'viewer')=?";
        $params[] = $filterRole;
        $types .= 's';
    }

    $sqlUsers = "SELECT {$empIdCol} AS employee_id, {$empNameCol} AS full_name, {$empCodeCol} AS employee_code, {$nikCol} AS nik, {$posCol} AS position_name, {$emailCol} AS email, {$unitNameCol} AS unit_name,
        u.id AS user_id, u.username, COALESCE(u.role,'viewer') AS role, COALESCE(u.is_active,0) AS is_active";
    $sqlUsers .= mu_col_exists($conn, 'users', 'last_login_at') ? ", u.last_login_at" : ", NULL AS last_login_at";
    $sqlUsers .= " FROM employees e {$unitJoin} LEFT JOIN users u ON u.employee_id={$empIdCol} {$where} ORDER BY full_name ASC LIMIT 1500";
    $users = mu_rows_safe($conn, $sqlUsers, $params, $types);

    $totalEmployees = mu_scalar_safe($conn, "SELECT COUNT(*) FROM employees");
    $totalUsers = mu_scalar_safe($conn, "SELECT COUNT(*) FROM users");
    $totalViewer = mu_scalar_safe($conn, "SELECT COUNT(*) FROM users WHERE role='viewer'");
    $totalModules = count($modules);
    $totalRows = count($users);
?>
<style>
.mu-card{background:#fff;border:1px solid #e2e8f0;border-radius:22px;box-shadow:0 14px 35px rgba(15,23,42,.06)}
.mu-btn{display:inline-flex;align-items:center;gap:.45rem;border-radius:14px;padding:.65rem .9rem;font-weight:800;transition:.2s;text-decoration:none}.mu-btn:hover{transform:translateY(-1px)}
.mu-input{width:100%;border:1px solid #cbd5e1;border-radius:14px;padding:.7rem .9rem;background:white;outline:none}.mu-input:focus{border-color:#2563eb;box-shadow:0 0 0 4px rgba(37,99,235,.12)}
.mu-badge{display:inline-flex;align-items:center;gap:.25rem;border-radius:999px;padding:.25rem .55rem;font-size:.72rem;font-weight:900}.role-viewer{background:#dcfce7;color:#166534}.role-user{background:#dbeafe;color:#1d4ed8}.role-editor{background:#ede9fe;color:#6d28d9}.role-admin,.role-superadmin{background:#fee2e2;color:#b91c1c}.status-on{background:#dcfce7;color:#15803d}.status-off{background:#fee2e2;color:#b91c1c}.mu-chip{display:inline-flex;align-items:center;gap:.25rem;margin:.12rem;border-radius:999px;background:#eef2ff;color:#3730a3;padding:.23rem .5rem;font-size:.7rem;font-weight:800}.mu-table th{background:#f8fafc;color:#64748b;font-size:.72rem;text-transform:uppercase;letter-spacing:.04em}.mu-table th,.mu-table td{padding:.75rem;border-bottom:1px solid #e2e8f0;vertical-align:top}.mu-section-title{font-size:1.12rem;font-weight:900;color:#0f172a}.mu-add-box{background:linear-gradient(135deg,#eff6ff,#f5f3ff);border:1px solid #bfdbfe;border-radius:24px}
</style>

<div class="space-y-5 p-4 md:p-6">
    <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-3">
        <div>
            <h1 class="text-2xl font-black text-slate-900">Manage User</h1>
            <p class="text-sm text-slate-500">Kelola user, tambah user baru, role, dan checklist menu/aplikasi yang boleh tampil.</p>
        </div>
        <div class="flex flex-wrap gap-2">
            <a href="index.php?module=manage_user&show_add=1" class="mu-btn bg-blue-600 text-white"><i class="fas fa-user-plus"></i> Tambah User Baru</a>
            <form method="post" onsubmit="return confirm('Yakin semua user/karyawan dibuat atau diubah menjadi Viewer?');" class="inline">
                <input type="hidden" name="action" value="set_all_viewer">
                <button class="mu-btn bg-emerald-600 text-white"><i class="fas fa-users-cog"></i> Set Semua Jadi Viewer</button>
            </form>
        </div>
    </div>

    <?php if ($success): ?><div class="rounded-2xl bg-green-50 border border-green-200 text-green-800 px-4 py-3 font-bold"><i class="fas fa-check-circle mr-2"></i><?= e($success) ?></div><?php endif; ?>
    <?php if ($error): ?><div class="rounded-2xl bg-red-50 border border-red-200 text-red-800 px-4 py-3 font-bold"><i class="fas fa-exclamation-circle mr-2"></i><?= e($error) ?></div><?php endif; ?>

    <?php if ($showAdd): ?>
    <div class="mu-add-box p-5" id="form-tambah-user">
        <div class="flex items-start justify-between gap-3 mb-4">
            <div>
                <h2 class="mu-section-title"><i class="fas fa-user-plus text-blue-600 mr-2"></i>Tambah User Baru</h2>
                <p class="text-sm text-slate-600">Data akan masuk ke <b>employees</b> dan akun login masuk ke <b>users</b>. Setelah disimpan otomatis muncul di Data Perawat dan Data Perawat per Unit.</p>
            </div>
            <a href="index.php?module=manage_user" class="mu-btn bg-white text-slate-700 border border-slate-200"><i class="fas fa-times"></i> Tutup</a>
        </div>
        <form method="post" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4" onsubmit="return confirm('Simpan user baru?');">
            <input type="hidden" name="action" value="create_new_user_employee">
            <div class="lg:col-span-2"><label class="text-xs font-black text-slate-500 uppercase">Nama Lengkap dengan Gelar</label><input name="full_name" required class="mu-input" placeholder="Contoh: Ns. Nama, S.Kep"></div>
            <div><label class="text-xs font-black text-slate-500 uppercase">NIK / Username Login</label><input name="nik" class="mu-input" placeholder="NIK / ID login"></div>
            <div><label class="text-xs font-black text-slate-500 uppercase">ID Karyawan</label><input name="employee_code" class="mu-input" placeholder="Boleh sama dengan NIK"></div>
            <div><label class="text-xs font-black text-slate-500 uppercase">Email</label><input name="email" type="email" class="mu-input" placeholder="email opsional"></div>
            <div><label class="text-xs font-black text-slate-500 uppercase">Telepon</label><input name="phone" class="mu-input" placeholder="No HP opsional"></div>
            <div><label class="text-xs font-black text-slate-500 uppercase">Unit Kerja</label><select name="unit_id" class="mu-input"><option value="0">-- Pilih Unit --</option><?php foreach($unitRows as $u): ?><option value="<?= (int)$u['id'] ?>"><?= e($u['name']) ?></option><?php endforeach; ?></select></div>
            <div><label class="text-xs font-black text-slate-500 uppercase">Jabatan/Posisi</label><input list="mu_positions" name="position_name" class="mu-input" placeholder="Jabatan"></div>
            <datalist id="mu_positions"><?php foreach($positions as $p): ?><option value="<?= e($p) ?>"><?php endforeach; ?></datalist>
            <div><label class="text-xs font-black text-slate-500 uppercase">Profesi</label><select name="profession" class="mu-input"><?php foreach($professions as $pk=>$pv): ?><option value="<?= e($pk) ?>"><?= e($pv) ?></option><?php endforeach; ?></select></div>
            <div><label class="text-xs font-black text-slate-500 uppercase">Tanggal Bergabung</label><input name="join_date" type="date" class="mu-input"></div>
            <div><label class="text-xs font-black text-slate-500 uppercase">Role Sistem</label><select name="role" class="mu-input"><?php foreach($roles as $rk=>$rl): ?><option value="<?= e($rk) ?>" <?= $rk==='viewer'?'selected':'' ?>><?= e($rl) ?></option><?php endforeach; ?></select></div>
            <div><label class="text-xs font-black text-slate-500 uppercase">Password Awal</label><input name="password" class="mu-input" value="balimed1"></div>
            <div class="flex items-end"><label class="inline-flex items-center gap-2 font-bold text-slate-700"><input type="checkbox" name="is_active" value="1" checked> Aktifkan user</label></div>
            <div class="lg:col-span-4 flex justify-end"><button class="mu-btn bg-blue-600 text-white"><i class="fas fa-save"></i> Simpan User Baru</button></div>
        </form>
    </div>
    <?php endif; ?>

    <div class="grid grid-cols-2 md:grid-cols-5 gap-3">
        <div class="mu-card p-4"><div class="text-xs text-slate-500 font-black">Data Tampil</div><div class="text-2xl font-black"><?= number_format($totalRows) ?></div></div>
        <div class="mu-card p-4"><div class="text-xs text-slate-500 font-black">Total Karyawan</div><div class="text-2xl font-black text-slate-700"><?= number_format($totalEmployees) ?></div></div>
        <div class="mu-card p-4"><div class="text-xs text-slate-500 font-black">Total User</div><div class="text-2xl font-black text-blue-700"><?= number_format($totalUsers) ?></div></div>
        <div class="mu-card p-4"><div class="text-xs text-slate-500 font-black">Viewer</div><div class="text-2xl font-black text-emerald-700"><?= number_format($totalViewer) ?></div></div>
        <div class="mu-card p-4"><div class="text-xs text-slate-500 font-black">Modul/Menu</div><div class="text-2xl font-black text-indigo-700"><?= number_format($totalModules) ?></div></div>
    </div>

    <div class="mu-card p-5">
        <div class="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4 mb-4">
            <div><h2 class="mu-section-title">Tabel User</h2><p class="text-sm text-slate-500">Centang nama lalu ubah role massal. User baru yang dibuat akan otomatis terlihat di sini.</p></div>
            <a href="#role-matrix" class="mu-btn bg-indigo-50 text-indigo-700"><i class="fas fa-table"></i> Lihat Matrix Role</a>
        </div>

        <form method="get" class="grid grid-cols-1 md:grid-cols-5 gap-3 mb-4 bg-slate-50 rounded-2xl p-4">
            <input type="hidden" name="module" value="manage_user">
            <div class="md:col-span-3"><label class="text-xs font-black text-slate-500 uppercase">Cari</label><input class="mu-input" name="search" value="<?= e($search) ?>" placeholder="Nama, NIK, ID karyawan, username..."></div>
            <div><label class="text-xs font-black text-slate-500 uppercase">Role</label><select class="mu-input" name="role"><option value="">Semua Role</option><?php foreach($roles as $rk=>$rl): ?><option value="<?= e($rk) ?>" <?= $filterRole===$rk?'selected':'' ?>><?= e($rl) ?></option><?php endforeach; ?></select></div>
            <div class="flex items-end"><button class="mu-btn bg-blue-600 text-white w-full justify-center"><i class="fas fa-search"></i> Cari</button></div>
        </form>

        <form method="post" onsubmit="return confirmBulkRole();">
            <input type="hidden" name="action" value="bulk_role">
            <div class="mb-4 rounded-2xl bg-slate-900 text-white p-4 flex flex-col md:flex-row md:items-center md:justify-between gap-3">
                <div class="font-black"><i class="fas fa-check-square mr-2"></i>Aksi untuk nama yang dicentang</div>
                <div class="flex flex-col sm:flex-row gap-2">
                    <select name="bulk_role" class="mu-input text-slate-800 min-w-[160px]"><?php foreach($roles as $rk=>$rl): ?><option value="<?= e($rk) ?>" <?= $rk==='viewer'?'selected':'' ?>><?= e($rl) ?></option><?php endforeach; ?></select>
                    <select name="bulk_active" class="mu-input text-slate-800 min-w-[130px]"><option value="1">Aktif</option><option value="0">Nonaktif</option></select>
                    <button class="mu-btn bg-emerald-500 text-white"><i class="fas fa-save"></i> Ubah Role Terpilih</button>
                </div>
            </div>

            <div class="overflow-x-auto rounded-2xl border border-slate-200">
                <table class="w-full mu-table bg-white">
                    <thead><tr><th><input type="checkbox" onclick="toggleMUAll(this)"></th><th>No</th><th>Nama</th><th>ID/NIK</th><th>Username</th><th>Role</th><th>Status</th><th>Last Login</th><th class="min-w-[280px]">Aplikasi Terlihat</th><th>Aksi</th></tr></thead>
                    <tbody>
                    <?php if (!$users): ?><tr><td colspan="10" class="text-center text-slate-500 py-8">Data user/karyawan tidak ditemukan.</td></tr><?php endif; ?>
                    <?php $no=1; foreach($users as $r): $rowRole=$r['role'] ?: 'viewer'; $apps=mu_visible_module_names($conn,$rowRole); ?>
                        <tr>
                            <td><input type="checkbox" class="mu-row" name="selected_employee[]" value="<?= (int)$r['employee_id'] ?>"></td>
                            <td><?= $no++ ?></td>
                            <td><div class="font-black text-slate-800"><?= e($r['full_name']) ?></div><div class="text-xs text-slate-500"><?= e(($r['position_name'] ?: 'Staf') . ' • ' . ($r['unit_name'] ?: '-')) ?></div></td>
                            <td><?= e($r['employee_code'] ?: $r['nik'] ?: '-') ?></td>
                            <td><?= e($r['username'] ?: '-') ?></td>
                            <td><span class="mu-badge role-<?= e($rowRole) ?>"><?= e($roles[$rowRole] ?? ucfirst($rowRole)) ?></span></td>
                            <td><span class="mu-badge <?= ((int)$r['is_active']===1)?'status-on':'status-off' ?>"><?= ((int)$r['is_active']===1)?'Aktif':'Nonaktif/Belum User' ?></span></td>
                            <td><?= !empty($r['last_login_at']) ? e(date('d/m/Y H:i', strtotime($r['last_login_at']))) : 'Belum pernah' ?></td>
                            <td><?php if($apps): foreach($apps as $app): ?><span class="mu-chip"><i class="fas fa-eye"></i><?= e($app['module_name']) ?></span><?php endforeach; else: ?><span class="text-xs font-bold text-red-600">Tidak ada menu terlihat</span><?php endif; ?></td>
                            <td class="whitespace-nowrap">
                                <?php if($r['user_id']): ?>
                                    <a href="index.php?module=manage_user&reset=<?= (int)$r['employee_id'] ?>" onclick="return confirm('Reset password ke balimed1?');" class="px-3 py-1.5 rounded-xl bg-amber-500 text-white text-xs font-black">Reset</a>
                                    <a href="index.php?module=manage_user&toggle=<?= (int)$r['employee_id'] ?>" class="px-3 py-1.5 rounded-xl bg-slate-600 text-white text-xs font-black">On/Off</a>
                                <?php else: ?>
                                    <span class="text-xs text-slate-400">Centang lalu set role</span>
                                <?php endif; ?>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
        </form>
    </div>

    <div class="mu-card p-5" id="role-matrix">
        <div class="mb-4"><h2 class="mu-section-title">Tabel Role Bisa Lihat Menu Apa Saja</h2><p class="text-sm text-slate-500">Centang menu/aplikasi yang boleh terlihat untuk setiap role. Admin dan Superadmin dikunci full akses.</p></div>
        <form method="post">
            <input type="hidden" name="action" value="save_role_matrix">
            <div class="overflow-x-auto rounded-2xl border border-slate-200">
                <table class="w-full mu-table bg-white">
                    <thead><tr><th class="min-w-[280px]">Menu / Aplikasi</th><?php foreach($roles as $rk=>$rl): ?><th class="text-center min-w-[120px]"><?= e($rl) ?></th><?php endforeach; ?></tr></thead>
                    <tbody>
                    <?php foreach($modules as $m): ?>
                        <tr>
                            <td><div class="font-black text-slate-800"><i class="<?= e($m['icon']) ?> mr-2 text-indigo-600"></i><?= e($m['module_name']) ?></div><div class="text-xs text-slate-500"><?= e($m['module_group']) ?> • <?= e($m['module_key']) ?></div></td>
                            <?php foreach($roles as $rk=>$rl): $checked = (isset($matrix[$rk][$m['module_key']]) && (int)$matrix[$rk][$m['module_key']]===1); $locked = in_array($rk, ['admin','superadmin'], true); ?>
                                <td class="text-center"><input type="checkbox" name="access[<?= e($rk) ?>][<?= e($m['module_key']) ?>]" <?= $checked || $locked ? 'checked' : '' ?> <?= $locked ? 'disabled' : '' ?> class="w-5 h-5"></td>
                            <?php endforeach; ?>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
            <div class="mt-4 flex justify-end"><button class="mu-btn bg-indigo-600 text-white"><i class="fas fa-save"></i> Simpan Checklist Role</button></div>
        </form>
    </div>
</div>
<script>
function toggleMUAll(source){document.querySelectorAll('.mu-row').forEach(cb=>cb.checked=source.checked)}
function confirmBulkRole(){const n=document.querySelectorAll('.mu-row:checked').length;if(n===0){alert('Centang minimal satu user/karyawan.');return false;}return confirm('Ubah role untuk '+n+' data terpilih?');}
</script>
<?php
} catch (Throwable $e) {
    echo '<div class="p-6 rounded-2xl bg-red-50 border border-red-200 text-red-700">';
    echo '<div class="font-black text-lg mb-2">Manage User error</div>';
    echo '<pre class="whitespace-pre-wrap text-sm">' . e($e->getMessage()) . '</pre>';
    echo '</div>';
}
