<?php
namespace Thirty\controllers;

class AuthController {
    
    public static function showLogin() {
        // Si ya está logueado, redirigir al dashboard
        if (user()) {
            header('Location: ' . base_url('/dashboard'));
            exit;
        }
        
        $data = [
            'old_email' => $_SESSION['old_email'] ?? '',
            'error' => isset($_SESSION['flash']) && strpos($_SESSION['flash'], 'Credenciales') !== false
        ];
        unset($_SESSION['old_email']);
        
        view('auth/login', $data);
    }

    public static function showRegister() {
        // Si ya está logueado, redirigir al dashboard
        if (user()) {
            header('Location: ' . base_url('/dashboard'));
            exit;
        }
        
        // Limpiar datos antiguos si viene de un registro exitoso
        if (isset($_SESSION['register_success'])) {
            unset($_SESSION['old']);
            unset($_SESSION['register_success']);
        }
        
        view('auth/register');
    }

    public static function login() {
        verify_csrf();
        global $DB;
        
        // Rate limiting simple
        if (!self::simpleRateLimit('login_' . ($_SERVER['REMOTE_ADDR'] ?? ''), 5, 300)) {
            set_flash('Demasiados intentos. Intenta nuevamente en 5 minutos.');
            redirect(base_url('/login'));
        }

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

        // Validaciones básicas
        if ($email === '' || $password === '') {
            set_flash('Email y contraseña son obligatorios.');
            $_SESSION['old_email'] = $email;
            redirect(base_url('/login'));
        }

        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            set_flash('Formato de email inválido.');
            $_SESSION['old_email'] = $email;
            redirect(base_url('/login'));
        }

        // Buscar usuario
        try {
            $st = $DB->prepare('SELECT id, email, password_hash, nick, first_name, last_name, status, role FROM users WHERE email = ? LIMIT 1');
            $st->execute([$email]);
            $user = $st->fetch();
        } catch (\PDOException $e) {
            error_log("Login error: " . $e->getMessage());
            set_flash('Error del sistema. Intenta más tarde.');
            redirect(base_url('/login'));
        }

        // Verificar usuario y contraseña
        if (!$user || !password_verify($password, $user['password_hash'])) {
            set_flash('Credenciales inválidas.');
            $_SESSION['old_email'] = $email;
            redirect(base_url('/login'));
        }

        // Verificar que el usuario esté activo
        if ($user['status'] !== 'active') {
            set_flash('Tu cuenta está desactivada. Contacta con soporte.');
            redirect(base_url('/login'));
        }

        // Login exitoso - CORREGIDO
        $_SESSION['user'] = [
            'role' => $user['role'],
            'id' => $user['id'],
            'email' => $user['email'],
            'nick' => $user['nick'],
            'name' => $user['first_name'] . ' ' . $user['last_name'],
            'login_time' => time(),
            'ip' => $_SERVER['REMOTE_ADDR'] ?? '',
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? ''
        ];

        // Registrar último login
        try {
            $DB->prepare('UPDATE users SET last_login = NOW() WHERE id = ?')->execute([$user['id']]);
        } catch (\PDOException $e) {
            // Ignorar si falla
        }

        // Registrar evento de seguridad
        self::logSecurityEvent('successful_login', $_SERVER['REMOTE_ADDR'] ?? '', $user['id']);

