<?php
declare(strict_types=1);

/**
 * config/master_auth.php
 * FIX FINAL - Login Perawat pakai database lokal aplikasi, bukan tabel master-only.
 * - Tidak mengubah index.php
 * - Login tetap lewat master_login_app($login, $password, 'perawat') agar login.php asli tetap cocok
 * - Prioritas: tabel lokal users + employees dari config/database.php
 * - Fallback: tabel master lama accounts + employee_app_access dari master_db.php
 */

$masterDbFile = __DIR__ . '/master_db.php';
if (file_exists($masterDbFile)) {
    require_once $masterDbFile;
}

if (session_status() !== PHP_SESSION_ACTIVE) {
    session_name('PERAWATSESSID');
    session_set_cookie_params([
        'lifetime' => 0,
        'path' => '/',
        'domain' => '',
        'secure' => isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off',
        'httponly' => true,
        'samesite' => 'Lax',
    ]);
    session_start();
}

if (!function_exists('ma_safe_col')) {
    function ma_safe_col(mysqli $conn, string $table, string $column): bool
    {
        try {
            $tableEsc = $conn->real_escape_string($table);
            $colEsc = $conn->real_escape_string($column);
            $res = $conn->query("SHOW COLUMNS FROM `{$tableEsc}` LIKE '{$colEsc}'");
            return $res && $res->num_rows > 0;
        } catch (Throwable $e) {
            return false;
        }
    }
}

if (!function_exists('ma_safe_table')) {
    function ma_safe_table(mysqli $conn, string $table): bool
    {
        try {
            $tableEsc = $conn->real_escape_string($table);
            $res = $conn->query("SHOW TABLES LIKE '{$tableEsc}'");
            return $res && $res->num_rows > 0;
        } catch (Throwable $e) {
            return false;
        }
    }
}

if (!function_exists('ma_local_conn')) {
    function ma_local_conn(): ?mysqli
    {
        static $localConn = null;
        if ($localConn instanceof mysqli) return $localConn;

        $dbFile = __DIR__ . '/database.php';
        if (file_exists($dbFile)) {
            require_once $dbFile;
        }

        if (function_exists('getConnection')) {
            try {
                $c = getConnection();
                if ($c instanceof mysqli) {
                    $c->set_charset('utf8mb4');
                    $localConn = $c;
                    return $localConn;
                }
            } catch (Throwable $e) {
                // lanjut coba koneksi manual dari constant bila tersedia
            }
        }

        global $conn;
        if (isset($conn) && $conn instanceof mysqli) {
            $conn->set_charset('utf8mb4');
            $localConn = $conn;
            return $localConn;
        }

        $host = defined('DB_HOST') ? DB_HOST : (defined('MYSQL_HOST') ? MYSQL_HOST : null);
        $user = defined('DB_USER') ? DB_USER : (defined('MYSQL_USER') ? MYSQL_USER : null);
        $pass = defined('DB_PASS') ? DB_PASS : (defined('MYSQL_PASS') ? MYSQL_PASS : '');
        $name = defined('DB_NAME') ? DB_NAME : (defined('MYSQL_DATABASE') ? MYSQL_DATABASE : null);

        if ($host && $user && $name) {
            try {
                $c = @new mysqli((string)$host, (string)$user, (string)$pass, (string)$name);
                if (!$c->connect_errno) {
                    $c->set_charset('utf8mb4');
                    $localConn = $c;
                    return $localConn;
                }
            } catch (Throwable $e) {
                return null;
            }
        }

        return null;
    }
}

