<?php

namespace App;

use App\Database;
use PDO;

class Auth {
    public static function init(): void {
        if (session_status() === PHP_SESSION_NONE) session_start();
    }

    /**
     * Attempt login by username or email. Returns:
     *  - 'success' on success
     *  - 'inactive' if user exists but status != 'active'
     *  - false on credential failure
     */
    public static function attempt(string $identifier, string $password): string|false {
        self::init();
        $pdo = Database::getConnection();
        $stmt = $pdo->prepare('SELECT u.*, r.name AS role_name FROM users u LEFT JOIN roles r ON u.role_id = r.id WHERE u.email = :id OR u.username = :id LIMIT 1');
        $stmt->execute([':id' => $identifier]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$user) {
            self::logEvent($identifier, 'login_failed', 'auth', 'user_not_found');
            return false;
        }

        $hash = $user['password_hash'] ?? $user['password'] ?? '';
        if (!password_verify($password, $hash)) {
            self::logEvent($user['email'] ?? $identifier, 'login_failed', 'auth', 'bad_password');
            return false;
        }

        if (($user['status'] ?? 'active') !== 'active') {
            self::logEvent($user['email'] ?? $identifier, 'login_blocked', 'auth', 'inactive_user');
            return 'inactive';
        }

        $_SESSION['user_id'] = (int)$user['id'];
        // Log login event
        self::logEvent($user['email'] ?? $identifier, 'login_success', 'auth', 'user_authenticated');
        return 'success';
    }

    /**
     * Log an event to system_logs table
     */
    public static function logEvent(string $user, string $event, ?string $module = null, ?string $details = null): void {
        try {
            $pdo = Database::getConnection();
            $ip = $_SERVER['REMOTE_ADDR'] ?? null;
            $stmt = $pdo->prepare('INSERT INTO system_logs (user, event, module, details, ip) VALUES (:user, :event, :module, :details, :ip)');
            $stmt->execute([
                ':user' => $user,
                ':event' => $event,
                ':module' => $module,
                ':details' => $details,
                ':ip' => $ip
            ]);
        } catch (\Throwable $e) {
            // fail silently
        }
    }

    public static function register(string $name, string $email, string $password, string $role = 'user'): bool {
        self::init();
        $pdo = Database::getConnection();

        // Find role id
        $stmt = $pdo->prepare('SELECT id FROM roles WHERE name = :name LIMIT 1');
        $stmt->execute([':name' => $role]);
        $roleRow = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$roleRow) return false;

        $stmt = $pdo->prepare('INSERT INTO users (name,email,password,role_id) VALUES (:name,:email,:password,:role_id)');
        try {
            $stmt->execute([
                ':name' => $name,
                ':email' => $email,
                ':password' => password_hash($password, PASSWORD_DEFAULT),
                ':role_id' => $roleRow['id']
            ]);
            $_SESSION['user_id'] = (int)$pdo->lastInsertId();
            return true;
        } catch (\PDOException $e) {
            return false;
        }
    }

    public static function user(): ?array {
        self::init();
        if (empty($_SESSION['user_id'])) return null;
        $pdo = Database::getConnection();
        $stmt = $pdo->prepare('SELECT u.*, r.name as role_name FROM users u JOIN roles r ON u.role_id = r.id WHERE u.id = :id LIMIT 1');
        $stmt->execute([':id' => $_SESSION['user_id']]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);
        return $user ?: null;
    }

    public static function logout(): void {
        self::init();
        unset($_SESSION['user_id']);
        session_regenerate_id(true);
    }

    public static function requireRole(array|string $roles): void {
        $user = self::user();
        if (!$user) {
            header('Location: /login.php');
            exit;
        }
        if (is_string($roles)) $roles = [$roles];
        if (!in_array($user['role_name'], $roles, true)) {
            http_response_code(403);
            echo "403 Forbidden - insufficient permissions";
            exit;
        }
    }
}
