<?php

require_once APP_ROOT . '/models/User.php';
require_once APP_ROOT . '/helpers/Mailer.php';

class AuthController
{
    public function loginForm(): void
    {
        if (Session::isLoggedIn()) {
            header('Location: ' . APP_URL . '/home');
            exit;
        }
        require APP_ROOT . '/views/auth/login.php';
    }

    public function login(): void
    {
        // Rate limiting check
        $clientIp = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
        if (!Security::rateLimitCheck("login_{$clientIp}", 5, 300)) {
            Session::flash('error', 'Too many login attempts. Please try again later.');
            Security::logSecurityEvent('login_rate_limit_exceeded', ['ip' => $clientIp]);
            header('Location: ' . APP_URL . '/login');
            exit;
        }

        if (!Session::verifyCsrfToken($_POST['csrf_token'] ?? '')) {
            Session::flash('error', 'Invalid request.');
            Security::logSecurityEvent('csrf_token_invalid', ['endpoint' => 'login']);
            header('Location: ' . APP_URL . '/login');
            exit;
        }

        // Verify reCAPTCHA if enabled
        $recaptchaToken = $_POST['recaptcha_token'] ?? '';
        if (!Recaptcha::verifyToken($recaptchaToken)) {
            Session::flash('error', Lang::get('recaptcha_error'));
            header('Location: ' . APP_URL . '/login');
            exit;
        }

        $username = trim($_POST['username'] ?? '');
        $password = $_POST['password'] ?? '';

        $userModel = new User();
        $user = $userModel->findByUsername($username);

        if ($user && password_verify($password, $user['password'])) {
            if ($user['status'] === 'pending') {
                Session::flash('error', Lang::get('account_pending'));
                header('Location: ' . APP_URL . '/login');
                exit;
            }
            if ($user['status'] === 'pending_verification') {
                Session::flash('error', Lang::get('account_pending_verification'));
                header('Location: ' . APP_URL . '/login');
                exit;
            }
            if ($user['status'] === 'rejected') {
                Session::flash('error', Lang::get('account_rejected'));
                header('Location: ' . APP_URL . '/login');
                exit;
            }
            
            // Regenerate session ID for security
            Session::regenerate();
            
            Session::set('user_id', $user['id']);
            Session::set('username', $user['username']);
            Session::set('display_name', $user['display_name'] ?? $user['username']);
            Session::set('role', $user['role'] ?? 'user');
            Session::set('avatar', $user['avatar'] ?? '');
            Session::set('default_view', $user['default_view'] ?? 'grid');
            Session::set('default_language', $user['default_language'] ?? 'en');
            Session::set('default_theme', $user['default_theme'] ?? 'system');
            Lang::setLocale($user['default_language'] ?? 'en');
            
            // Check if user has accepted cookies
            $hasAccepted = $userModel->hasAcceptedCookies($user['id']);
            
            if (!$hasAccepted) {
                Session::set('show_cookie_consent', 'true');
                header('Location: ' . APP_URL . '/home');
                exit;
            }
            
            header('Location: ' . APP_URL . '/home');
            exit;
        }

        Session::flash('error', Lang::get('login_error'));
        header('Location: ' . APP_URL . '/login');
        exit;
    }

    public function registerForm(): void
    {
        if (Session::isLoggedIn()) {
            header('Location: ' . APP_URL . '/home');
            exit;
        }
        require APP_ROOT . '/views/auth/register.php';
    }

    public function register(): void
    {
        // Rate limiting check
        $clientIp = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
        if (!Security::rateLimitCheck("register_{$clientIp}", 3, 600)) {
            Session::flash('error', 'Too many registration attempts. Please try again later.');
            Security::logSecurityEvent('register_rate_limit_exceeded', ['ip' => $clientIp]);
            header('Location: ' . APP_URL . '/register');
            exit;
        }

        if (!Session::verifyCsrfToken($_POST['csrf_token'] ?? '')) {
            Session::flash('error', 'Invalid request.');
            Security::logSecurityEvent('csrf_token_invalid', ['endpoint' => 'register']);
            header('Location: ' . APP_URL . '/register');
            exit;
        }

        // Verify reCAPTCHA if enabled
        $recaptchaToken = $_POST['recaptcha_token'] ?? '';
        if (!Recaptcha::verifyToken($recaptchaToken)) {
            Session::flash('error', Lang::get('recaptcha_error'));
            header('Location: ' . APP_URL . '/register');
            exit;
        }

        $username = trim($_POST['username'] ?? '');
        $email = trim($_POST['email'] ?? '');
        $password = $_POST['password'] ?? '';
        $confirmPassword = $_POST['confirm_password'] ?? '';

        $validator = new Validator();
        $validator->username('username', $username, Lang::get('username'))
                 ->email('email', $email, Lang::get('email'))
                 ->password('password', $password, Lang::get('password'));

        // Add email validation
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            Session::flash('error', Lang::get('email_invalid'));
            header('Location: ' . APP_URL . '/register');
            exit;
        }