        set_flash('¡Bienvenido a Nebusa!', 'success');
        redirect(base_url('/dashboard'));
    }

    public static function register() {
        verify_csrf();
        global $DB;

        // Guardar datos antiguos para repoblar el formulario
        $_SESSION['old'] = $_POST;

        // Rate limiting simple para registro
        if (!self::simpleRateLimit('register_' . ($_SERVER['REMOTE_ADDR'] ?? ''), 3, 3600)) {
            set_flash('Demasiados registros desde tu IP. Intenta más tarde.');
            redirect(base_url('/register'));
        }

        $first = trim($_POST['first_name'] ?? '');
        $last = trim($_POST['last_name'] ?? '');
        $nick = trim($_POST['nick'] ?? '');
        $province = $_POST['province_code'] ?? '';
        $municipality = $_POST['municipality_code'] ?? '';
        $email = trim($_POST['email'] ?? '');
        $email2 = trim($_POST['email2'] ?? '');
        $pass = $_POST['password'] ?? '';
        $pass2 = $_POST['password2'] ?? '';
        $dob = $_POST['dob'] ?? '';
        
        // Consentimientos legales
        $accept_terms = isset($_POST['accept_terms']);
        $accept_privacy = isset($_POST['accept_privacy']);
        $accept_cookies = isset($_POST['accept_cookies']);
        $commercial_comm = isset($_POST['commercial_comm']);

        // ==================== VALIDACIONES LEGALES ====================

        // Validar consentimientos obligatorios (RGPD)
        if (!$accept_terms) {
            set_flash('Debes aceptar los términos y condiciones.');
            redirect(base_url('/register'));
        }

        if (!$accept_privacy) {
            set_flash('Debes aceptar la política de privacidad para el tratamiento de tus datos según el RGPD.');
            redirect(base_url('/register'));
        }

        if (!$accept_cookies) {
            set_flash('Debes aceptar el uso de cookies necesarias para el funcionamiento del sitio.');
            redirect(base_url('/register'));
        }

        // Validar emails coincidentes
        if ($email !== $email2) {
            set_flash('Los correos no coinciden.');
            redirect(base_url('/register'));
        }

        // Validar contraseñas coincidentes
        if ($pass !== $pass2) {
            set_flash('Las contraseñas no coinciden.');
            redirect(base_url('/register'));
        }

        // Validar formato de email
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            set_flash('Email no válido.');
            redirect(base_url('/register'));
        }

        // Validar nombre de usuario
        if (strlen($nick) < 3) {
            set_flash('Nick demasiado corto (mínimo 3 caracteres).');
            redirect(base_url('/register'));
        }

        if (!preg_match('/^[A-Za-z0-9._]+$/', $nick)) {
            set_flash('El nick solo puede contener letras, números, puntos y guiones bajos.');
            redirect(base_url('/register'));
        }

        // Validar fortaleza de contraseña (LSSI)
        if (strlen($pass) < 8) {
            set_flash('La contraseña debe tener al menos 8 caracteres.');
            redirect(base_url('/register'));
        }

        if (!preg_match('/[A-Z]/', $pass) || !preg_match('/[a-z]/', $pass) || !preg_match('/[0-9]/', $pass)) {
            set_flash('La contraseña debe incluir mayúsculas, minúsculas y números.');
            redirect(base_url('/register'));
        }

        // Validar ubicación (SOLO provincia y municipio)
        if (empty($province) || empty($municipality)) {
            set_flash('Por favor, completa la información de provincia y municipio.');
            redirect(base_url('/register'));
        }

        // Validar código de invitación si está activo
        $invite = null;
        if (env('APP_INVITES', 'off') === 'on') {
            $icode = trim($_POST['invite_code'] ?? '');
            if ($icode === '') {
                set_flash('Falta el código de invitación.');
                redirect(base_url('/register'));
            }
            
            try {
                $chk = $DB->prepare('SELECT id, creator_user_id, uses, max_uses, status FROM invites WHERE code = ? LIMIT 1');
                $chk->execute([$icode]);
                $invite = $chk->fetch();
                
                if (!$invite || $invite['status'] !== 'active' || (int)$invite['uses'] >= (int)$invite['max_uses']) {
                    set_flash('Código de invitación no válido o agotado.');
                    redirect(base_url('/register'));
                }
            } catch (\PDOException $e) {
                set_flash('Error verificando invitación.');
                redirect(base_url('/register'));
            }
        }

        // Verificar email y nick únicos
        try {
            $st = $DB->prepare('SELECT COUNT(*) FROM users WHERE email = ? OR nick = ?');
            $st->execute([$email, $nick]);
            if ((int)$st->fetchColumn() > 0) {
                set_flash('Email o Nick ya en uso.');
                redirect(base_url('/register'));
            }
        } catch (\PDOException $e) {
            set_flash('Error verificando credenciales.');
            redirect(base_url('/register'));
        }

        // ==================== VALIDACIÓN DE EDAD (LOPDGDD) ====================
        $dob_dt = date_create_from_format('Y-m-d', $dob);
        if (!$dob_dt) {
            $dob_dt = date_create_from_format('d/m/Y', $dob);
        }
        
        if (!$dob_dt) {
            set_flash('Fecha de nacimiento inválida.');
            redirect(base_url('/register'));
        }
        
        // Validar edad mínima de 16 años (LOPDGDD)
        $age = (int)floor((time() - $dob_dt->getTimestamp()) / (365.25 * 24 * 3600));
        if ($age < 16) {
            set_flash('Debes tener al menos 16 años para registrarte según la LOPDGDD.');
            redirect(base_url('/register'));
        }

        // Validar edad máxima razonable
        if ($age > 120) {
            set_flash('Fecha de nacimiento no válida.');
            redirect(base_url('/register'));
        }

        // ==================== CREACIÓN DEL USUARIO ====================
        $hash = hash_password($pass);
        $DB->beginTransaction();
        
        try {
            // Insertar usuario
            $st = $DB->prepare('INSERT INTO users (email, password_hash, nick, first_name, last_name, dob, locale, tz, status) VALUES (?, ?, ?, ?, ?, ?, "es-ES", "Europe/Madrid", "active")');
            $st->execute([$email, $hash, $nick, $first, $last, $dob_dt->format('Y-m-d')]);
            
            $uid = (int)$DB->lastInsertId();
            
            // Crear perfil con consentimientos (SIN código postal)
            try {
                $consents = json_encode([
                    'terms_accepted_at' => date('Y-m-d H:i:s'),
                    'privacy_accepted_at' => date('Y-m-d H:i:s'),
                    'cookies_accepted_at' => date('Y-m-d H:i:s'),
                    'commercial_comm' => (bool)$commercial_comm,
                    'commercial_comm_accepted_at' => $commercial_comm ? date('Y-m-d H:i:s') : null
                ]);
                
                $DB->prepare('INSERT INTO profiles (user_id, bio, province_code, municipality_code, avatar_url, consents) VALUES (?, ?, ?, ?, NULL, ?)')
                   ->execute([$uid, '', $province, $municipality, $consents]);
            } catch (\PDOException $e) {
                // Si la tabla profiles no existe, continuar sin ella
                error_log("Profiles table might not exist: " . $e->getMessage());
            }
            
            // Actualizar invitación si existe
            if ($invite) {
                try {
                    $DB->prepare('UPDATE invites SET uses = uses + 1, used_by_user_id = ?, status = IF(uses + 1 >= max_uses, "used", "active") WHERE id = ?')
                       ->execute([$uid, $invite['id']]);
                } catch (\PDOException $e) {
                    // Continuar incluso si falla la actualización de invitación
                    error_log("Error updating invite: " . $e->getMessage());
                }
            }
            
            $DB->commit();
            
            // Limpiar datos antiguos y marcar éxito
            unset($_SESSION['old']);
            $_SESSION['register_success'] = true;
            
            // Registrar evento de seguridad
            self::logSecurityEvent('user_registered', $_SERVER['REMOTE_ADDR'] ?? '', $uid);
            
        } catch (\Throwable $e) {
            $DB->rollBack();
            error_log("Error creating user: " . $e->getMessage());
            set_flash('Error creando usuario. Intenta nuevamente.');
            redirect(base_url('/register'));
        }

        set_flash('Cuenta creada exitosamente. Ya puedes iniciar sesión.', 'success');
        redirect(base_url('/login'));
    }

    public static function logout() {
        // Registrar evento de seguridad
        if (isset($_SESSION['user']['id'])) {
            self::logSecurityEvent('user_logout', $_SERVER['REMOTE_ADDR'] ?? '', $_SESSION['user']['id']);
        }
        
        // Limpiar sesión
        $_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();
        set_flash('Has cerrado sesión correctamente.', 'success');
        redirect(base_url('/'));
    }

    // Rate limiting simple usando sesiones
    private static function simpleRateLimit($key, $max_attempts, $time_window) {
        $now = time();
        $attempts = $_SESSION['rate_limits'][$key] ?? [];
        
        // Limpiar intentos antiguos
        $attempts = array_filter($attempts, function($time) use ($now, $time_window) {
            return ($now - $time) < $time_window;
        });
        
        if (count($attempts) >= $max_attempts) {
            return false;
        }
        
        // Registrar nuevo intento
        $attempts[] = $now;
        $_SESSION['rate_limits'][$key] = $attempts;
        
        return true;
    }

    // Registrar eventos de seguridad - CORREGIDA PARA PHP 8+
    private static function logSecurityEvent($eventType, $ipAddress, $userId = null, $details = null) {
        global $DB;
        
        try {
            $stmt = $DB->prepare('
                INSERT INTO security_events (user_id, event_type, ip_address, user_agent, details) 
                VALUES (?, ?, ?, ?, ?)
            ');
            
            $stmt->execute([
                $userId,
                $eventType,
                $ipAddress,
                $_SERVER['HTTP_USER_AGENT'] ?? '',
                $details ? json_encode($details) : null
            ]);
            
        } catch (\Exception $e) {
            error_log("Error logging security event: " . $e->getMessage());
        }
    }

    // Verificar si el usuario necesita verificación de edad
    public static function needsAgeVerification($userId) {
        global $DB;
        
        try {
            $stmt = $DB->prepare('SELECT dob FROM users WHERE id = ?');
            $stmt->execute([$userId]);
            $user = $stmt->fetch();
            
            if (!$user || !$user['dob']) {
                return true;
            }
            
            $dob = new \DateTime($user['dob']);
            $now = new \DateTime();
            $age = $now->diff($dob)->y;
            
            return $age < 16;
            
        } catch (\Exception $e) {
            error_log("Error checking age verification: " . $e->getMessage());
            return true;
        }
    }

    // Obtener consentimientos del usuario
    public static function getUserConsents($userId) {
        global $DB;
        
        try {
            $stmt = $DB->prepare('SELECT consents FROM profiles WHERE user_id = ?');
            $stmt->execute([$userId]);
            $profile = $stmt->fetch();
            
            if ($profile && $profile['consents']) {
                return json_decode($profile['consents'], true);
            }
            
        } catch (\Exception $e) {
            error_log("Error getting user consents: " . $e->getMessage());
        }
        
        return [
            'terms_accepted_at' => null,
            'privacy_accepted_at' => null,
            'cookies_accepted_at' => null,
            'commercial_comm' => false,
            'commercial_comm_accepted_at' => null
        ];
    }
}