<?php
require_once __DIR__ . '/../Core.php';
require_once __DIR__ . '/../models/User.php';
require_once __DIR__ . '/../models/PasswordReset.php';
require_once __DIR__ . '/../models/LoginHistory.php';
require_once __DIR__ . '/../services.php';

class AuthController extends Controller
{
    public function login(): void
    {
        $this->view('auth/login', [], 'auth');
    }

    public function authenticate(): void
    {
        verify_csrf();
        $user = (new User())->verify(trim($_POST['email'] ?? ''), $_POST['password'] ?? '');
        if (!$user || !(int)$user['is_active']) {
            (new LoginHistory())->record($user['id'] ?? null, $email = trim($_POST['email'] ?? ''), 'failed', 'Invalid credentials');
            flash('error', 'Invalid email or password.');
            redirect('auth/login');
        }
        start_session();
        if (!empty($user['two_factor_enabled']) && !empty($user['two_factor_secret'])) {
            $_SESSION['pending_2fa_user_id'] = (int)$user['id'];
            $_SESSION['pending_2fa_started_at'] = time();
            redirect('auth/twoFactor');
        }
        $_SESSION['user'] = [
            'id' => $user['id'],
            'name' => $user['name'],
            'email' => $user['email'],
            'role' => $user['role'],
        ];
        (new LoginHistory())->record((int)$user['id'], $user['email'], 'success', 'Password authentication succeeded');
        flash('success', 'Welcome back, ' . $user['name'] . '.');
        redirect('dashboard/index');
    }

    public function twoFactor(): void
    {
        start_session();
        if (empty($_SESSION['pending_2fa_user_id'])) {
            redirect('auth/login');
        }
        $this->view('auth/two_factor', [], 'auth');
    }

    public function verifyTwoFactor(): void
    {
        verify_csrf();
        start_session();
        $userId = (int)($_SESSION['pending_2fa_user_id'] ?? 0);
        if (!$userId || (time() - (int)($_SESSION['pending_2fa_started_at'] ?? 0)) > 600) {
            unset($_SESSION['pending_2fa_user_id'], $_SESSION['pending_2fa_started_at']);
            flash('error', 'Two-factor session expired. Please sign in again.');
            redirect('auth/login');
        }
        $user = (new User())->find($userId);
        $code = trim($_POST['code'] ?? '');
        if (!$user || empty($user['two_factor_secret']) || !verify_totp_code($user['two_factor_secret'], $code)) {
            flash('error', 'Invalid authentication code.');
            redirect('auth/twoFactor');
        }
        $_SESSION['user'] = [
            'id' => $user['id'],
            'name' => $user['name'],
            'email' => $user['email'],
            'role' => $user['role'],
        ];
        unset($_SESSION['pending_2fa_user_id'], $_SESSION['pending_2fa_started_at']);
        (new LoginHistory())->record((int)$user['id'], $user['email'], 'success', 'Two-factor authentication complete');
        flash('success', 'Two-factor authentication complete.');
        redirect('dashboard/index');
    }

    public function forgotPassword(): void
    {
        $this->view('auth/forgot_password', [], 'auth');
    }

    public function sendResetLink(): void
    {
        verify_csrf();
        $email = trim($_POST['email'] ?? '');
        $user = (new User())->findByEmail($email);
        if ($user) {
            $token = (new PasswordReset())->createToken((int)$user['id'], $user['email']);
            $resetUrl = full_url('index.php?route=auth/resetPassword&token=' . urlencode($token));
            try {
                (new EmailService())->sendPasswordReset($user['email'], $user['name'], $resetUrl);
            } catch (Throwable $e) {
                flash('error', 'Reset token generated, but email delivery failed: ' . $e->getMessage());
                redirect('auth/forgotPassword');
            }
        }
        flash('success', 'If that account exists, a reset link has been sent.');
        redirect('auth/login');
    }

    public function resetPassword(): void
    {
        $token = $_GET['token'] ?? '';
        $record = $token ? (new PasswordReset())->findValid($token) : null;
        $this->view('auth/reset_password', ['token' => $token, 'valid' => (bool)$record], 'auth');
    }

    public function updatePassword(): void
    {
        verify_csrf();
        $token = $_POST['token'] ?? '';
        $password = $_POST['password'] ?? '';
        $confirm = $_POST['password_confirm'] ?? '';
        $reset = $token ? (new PasswordReset())->findValid($token) : null;
        if (!$reset) {
            flash('error', 'This reset link is invalid or expired.');
            redirect('auth/forgotPassword');
        }
        if (strlen($password) < 8) {
            flash('error', 'Password must be at least 8 characters.');
            redirect_url('index.php?route=auth/resetPassword&token=' . urlencode($token));
        }
        if ($password !== $confirm) {
            flash('error', 'Passwords do not match.');
            redirect_url('index.php?route=auth/resetPassword&token=' . urlencode($token));
        }
        (new User())->updatePassword((int)$reset['user_id'], $password);
        (new PasswordReset())->markUsed((int)$reset['id']);
        flash('success', 'Password updated. You can sign in now.');
        redirect('auth/login');
    }

    public function logout(): void
    {
        start_session();
        session_destroy();
        header('Location: index.php?route=auth/login');
        exit;
    }
}