if (!function_exists('ma_local_login')) {
    function ma_local_login(string $login, string $password): ?array
    {
        $conn = ma_local_conn();
        if (!$conn instanceof mysqli) {
            return null; // biarkan fallback ke master lama
        }

        if (!ma_safe_table($conn, 'users') || !ma_safe_table($conn, 'employees')) {
            return null; // jangan error; fallback ke master lama
        }

        $empIdCol     = ma_safe_col($conn, 'employees', 'id') ? 'e.id' : 'e.employee_id';
        $empCodeCol   = ma_safe_col($conn, 'employees', 'employee_code') ? 'e.employee_code' : "''";
        $nikCol       = ma_safe_col($conn, 'employees', 'nik') ? 'e.nik' : "''";
        $nameCol      = ma_safe_col($conn, 'employees', 'full_name') ? 'e.full_name' : (ma_safe_col($conn, 'employees', 'nama_lengkap') ? 'e.nama_lengkap' : (ma_safe_col($conn, 'employees', 'name') ? 'e.name' : "u.username"));
        $emailCol     = ma_safe_col($conn, 'employees', 'email') ? 'e.email' : "''";
        $unitIdCol    = ma_safe_col($conn, 'employees', 'unit_id') ? 'e.unit_id' : 'NULL';
        $posIdCol     = ma_safe_col($conn, 'employees', 'position_id') ? 'e.position_id' : 'NULL';
        $posNameCol   = ma_safe_col($conn, 'employees', 'position_name') ? 'e.position_name' : (ma_safe_col($conn, 'employees', 'position') ? 'e.position' : "''");

        $unitJoin = '';
        $unitNameCol = "''";
        if (ma_safe_col($conn, 'employees', 'unit_id') && ma_safe_table($conn, 'units')) {
            $unitIdName = ma_safe_col($conn, 'units', 'id') ? 'id' : null;
            $unitNameName = ma_safe_col($conn, 'units', 'name') ? 'name' : (ma_safe_col($conn, 'units', 'unit_name') ? 'unit_name' : null);
            if ($unitIdName && $unitNameName) {
                $unitJoin = " LEFT JOIN units un ON un.`{$unitIdName}` = e.unit_id ";
                $unitNameCol = "un.`{$unitNameName}`";
            }
        }

        $statusCondition = '1=1';
        if (ma_safe_col($conn, 'employees', 'employment_status')) {
            $statusCondition = "(e.employment_status IS NULL OR e.employment_status='' OR e.employment_status='aktif')";
        } elseif (ma_safe_col($conn, 'employees', 'is_active')) {
            $statusCondition = "e.is_active=1";
        }

        $sql = "
            SELECT
                u.id AS user_id,
                u.employee_id,
                u.username,
                u.password_hash,
                COALESCE(u.role, 'viewer') AS role,
                COALESCE(u.must_change_password, 0) AS must_change_password,
                COALESCE(u.is_active, 0) AS user_active,
                {$empIdCol} AS emp_pk,
                {$empCodeCol} AS employee_code,
                {$nikCol} AS nik,
                {$nameCol} AS nama,
                {$emailCol} AS email,
                {$unitIdCol} AS unit_id,
                {$posIdCol} AS position_id,
                {$unitNameCol} AS unit_name,
                {$posNameCol} AS position_name
            FROM users u
            INNER JOIN employees e ON e.id = u.employee_id
            {$unitJoin}
            WHERE (
                    u.username = ?
                    OR {$empCodeCol} = ?
                    OR {$nikCol} = ?
                  )
              AND {$statusCondition}
            LIMIT 1
        ";

        $stmt = $conn->prepare($sql);
        if (!$stmt) {
            return ['success' => false, 'message' => 'Query login lokal gagal: ' . $conn->error];
        }
        $stmt->bind_param('sss', $login, $login, $login);
        $stmt->execute();
        $res = $stmt->get_result();
        $user = $res ? $res->fetch_assoc() : null;
        $stmt->close();

        if (!$user) {
            return null; // boleh fallback ke master lama
        }

        if ((int)$user['user_active'] !== 1) {
            return ['success' => false, 'message' => 'Akun nonaktif'];
        }

        if (!password_verify($password, (string)$user['password_hash'])) {
            return ['success' => false, 'message' => 'Password salah'];
        }

        session_regenerate_id(true);

        $role = strtolower((string)($user['role'] ?: 'viewer'));
        $nama = (string)($user['nama'] ?: $user['username']);

        $_SESSION['user'] = [
            'logged_in'            => true,
            'account_id'           => (int)$user['user_id'],
            'user_id'              => (int)$user['user_id'],
            'employee_id'          => (int)$user['employee_id'],
            'employee_code'        => (string)($user['employee_code'] ?? ''),
            'nik'                  => (string)($user['nik'] ?? ''),
            'username'             => (string)$user['username'],
            'nama'                 => $nama,
            'nama_lengkap'         => $nama,
            'full_name'            => $nama,
            'email'                => (string)($user['email'] ?? ''),
            'unit_id'              => $user['unit_id'] !== null ? (int)$user['unit_id'] : null,
            'unit_name'            => (string)($user['unit_name'] ?? ''),
            'position_id'          => $user['position_id'] !== null ? (int)$user['position_id'] : null,
            'position_name'        => (string)($user['position_name'] ?? ''),
            'role'                 => $role,
            'app_code'             => 'perawat',
            'app_name'             => 'Sistem Keperawatan',
            'must_change_password' => (int)($user['must_change_password'] ?? 0),
        ];

        // Kompatibilitas modul lama yang membaca session flat.
        $_SESSION['logged_in']     = true;
        $_SESSION['user_id']       = (int)$user['user_id'];
        $_SESSION['employee_id']   = (int)$user['employee_id'];
        $_SESSION['username']      = (string)$user['username'];
        $_SESSION['nama']          = $nama;
        $_SESSION['nama_lengkap']  = $nama;
        $_SESSION['role']          = $role;
        $_SESSION['user_role']     = $role;
        $_SESSION['unit_id']       = $user['unit_id'] !== null ? (int)$user['unit_id'] : null;
        $_SESSION['unit_name']     = (string)($user['unit_name'] ?? '');

        try {
            $ip = $_SERVER['REMOTE_ADDR'] ?? null;
            if (ma_safe_col($conn, 'users', 'last_login_ip')) {
                $upd = $conn->prepare("UPDATE users SET last_login_at=NOW(), last_login_ip=? WHERE id=?");
                if ($upd) {
                    $uid = (int)$user['user_id'];
                    $upd->bind_param('si', $ip, $uid);
                    $upd->execute();
                    $upd->close();
                }
            } else {
                $uid = (int)$user['user_id'];
                $conn->query("UPDATE users SET last_login_at=NOW() WHERE id={$uid}");
            }
        } catch (Throwable $e) {
            // login tetap berhasil walau update last login gagal
        }

        return ['success' => true, 'message' => 'Login berhasil'];
    }
}

