<?php

namespace App\Controllers;

use App\Middlewares\AuthMiddleware;
use App\Models\PasswordReset;
use App\Models\PersonType;
use App\Models\User;
use App\Models\UserUgel;
use App\Services\MailService;
use App\Services\PasswordResetService;
use App\Services\PasswordValidator;
use App\Services\PersonTypeService;
use App\Services\UserRecoveryService;
use App\Services\UserService;

class AuthController
{
    protected PasswordResetService $passwordResetService;
    protected PersonTypeService $personTypeService;
    protected UserService $userService;
    protected UserRecoveryService $userRecoveryService;

    public function __construct() 
    {
        $this->passwordResetService = new PasswordResetService();
        $this->personTypeService = new PersonTypeService();
        $this->userService = new UserService();
        $this->userRecoveryService = new UserRecoveryService();
    }

    public function loginForm ()
    {
        AuthMiddleware::redirectIfAuthenticated();
        include __DIR__ . '/../views/auth/login.php';
    }



    public function login()
    {
        session_start();

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $username = $_POST['username'] ?? '';
            $password = trim($_POST['password']);

            if (empty($username) || empty($password)) {
                $_SESSION['message'] = "Todos los campos son obligatorios.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER);
                exit;
            }

            $user = $this->userService->findByUsername($username);

            if (!$user || !password_verify($password, $user->password)) {
                $_SESSION['message'] = "Credenciales incorrectas.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER);
                exit;
            }

            session_regenerate_id(true);
            $_SESSION['user_id'] = $user->id;

            // Obtener los roles asociados al usuario
            $roles = $this->userService->getUserRoles($user->id);

            if (empty($roles)) {
                $_SESSION['message'] = "Tu cuenta no tiene roles asignados. Contacta con el administrador.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER);
                exit;
            }

            // Si tiene varios roles, mostrar pantalla para elegir
            if (count($roles) > 1) {
                $_SESSION['available_roles'] = $roles;
                header("Location: " . BASE_HEADER . "select-role");
                exit;
            }

            // Si tiene solo uno, lo establecemos directamente
            $this->setRoleSession($roles[0]->name);
            header("Location: " . BASE_HEADER . "dashboard");
            exit;
        }
    }

    public function setRole()
    {
        session_start();

        if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['role'])) {
            $role = $_POST['role'];

            $this->setRoleSession($role);

            header("Location: " . BASE_HEADER . "dashboard");
            exit;
        }

        $_SESSION['message'] = "Debes seleccionar un rol válido.";
        $_SESSION['message_type'] = "danger";
        header("Location: " . BASE_HEADER . "select-role");
        exit;
    }


    private function setRoleSession($role)
    {
        // 🔹 Limpia datos de roles anteriores por seguridad
        unset($_SESSION['group'], $_SESSION['mirror_id'], $_SESSION['person_type'], $_SESSION['person_type_id']);

        $_SESSION['role'] = $role;

        if ($role === 'UGEL' || $role === 'ADMIN') {
            // ✅ Si es UGEL, obtener info de su usuario UGEL
            $ugelUser = UserUgel::findBy('user_id', $_SESSION['user_id']);
            if ($ugelUser) {
                $_SESSION['group'] = $ugelUser->group()->description ?? null;
            }
        }

        if ($role === 'COMUNITY') {
            // ✅ Si es comunidad, verificar si proviene de un usuario UGEL
            $ugelUser = UserUgel::findBy('user_id', $_SESSION['user_id']);

            if ($ugelUser) {
                // Tiene un usuario UGEL: buscar o crear su espejo comunidad
                $mirrorComunity = $this->userService->findMirrorComunity($ugelUser->dni);

                if (!$mirrorComunity) {
                    $mirrorComunity = $this->userService->createMirrorComunity($ugelUser);
                }

                $_SESSION['mirror_id'] = $mirrorComunity->id;
            }
        }
    }



    // public function login()
    // {
    //     session_start();
        
    //     if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    //         $username = $_POST['username'] ?? '';
    //         $password = trim($_POST['password']);

    //         if (empty($username) || empty($password)) {
    //             $_SESSION['message'] = "Todos los campos son obligatorios.";
    //             $_SESSION['message_type'] = "danger";
    //             header("Location: " . BASE_HEADER);
    //             exit;
    //         }

    //         $user = $this->userService->findByUsername($username);            

    //         if (!$user || !password_verify($password, $user->password)) {
    //             $_SESSION['message'] = "Credenciales incorrectas.";
    //             $_SESSION['message_type'] = "danger";
    //             header("Location: " . BASE_HEADER);
    //             exit;
    //         }

    //         session_regenerate_id(true);

    //         $_SESSION['user_id'] = $user->id;
    //         $_SESSION['role'] = $user->role;

    //         if($user->role === 'UGEL'){
    //             $ugelUser = UserUgel::findBy('user_id', $user->id);
                
    //             $mirrorComunity = $this->userService->findMirrorComunity($ugelUser->dni);

    //             if (!$mirrorComunity) {
    //                 $this->userService->createMirrorComunity($ugelUser);
    //             }

    //             $_SESSION['group'] = $ugelUser->group()->description;
    //             $_SESSION['mirror_id'] = $mirrorComunity->id;


    //         }

    //         if ($user->role === 'COMUNITY' && !isset($_SESSION['person_type_id'])) {
    //             header("Location: " . BASE_HEADER . "select-person-type");
    //             exit;
    //         }            

    //         unset($_SESSION['message'], $_SESSION['message_type']);
    //         header("Location: " . BASE_HEADER . "dashboard");
    //         exit;
    //     }
    // }


    public function selectPersonType()
    {
        if (!isset($_SESSION['user_id'])) {
            header("Location: " . BASE_HEADER);
            exit;
        }

        $personTypes = $this->personTypeService->getByUserId($_SESSION['user_id']);

        require_once __DIR__ . '/../views/auth/select_person_type.php';
    }

    public function setPersonType()
    {
        session_start();

        if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['person_type_id'])) {
            $personTypeId = intval($_POST['person_type_id']);

            if ($_SESSION['role'] === 'COMUNITY') {
                $_SESSION['person_type_id'] = $personTypeId;
                $_SESSION['person_type'] = PersonType::find($personTypeId)->description;
    
                if (isset($_SESSION['person_type_id'])) {
                    header("Location: " . BASE_HEADER . "dashboard");
                    exit;
                }
            }
        }

        $_SESSION['message'] = "Debes seleccionar un tipo de persona.";
        $_SESSION['message_type'] = "danger";
        header("Location: " . BASE_HEADER . "select-person-type");
        exit;
    }

    public function selectRole()
    {
        if (!isset($_SESSION['user_id'])) {
            header("Location: " . BASE_HEADER);
            exit;
        }

        $roles = $_SESSION['available_roles'];
        
        require_once __DIR__ . '/../views/auth/select_role.php';
    }

    public function logout()
    {
        session_start();
        $_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();
        header("Location: " . BASE_HEADER);
        exit;
    }

    public function showForgotPasswordForm()
    {
        session_start();
        $personTypes = PersonType::getActives();
        include __DIR__ . '/../views/auth/forgot-password.php';
    }

    public function sendResetCode()
    {
        session_start();
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            
            $personType = strtoupper(trim($_POST['person_type'] ?? ''));
            $dni = trim($_POST['dni'] ?? '');
            $email = trim($_POST['email'] ?? '');
            $ruc = trim($_POST['ruc'] ?? '');

            if (!$personType || !$dni || !$email || ($personType === 'JURIDICA' && !$ruc)) {
                $_SESSION['message'] = "Complete todos los campos requeridos.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "auth/forgot-password");
                exit;
            }

            $user = $this->userRecoveryService->findUser($dni, $email, $ruc);

            if (!$user) {
                $_SESSION['message'] = "No se encontró un usuario con esos datos.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "auth/forgot-password");
                exit;
            }

            $this->passwordResetService->softDeleteAllByEmail($email);

            $token = $this->userRecoveryService->createPasswordReset($email);
            
            MailService::sendResetPasswordEmail($email, $token);

            $emailToShow = $email;

            require_once __DIR__ . '/../views/auth/reset-code-sent.php';
            exit;

        }
    }

    public function resendResetCode()
    {
        session_start();
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $email = trim($_POST['email'] ?? '');

            if (!$email || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
                $_SESSION['message'] = "Correo electrónico no válido.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "auth/forgot-password");
                exit;
            }

            $user = $this->userRecoveryService->findUserByEmail($email);
            if (!$user) {
                $_SESSION['message'] = "No se encontró un usuario con ese correo.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "auth/forgot-password");
                exit;
            }

            $this->passwordResetService->softDeleteAllByEmail($email);
            $token = $this->userRecoveryService->createPasswordReset($email);
            MailService::sendResetPasswordEmail($email, $token);

            $emailToShow = $email;
            $_SESSION['message'] = "Enlace reenviado coorectamente.";
            $_SESSION['message_type'] = "success";
            require_once __DIR__ . '/../views/auth/reset-code-sent.php';
            exit;
        }

        header("Location: " . BASE_HEADER . "auth/forgot-password");
        exit;
    }

    public function showResetPasswordForm()
    {
        session_start();
        $token = $_GET['token'] ?? '';

        if (!$token) {
            $_SESSION['message'] = "Token no válido.";
            $_SESSION['message_type'] = "danger";
            header("Location: " . BASE_HEADER . "auth/forgot-password");
            exit;
        }

        $reset = $this->passwordResetService->findValidToken($token);

        if (!$reset) {
            $_SESSION['message'] = "Este enlace ya expiró o no es válido.";
            $_SESSION['message_type'] = "danger";
            header("Location: " . BASE_HEADER . "auth/forgot-password");
            exit;
        }

        $email = $reset['email'];
        require_once __DIR__ . '/../views/auth/reset-password-form.php';
    }

    public function resetPassword()
    {
        session_start();
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $token = trim($_POST['token'] ?? '');
            $password = $_POST['password'] ?? '';
            $confirm = $_POST['confirm_password'] ?? '';

            if (!$token || !$password || !$confirm) {
                $_SESSION['message'] = "Completa todos los campos.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "auth/reset-password?token=" . urlencode($token));
                exit;
            }

            $errors = PasswordValidator::validate($password);

            if (!empty($errors)) {
                $_SESSION['message'] = implode("<br>", $errors);
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "auth/reset-password?token=" . urlencode($token));
                exit;
            }

            if ($password !== $confirm) {
                $_SESSION['message'] = "Las contraseñas no coinciden.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "auth/reset-password?token=" . urlencode($token));
                exit;
            }

            $reset = $this->passwordResetService->findValidToken($token);
            if (!$reset) {
                $_SESSION['message'] = "Este enlace ya no es válido.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "auth/forgot-password");
                exit;
            }

            $updated = $this->userRecoveryService->updatePassword($reset['email'], $password);

            if(!$updated)
            {
                $_SESSION['message'] = "No se pudo actualizar la contraseña.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "auth/forgot-password");
                exit;
            }
            
            $this->passwordResetService->markAsUsed($token);

            $_SESSION['message'] = "Contraseña actualizada correctamente.";
            $_SESSION['message_type'] = "success";
            header("Location: " . BASE_HEADER);
            exit;
        }
    }


}