        if ($validator->fails()) {
            Session::flash('error', $validator->firstError());
            header('Location: ' . APP_URL . '/register');
            exit;
        }

        if ($password !== $confirmPassword) {
            Session::flash('error', Lang::get('password_mismatch'));
            header('Location: ' . APP_URL . '/register');
            exit;
        }

        $userModel = new User();

        if ($userModel->findByUsername($username)) {
            Session::flash('error', Lang::get('username_taken'));
            header('Location: ' . APP_URL . '/register');
            exit;
        }

        if ($userModel->findByEmail($email)) {
            Session::flash('error', 'Email address is already registered.');
            header('Location: ' . APP_URL . '/register');
            exit;
        }

        require_once APP_ROOT . '/models/Setting.php';
        $settingModel = new Setting();
        $autoApprove = $settingModel->get('auto_approve_registrations') === '1';
        $emailVerification = $settingModel->get('email_verification_required') === '1';

        if ($emailVerification) {
            $status = 'pending_verification';
        } elseif ($autoApprove) {
            $status = 'approved';
        } else {
            $status = 'pending';
        }

        $userId = $userModel->create([
            'username'     => $username,
            'password'     => password_hash($password, PASSWORD_BCRYPT),
            'display_name' => $username,
            'email'        => $email,
            'role'         => 'user',
            'status'       => $status,
        ]);

        if ($emailVerification) {
            $token = bin2hex(random_bytes(32));
            $expires = date('Y-m-d H:i:s', strtotime('+24 hours'));
            $userModel->setEmailVerificationToken($userId, $token, $expires);

            $verifyLink = APP_URL . '/verify-email?token=' . $token;
            $emailSent = Mailer::sendEmailVerificationEmail($email, $username, $verifyLink);

            if ($emailSent) {
                Session::flash('success', Lang::get('registration_verify_email'));
            } else {
                Session::flash('error', Lang::get('email_verification_failed'));
            }
        } elseif ($autoApprove) {
            Session::flash('success', Lang::get('registration_approved'));
        } else {
            Session::flash('success', Lang::get('registration_pending'));
        }