if (!function_exists('ma_master_legacy_login')) {
    function ma_master_legacy_login(string $login, string $password, string $appCode = 'perawat'): array
    {
        if (!function_exists('master_db')) {
            return ['success' => false, 'message' => 'Koneksi master_db tidak tersedia'];
        }

        try {
            $pdo = master_db();

            $sql = "
                SELECT
                    a.id AS account_id,
                    a.username,
                    a.password_hash,
                    a.must_change_password,
                    a.is_active AS account_active,
                    e.id AS employee_id,
                    e.employee_code,
                    e.nik,
                    e.nama_lengkap,
                    e.email,
                    e.unit_id,
                    e.position_id,
                    e.is_active AS employee_active,
                    u.name AS unit_name,
                    p.name AS position_name,
                    ap.app_code,
                    ap.app_name,
                    ea.role_name,
                    ea.can_login,
                    ea.is_active AS access_active
                FROM accounts a
                INNER JOIN employees e ON e.id = a.employee_id
                LEFT JOIN units u ON u.id = e.unit_id
                LEFT JOIN positions p ON p.id = e.position_id
                INNER JOIN employee_app_access ea ON ea.employee_id = e.id
                INNER JOIN apps ap ON ap.id = ea.app_id
                WHERE (
                        a.username = :login
                        OR e.employee_code = :login
                        OR e.nik = :login
                      )
                  AND ap.app_code = :app_code
                LIMIT 1
            ";

            $stmt = $pdo->prepare($sql);
            $stmt->execute([
                ':login' => $login,
                ':app_code' => $appCode,
            ]);
            $user = $stmt->fetch();

            if (!$user) {
                return ['success' => false, 'message' => 'Username tidak ditemukan atau tidak punya akses ke aplikasi ini'];
            }
            if ((int)$user['account_active'] !== 1) return ['success' => false, 'message' => 'Akun nonaktif'];
            if ((int)$user['employee_active'] !== 1) return ['success' => false, 'message' => 'Karyawan nonaktif'];
            if ((int)$user['access_active'] !== 1 || (int)$user['can_login'] !== 1) return ['success' => false, 'message' => 'Tidak memiliki izin login'];
            if (!password_verify($password, $user['password_hash'])) return ['success' => false, 'message' => 'Password salah'];

            session_regenerate_id(true);
            $_SESSION['user'] = [
                'logged_in'            => true,
                'account_id'           => (int)$user['account_id'],
                'user_id'              => (int)$user['account_id'],
                'employee_id'          => (int)$user['employee_id'],
                'employee_code'        => $user['employee_code'],
                'nik'                  => $user['nik'],
                'username'             => $user['username'],
                'nama'                 => $user['nama_lengkap'],
                'nama_lengkap'         => $user['nama_lengkap'],
                'email'                => $user['email'],
                'unit_id'              => $user['unit_id'],
                'unit_name'            => $user['unit_name'],
                'position_id'          => $user['position_id'],
                'position_name'        => $user['position_name'],
                'role'                 => strtolower((string)$user['role_name']),
                'app_code'             => $user['app_code'],
                'app_name'             => $user['app_name'],
                'must_change_password' => (int)$user['must_change_password'],
            ];

            $_SESSION['logged_in']     = true;
            $_SESSION['user_id']       = (int)$user['account_id'];
            $_SESSION['employee_id']   = (int)$user['employee_id'];
            $_SESSION['username']      = (string)$user['username'];
            $_SESSION['nama']          = (string)$user['nama_lengkap'];
            $_SESSION['nama_lengkap']  = (string)$user['nama_lengkap'];
            $_SESSION['role']          = strtolower((string)$user['role_name']);
            $_SESSION['user_role']     = strtolower((string)$user['role_name']);
            $_SESSION['unit_id']       = $user['unit_id'];
            $_SESSION['unit_name']     = (string)$user['unit_name'];

            $upd = $pdo->prepare("UPDATE accounts SET last_login_at = NOW() WHERE id = ?");
            $upd->execute([(int)$user['account_id']]);

            return ['success' => true, 'message' => 'Login berhasil'];
        } catch (Throwable $e) {
            return ['success' => false, 'message' => 'Login gagal: ' . $e->getMessage()];
        }
    }
}

if (!function_exists('master_login_app')) {
    function master_login_app(string $login, string $password, string $appCode = 'perawat'): array
    {
        // Untuk aplikasi perawat: prioritas database lokal agar sesuai Manage User.
        $local = ma_local_login($login, $password);
        if (is_array($local)) {
            return $local;
        }

        // Jika user tidak ada di lokal atau koneksi lokal tidak tersedia, pakai master lama.
        return ma_master_legacy_login($login, $password, $appCode);
    }
}

if (!function_exists('current_user')) {
    function current_user(): ?array
    {
        return $_SESSION['user'] ?? null;
    }
}

if (!function_exists('require_login')) {
    function require_login(): void
    {
        if (empty($_SESSION['user']['logged_in'])) {
            header('Location: login.php');
            exit;
        }
    }
}

if (!function_exists('logout_user')) {
    function logout_user(): void
    {
        $_SESSION = [];
        if (ini_get('session.use_cookies')) {
            $params = session_get_cookie_params();
            setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
        }
        session_destroy();
    }
}
