<?php
require_once dirname(__DIR__) . '/bootstrap.php';

$auth->requireRole(ROLE_APP_ADMIN);

$userModel = new User();
$action    = $_GET['action'] ?? 'list';
$userId    = isset($_GET['id']) ? (int)$_GET['id'] : null;
$error     = null;
$editUser  = null;

if (!Session::has('csrf_token')) {
    Session::set('csrf_token', bin2hex(random_bytes(32)));
}

// ── Handle POST ──────────────────────────────────────────────────────────────
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $token = $_POST['csrf_token'] ?? '';
    if (!hash_equals(Session::get('csrf_token', ''), $token)) {
        Session::setFlash('error', t('msg.error'));
        header('Location: /admin/users.php');
        exit;
    }

    $postAction = $_POST['action'] ?? '';

    /**
     * Auto-protection : empêche un admin courant de retirer son propre app_admin
     * via un POST forgé (la checkbox est déjà désactivée côté client).
     */
    $protectSelfAppAdmin = function (int $editedId, array $roles): array {
        if ($editedId === (int)Session::get('user_id')
            && in_array(ROLE_APP_ADMIN, Session::get('roles', []) ?: [], true)
            && !in_array(ROLE_APP_ADMIN, $roles, true)) {
            $roles[] = ROLE_APP_ADMIN;
        }
        return $roles;
    };

    /**
     * N'autorise que les profils assignables : rôles système (module NULL) ou
     * rôles d'un module ACTIF. Les profils d'un module désactivé ne sont pas
     * attribuables — sauf ceux déjà détenus par l'utilisateur (préservés pour ne
     * pas les retirer lors d'une simple édition). Filet serveur en complément du
     * masquage de _user_form.php.
     */
    $filterAssignableRoles = function (array $roles, int $userId = 0) use ($userModel, $moduleRegistry): array {
        $roleModule = [];
        foreach ($userModel->getAllRoles() as $r) {
            $roleModule[$r['name']] = $r['module'];   // null = rôle système
        }
        $current = $userId > 0 ? $userModel->getRoles($userId) : [];
        $out = [];
        foreach ($roles as $rn) {
            if (!array_key_exists($rn, $roleModule)) continue;        // rôle inconnu
            $mod = $roleModule[$rn];
            if ($mod === null
                || $moduleRegistry->isActive($mod)
                || in_array($rn, $current, true)) {
                $out[] = $rn;
            }
        }
        return array_values(array_unique($out));
    };

    if ($postAction === 'create') {
        $username   = trim($_POST['username']   ?? '');
        $email      = trim($_POST['email']      ?? '');
        $password   = $_POST['password']        ?? '';
        $roles      = $filterAssignableRoles(array_values(array_unique($_POST['roles'] ?? [])));
        $authMethod = $_POST['auth_method']     ?? AUTH_LOCAL;
        $lang       = $_POST['language']        ?? null;
        $theme      = $_POST['theme']           ?? null;
        $active     = isset($_POST['active']) ? 1 : 0;

        if (empty($username)) {
            $error  = t('msg.required_fields');
            $action = 'create';
        } elseif ($authMethod === AUTH_LOCAL && empty($password)) {
            $error  = t('msg.required_fields');
            $action = 'create';
        } elseif ($authMethod === AUTH_LOCAL && strlen($password) < 8) {
            // Politique mot de passe : minimum 8 caractères (cohérent avec le
            // changement de mot de passe self-service).
            $error  = t('auth.password_too_short');
            $action = 'create';
        } else {
            // Vérifier dans l'AD (par SAN ou par email) + résoudre le SAN réel
            if ($authMethod === AUTH_LDAP) {
                $ldapUser = $auth->lookupLdapUser($username);
                if (!$ldapUser || $ldapUser['san'] === '') {
                    $error  = t('msg.ldap_user_not_found');
                    $action = 'create';
                } else {
                    $username = $ldapUser['san'];  // SAN résolu (ex: olivjoly)
                    if ($email === '' && $ldapUser['email'] !== '') {
                        $email = $ldapUser['email'];
                    }
                }
            }

            if (!$error) {
                $id = $userModel->create([
                    'username'    => $username,
                    'email'       => $email ?: null,
                    'password'    => $password ?: null,
                    'auth_method' => $authMethod,
                    'language'    => $lang  ?: null,
                    'theme'       => $theme ?: null,
                    'active'      => $active,
                ]);

                if ($id) {
                    $userModel->setRoles($id, $roles);
                    Session::setFlash('success', t('msg.user_created'));
                    header('Location: /admin/users.php');
                } else {
                    $error  = t('msg.username_taken');
                    $action = 'create';
                }
                exit;
            }
        }

    } elseif ($postAction === 'edit') {
        $editId     = (int)($_POST['user_id']   ?? 0);
        $email      = trim($_POST['email']      ?? '');
        $password   = $_POST['password']        ?? '';
        $roles      = $filterAssignableRoles(array_values(array_unique($_POST['roles'] ?? [])), $editId);
        $roles      = $protectSelfAppAdmin($editId, $roles);
        $authMethod = $_POST['auth_method']     ?? AUTH_LOCAL;
        $lang       = $_POST['language']        ?? null;
        $theme      = $_POST['theme']           ?? null;
        $active     = isset($_POST['active']) ? 1 : 0;

        // Vérifier que le SAN existe dans l'AD + récupérer l'email
        if ($authMethod === AUTH_LDAP) {
            $existingUser = $userModel->findById($editId);
            $san = $existingUser['username'] ?? '';
            if ($san !== '') {
                $ldapUser = $auth->lookupLdapUser($san);
                if (!$ldapUser) {
                    Session::setFlash('error', t('msg.ldap_user_not_found'));
                    header('Location: /admin/users.php?action=edit&id=' . $editId);
                    exit;
                }
                if ($email === '' && ($ldapUser['email'] ?? '') !== '') {
                    $email = $ldapUser['email'];
                }
            }
        }

        $data = [
            'email'       => $email ?: null,
            'auth_method' => $authMethod,
            'language'    => $lang  ?: null,
            'theme'       => $theme ?: null,
            'active'      => $active,
        ];
        if (!empty($password)) {
            $data['password'] = $password;
        }

        if ($userModel->update($editId, $data)) {
            $userModel->setRoles($editId, $roles);
            Session::setFlash('success', t('msg.user_updated'));
            header('Location: /admin/users.php');
        } else {
            Session::setFlash('error', t('msg.error'));
            header('Location: /admin/users.php?action=edit&id=' . $editId);
        }
        exit;

    } elseif ($postAction === 'delete') {
        $delId = (int)($_POST['user_id'] ?? 0);
        // Prevent deleting own account
        if ($delId === (int)Session::get('user_id')) {
            Session::setFlash('error', t('msg.error'));
        } else {
            $userModel->delete($delId);
            Session::setFlash('success', t('msg.user_deleted'));
        }
        header('Location: /admin/users.php');
        exit;
    }
}

// ── Load data for edit form ──────────────────────────────────────────────────
if ($action === 'edit' && $userId) {
    $editUser = $userModel->findById($userId);
    if (!$editUser) {
        Session::setFlash('error', t('msg.not_found'));
        header('Location: /admin/users.php');
        exit;
    }
}

$allRoles    = $userModel->getAllRoles();
$users       = ($action === 'list') ? $userModel->findAll() : [];

// Rôles courants de l'utilisateur en édition (vide pour création)
$userRoles = $editUser ? ($editUser['roles'] ?? []) : ($_POST['roles'] ?? []);

// ── Render ───────────────────────────────────────────────────────────────────
View::display(__DIR__ . '/views/users.php', [
    'action'    => $action,
    'userId'    => $userId,
    'editUser'  => $editUser,
    'allRoles'  => $allRoles,
    'users'     => $users,
    'userRoles' => $userRoles,
    'error'     => $error,
]);
