<?php

namespace App\Controllers;

use App\Models\PendingUser;
use App\Models\PersonType;
use App\Models\User;
use App\Models\UserComunity;
use App\Services\MailService;
use App\Services\PasswordValidator;
use App\Services\PendingUserService;
use App\Services\UserService;
use Exception;

class RegisterController extends BaseController
{
    protected PendingUserService $pendingUserService;
    protected UserService $userService;

    public function __construct() {
        if (session_status() === PHP_SESSION_NONE) {
            session_start();
        }

        $this->pendingUserService = new PendingUserService();
        $this->userService = new UserService();
    }

    public function registerStep1() 
    {
        include __DIR__ . '/../views/auth/register_step1.php';
    }

    public function handleRegisterStep1() {
        $email = trim($_POST['email']);

        if (!isset($_POST['checkbox1']) || !isset($_POST['checkbox2'])) {
            $_SESSION['message'] = "Debes aceptar ambas declaraciones para continuar con el registro.";
            $_SESSION['message_type'] = "danger";
            header("Location: " . BASE_HEADER . "auth/register");
            exit;
        }
    
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $_SESSION['message'] = "Error: El correo ingresado no es válido.";
            $_SESSION['message_type'] = "danger";
            header("Location: " . BASE_HEADER . "auth/register");
            exit;
        }
    
        $existingUser = UserComunity::findBy('email',$email);
        if ($existingUser && $existingUser->user_id !== null) {
            $_SESSION['message'] = "Error: El correo ingresado ya está registrado.";
            $_SESSION['message_type'] = "danger";
            header("Location: " . BASE_HEADER . "auth/register");
            exit;
        }

        $pending = $this->pendingUserService->findByEmail($email);

        if ($pending && !$pending->verified) {
            $pending->token = bin2hex(random_bytes(32));
            $pending->token_expires_at = date('Y-m-d H:i:s', strtotime('+1 hour'));
            $pending->save();

            MailService::sendVerificationEmail($email, $pending->token);

            $_SESSION['email_pending_verification'] = $email;
            $_SESSION['message'] = "Ya habías iniciado un registro. Te hemos reenviado un nuevo correo de verificación.";
            $_SESSION['message_type'] = "info";
            header("Location: " . BASE_HEADER . "auth/verify-sent");
            exit;
        }

        if (!$pending) {
            $token = bin2hex(random_bytes(32));
            $pendingUser = new PendingUser([
                'email' => $email,
                'token' => $token,
                'token_expires_at' => date('Y-m-d H:i:s', strtotime('+1 hour')),
                'verified' => 0
            ]);
            $pendingUser->save();

            MailService::sendVerificationEmail($email, $token);

            $_SESSION['email_pending_verification'] = $email;
            $_SESSION['message'] = "¡Revisa tu correo para continuar con el registro!";
            $_SESSION['message_type'] = "success";
            header("Location: " . BASE_HEADER . "auth/verify-sent");
            exit;
        }