        header('Location: ' . APP_URL . '/login');
        exit;
    }

    public function verifyEmail(): void
    {
        $token = $_GET['token'] ?? '';
        if (empty($token)) {
            Session::flash('error', Lang::get('email_verification_invalid'));
            header('Location: ' . APP_URL . '/login');
            exit;
        }

        $userModel = new User();
        $user = $userModel->findByEmailVerificationToken($token);

        if (!$user || (isset($user['email_verification_expires']) && strtotime($user['email_verification_expires']) < time())) {
            Session::flash('error', Lang::get('email_verification_invalid'));
            header('Location: ' . APP_URL . '/login');
            exit;
        }

        $userModel->verifyEmail($user['id']);

        Session::flash('success', Lang::get('email_verified_success'));
        header('Location: ' . APP_URL . '/login');
        exit;
    }

    public function logout(): void
    {
        Session::destroy();
        session_start();
        header('Location: ' . APP_URL . '/login');
        exit;
    }

    public function forgotPasswordForm(): void
    {
        if (Session::isLoggedIn()) {
            header('Location: ' . APP_URL . '/home');
            exit;
        }
        require APP_ROOT . '/views/auth/forgot_password.php';
    }

    public function forgotPassword(): void
    {
        if (!Session::verifyCsrfToken($_POST['csrf_token'] ?? '')) {
            Session::flash('error', 'Invalid request.');
            header('Location: ' . APP_URL . '/forgot-password');
            exit;
        }

        $email = trim($_POST['email'] ?? '');

        // Validate email
        if (empty($email)) {
            Session::flash('error', Lang::get('email_required'));
            header('Location: ' . APP_URL . '/forgot-password');
            exit;
        }

        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            Session::flash('error', Lang::get('email_invalid'));
            header('Location: ' . APP_URL . '/forgot-password');
            exit;
        }

        $userModel = new User();
        $user = $userModel->findByEmail($email);

        if (!$user) {
            Session::flash('error', Lang::get('email_not_found'));
            header('Location: ' . APP_URL . '/forgot-password');
            exit;
        }

        // Generate reset token
        $token = bin2hex(random_bytes(32));
        $expires = date('Y-m-d H:i:s', strtotime('+1 hour'));

        // Save token to database
        $userModel->setPasswordResetToken($user['id'], $token, $expires);

        // Send reset email (using Mailer helper)
        $resetLink = APP_URL . '/reset-password?token=' . $token;
        $emailSent = Mailer::sendPasswordResetEmail($email, $resetLink);

        if ($emailSent) {
            Session::flash('success', Lang::get('email_reset_sent'));
        } else {
            Session::flash('error', 'Failed to send reset email. Please try again.');
        }

        header('Location: ' . APP_URL . '/login');
        exit;
    }

    public function resetPasswordForm(): void
    {
        if (Session::isLoggedIn()) {
            header('Location: ' . APP_URL . '/home');
            exit;
        }

        $token = $_GET['token'] ?? '';
        if (empty($token)) {
            Session::flash('error', Lang::get('reset_link_invalid'));
            header('Location: ' . APP_URL . '/login');
            exit;
        }

        // Validate token
        $userModel = new User();
        $user = $userModel->findByResetToken($token);

        if (!$user || strtotime($user['password_reset_expires']) < time()) {
            Session::flash('error', Lang::get('reset_link_invalid'));
            header('Location: ' . APP_URL . '/login');
            exit;
        }

        require APP_ROOT . '/views/auth/reset_password.php';
    }

    public function resetPassword(): void
    {
        if (!Session::verifyCsrfToken($_POST['csrf_token'] ?? '')) {
            Session::flash('error', 'Invalid request.');
            header('Location: ' . APP_URL . '/login');
            exit;
        }

        $token = $_POST['token'] ?? '';
        $password = $_POST['password'] ?? '';
        $confirmPassword = $_POST['confirm_password'] ?? '';

        if (empty($token)) {
            Session::flash('error', Lang::get('reset_link_invalid'));
            header('Location: ' . APP_URL . '/login');
            exit;
        }

        // Validate password
        if (strlen($password) < 6) {
            Session::flash('error', 'Password must be at least 6 characters long.');
            header('Location: ' . APP_URL . '/reset-password?token=' . urlencode($token));
            exit;
        }

        if ($password !== $confirmPassword) {
            Session::flash('error', Lang::get('password_mismatch'));
            header('Location: ' . APP_URL . '/reset-password?token=' . urlencode($token));
            exit;
        }

        // Validate token and user
        $userModel = new User();
        $user = $userModel->findByResetToken($token);

        if (!$user || strtotime($user['password_reset_expires']) < time()) {
            Session::flash('error', Lang::get('reset_link_invalid'));
            header('Location: ' . APP_URL . '/login');
            exit;
        }

        // Update password and clear token
        $hashedPassword = password_hash($password, PASSWORD_BCRYPT);
        $userModel->updatePasswordAndClearToken($user['id'], $hashedPassword);

        Session::flash('success', Lang::get('password_reset_success'));
        header('Location: ' . APP_URL . '/login');
        exit;
    }

    public function handleCookieConsent(): void
    {
        if (!Session::isLoggedIn()) {
            http_response_code(401);
            echo json_encode(['success' => false, 'message' => 'Unauthorized']);
            exit;
        }

        if (!Session::verifyCsrfToken($_POST['csrf_token'] ?? '')) {
            http_response_code(403);
            echo json_encode(['success' => false, 'message' => 'Invalid request']);
            exit;
        }

        $action = $_POST['action'] ?? '';
        $userId = Session::getUserId();
        $userModel = new User();

        if ($action === 'accept') {
            $success = $userModel->acceptCookies($userId);
            if ($success) {
                Session::remove('show_cookie_consent');
                echo json_encode(['success' => true, 'redirect' => APP_URL . '/home']);
            } else {
                echo json_encode(['success' => false, 'message' => 'Failed to accept cookies']);
            }
        } elseif ($action === 'reject') {
            // Log out user and redirect to login
            Session::destroy();
            session_start();
            Session::flash('error', Lang::get('cookie_consent_rejected'));
            echo json_encode(['success' => true, 'redirect' => APP_URL . '/login']);
        } else {
            echo json_encode(['success' => false, 'message' => 'Invalid action']);
        }
        exit;
    }
}
