<?php

declare(strict_types=1);

namespace App\Core;

use PDO;

/**
 * Auth
 *
 * Answers "who is logged in right now?" for the rest of the app.
 * Deliberately separate from the login FLOW (credential checking, rate
 * limiting, remember-me tokens — see App\Services\AuthService): this
 * class only cares about reading/writing the authenticated identity
 * once a login has already succeeded. AuthMiddleware and every
 * controller/model that needs "the current user" goes through here.
 *
 * The full user row is cached on the PHP request lifecycle (static
 * property) so calling Auth::user() ten times in one request costs one
 * query, not ten.
 */
final class Auth
{
    private static ?array $cachedUser = null;
    private static bool $resolved = false;

    public static function id(): ?int
    {
        $id = Session::get('user_id');

        return $id === null ? null : (int) $id;
    }

    public static function check(): bool
    {
        return self::id() !== null;
    }

    public static function guest(): bool
    {
        return !self::check();
    }

    /** Full user row (password_hash stripped) for the logged-in user, or null. */
    public static function user(): ?array
    {
        if (self::$resolved) {
            return self::$cachedUser;
        }

        self::$resolved = true;
        $id = self::id();

        if ($id === null) {
            return self::$cachedUser = null;
        }

        $stmt = Database::connection()->prepare(
            "SELECT u.*, r.slug AS role_slug, r.name AS role_name
             FROM users u
             LEFT JOIN roles r ON r.id = u.role_id
             WHERE u.id = :id AND u.deleted_at IS NULL AND u.status = 'active'
             LIMIT 1"
        );
        $stmt->execute(['id' => $id]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);

        if ($user === false) {
            // Session points at a user that's been deleted/suspended
            // since the cookie was issued — treat as logged out.
            Session::destroy();

            return self::$cachedUser = null;
        }

        unset($user['password_hash'], $user['two_factor_secret']);

        return self::$cachedUser = $user;
    }

    /** Business line slugs (e.g. ['homecare','janitorial']) this user is allowed to see. */
    public static function businessLineSlugs(): array
    {
        $id = self::id();
        if ($id === null) {
            return [];
        }

        static $cache = [];
        if (isset($cache[$id])) {
            return $cache[$id];
        }

        $stmt = Database::connection()->prepare(
            'SELECT bl.slug FROM user_business_lines ubl
             JOIN business_lines bl ON bl.id = ubl.business_line_id
             WHERE ubl.user_id = :id'
        );
        $stmt->execute(['id' => $id]);

        return $cache[$id] = $stmt->fetchAll(PDO::FETCH_COLUMN);
    }

    /** Called by AuthService after credentials + rate limits pass. Never call this directly from a controller. */
    public static function login(int $userId): void
    {
        Session::regenerate();
        Session::set('user_id', $userId);
        Session::set('logged_in_at', time());
        self::$resolved = false;
        self::$cachedUser = null;
    }

    public static function logout(): void
    {
        Session::destroy();
        self::$resolved = false;
        self::$cachedUser = null;
    }
}