        $_SESSION['message'] = "Este correo ya ha sido verificado. Inicia sesión o recupera tu contraseña si no puedes acceder.";
        $_SESSION['message_type'] = "danger";
        header("Location: " . BASE_HEADER . "auth/register");
        exit;
    }

    public function showVerificationNotice()
    {
        $email = $_SESSION['email_pending_verification'] ?? null;

        if (!$email) {
            $_SESSION['message'] = "Error: No hay una solicitud de verificación activa.";
            $_SESSION['message_type'] = "danger";
            header("Location: " . BASE_HEADER . "auth/register");
            exit;
        }

        include __DIR__ . '/../views/auth/verify_sent.php';
    }


    public function verifyEmail()
    {
        $token = $_GET['token'] ?? null;

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

        $pendingUser = $this->pendingUserService->findByToken($token);

        if (!$pendingUser) {
            $_SESSION['message'] = "Token inválido. Por favor vuelve a realizar tu registro ingresando tu correo electrónico.";
            $_SESSION['message_type'] = "danger";
            header("Location: " . BASE_HEADER . "auth/register");
            exit;
        }

        $currentDate = date('Y-m-d H:i:s');
        if ($pendingUser->token_expires_at < $currentDate) {
            $_SESSION['message'] = "El token ha expirado. Puedes solicitar uno nuevo desde el formulario.";
            $_SESSION['message_type'] = "warning";
            $_SESSION['email_pending_verification'] = $pendingUser->email;
            header("Location: " . BASE_HEADER . "auth/verify-sent");
            exit;
        }


        if ($pendingUser->verified) {
            $_SESSION['message'] = "Este correo ya ha sido verificado.";
            $_SESSION['message_type'] = "info";
            header("Location: " . BASE_HEADER . "auth/register");
            exit;
        }

        $_SESSION['email_pending_verification'] = $pendingUser->email;
        header("Location: " . BASE_HEADER . "auth/register-step2?email=" . urlencode($pendingUser->email));
        exit;
    }

    public function registerStep2()
    {
        $email = $_GET['email'] ?? null;

        if (!$email) {
            $_SESSION['message'] = "Correo no proporcionado.";
            $_SESSION['message_type'] = "danger";
            header("Location: " . BASE_HEADER . "auth/register");
            exit;
        }

        $pending = $this->pendingUserService->findByEmail($email);
        if (!$pending) {
            $_SESSION['message'] = "Correo no encontrado o aún no verificado.";
            $_SESSION['message_type'] = "danger";
            header("Location: " . BASE_HEADER . "auth/register");
            exit;
        }

        $personTypes = PersonType::getActives();

        include __DIR__ . '/../views/auth/register_step2.php';
    }

    public function handleRegisterStep2()
    {
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $email = $_POST['email'] ?? null;
            $username = trim($_POST['username'] ?? '');
            $password = trim($_POST['password'] ?? '');
            $confirmPassword = trim($_POST['confirm_password'] ?? '');

            if (!$email || !$username || !$password || !$confirmPassword) {
                $_SESSION['message'] = "Faltan campos obligatorios.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "auth/register-step2?email=" . urlencode($email));
                exit;
            }

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

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

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

            if (!isset($_POST['declaration'])) {
                $_SESSION['message'] = "Debes aceptar la declaración jurada para continuar.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "auth/register-step2?email=" . urlencode($email));
                exit;
            }
            

            // Validar que el email exista en pending_users
            $pendingUser = $this->pendingUserService->findByEmail($email);
            if (!$pendingUser) {
                $_SESSION['message'] = "Correo no registrado para verificación.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "auth/register");
                exit;
            }

            if ($pendingUser->verified) {
                $_SESSION['message'] = "Este correo ya ha sido verificado.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "auth/register");
                exit;
            }

            // Validar que el nombre de usuario no esté en uso
            if ($this->userService->findByUsername($username)) {
                $_SESSION['message'] = "El nombre de usuario ya está en uso.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "auth/register-step2?email=" . urlencode($email));
                exit;
            }

            try {
                $userService = new UserService();

                $data = $_POST;

                $userService->createComunityUser($data);

                // Marcamos el pending_user como verificado
                $pendingUser->verified = 1;
                $pendingUser->save();

                // Redirigimos al login con mensaje
                $_SESSION['message'] = "¡Registro exitoso! Ya puedes iniciar sesión.";
                $_SESSION['message_type'] = "success";
                header("Location: " . BASE_HEADER);
                exit;
            } catch (Exception $e) {
                $_SESSION['message'] = "Error al completar el registro: " . $e->getMessage();
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "auth/register-step2?email=" . urlencode($email));
                exit;
            }
        }
    }


    public function resendVerification()
    {
        $email = $_POST['email'] ?? null;

        if (!$email) {
            $_SESSION['message'] = "Correo no proporcionado.";
            $_SESSION['message_type'] = "danger";
            header("Location: " . BASE_HEADER . "auth/verify-sent");
            exit;
        }

        $pendingUser = $this->pendingUserService->findByEmail($email);

        if (!$pendingUser || $pendingUser->verified) {
            $_SESSION['message'] = "Este correo no necesita verificación o ya está registrado.";
            $_SESSION['message_type'] = "danger";
            header("Location: " . BASE_HEADER . "auth/register");
            exit;
        }

        // Generar nuevo token y actualizar expiración
        $pendingUser->token = bin2hex(random_bytes(32));
        $pendingUser->token_expires_at = date('Y-m-d H:i:s', strtotime('+1 hour'));
        $pendingUser->save();

        // Enviar nuevo correo
        MailService::sendVerificationEmail($pendingUser->email, $pendingUser->token);

        $_SESSION['message'] = "Se ha reenviado el enlace de verificación.";
        $_SESSION['message_type'] = "info";
        $_SESSION['email_pending_verification'] = $email;
        header("Location: " . BASE_HEADER . "auth/verify-sent");
        exit;
    }
}