<?php

declare(strict_types=1);

namespace Instinctor\Core;


if (!defined('ABSPATH')) exit;
use Instinctor\Core\Auth\DriverInterface;
use Instinctor\Core\Auth\WordPressDriver;
use Instinctor\Core\Auth\StandaloneDriver;

/**
 * Auth — static facade over the active authentication driver.
 *
 * Driver selection:
 *   INSTINCTOR_ENV = 'wordpress'   → WordPressDriver  (default)
 *   INSTINCTOR_ENV = 'standalone'  → StandaloneDriver (stub until M11)
 *
 * Usage:
 *   if (!Auth::can('manage_options')) { wp_die(); }
 *   $userId = Auth::userId();
 *   if (!Auth::check()) { return; }
 */
class Auth
{
    private static ?DriverInterface $driver = null;

    public static function driver(): DriverInterface
    {
        if (self::$driver === null) {
            self::$driver = self::makeDriver();
        }
        return self::$driver;
    }

    public static function setDriver(DriverInterface $driver): void
    {
        self::$driver = $driver;
    }

    private static function makeDriver(): DriverInterface
    {
        $env = defined('INSTINCTOR_ENV') ? INSTINCTOR_ENV : 'wordpress';
        return match ($env) {
            'standalone' => new StandaloneDriver(),
            default      => new WordPressDriver(),
        };
    }

    // -------------------------------------------------------------------------
    // Static API
    // -------------------------------------------------------------------------

    /** Current authenticated user object, or null. */
    public static function user(): ?object
    {
        return self::driver()->user();
    }

    /** Current user ID, or 0 if not logged in. */
    public static function userId(): int
    {
        return self::driver()->userId();
    }

    /** Whether there is an authenticated user. */
    public static function check(): bool
    {
        return self::driver()->check();
    }

    /** Whether the current user has a given capability. */
    public static function can(string $capability, mixed ...$args): bool
    {
        return self::driver()->can($capability, ...$args);
    }

    /** Whether the current user is an admin (manage_options). */
    public static function isAdmin(): bool
    {
        return self::driver()->isAdmin();
    }

    /** Attempt login. Returns true on success. */
    public static function login(string $email, string $password, bool $remember = false): bool
    {
        return self::driver()->login($email, $password, $remember);
    }

    /**
     * Log in a user by ID without checking password — used by SSO (token already
     * verified upstream). Returns true on success. Drivers must implement loginAs().
     *
     * @since 2.0.778
     */
    public static function loginAs(int $userId, bool $remember = false): bool
    {
        if ($userId <= 0) return false;
        $driver = self::driver();
        if (method_exists($driver, 'loginAs')) {
            return (bool) $driver->loginAs($userId, $remember);
        }
        return false;
    }

    /**
     * Attempt login and return user array on success, null on failure.
     * Used by LoginController (standalone) — returns the user data needed to
     * set up a session cookie.
     *
     * @return array{id:int,email:string,display_name:string,role:string}|null
     */
    public static function attempt(string $email, string $password): ?array
    {
        if (method_exists(self::driver(), 'attempt')) {
            return self::driver()->attempt($email, $password);
        }

        // Fallback: use existing login() and then return current user
        if (self::driver()->login($email, $password)) {
            $user = self::user();
            if ($user) {
                return [
                    'id'           => self::userId(),
                    'email'        => $user->user_email ?? $email,
                    'display_name' => $user->display_name ?? $email,
                    'role'         => 'administrator',
                ];
            }
        }

        return null;
    }

    /**
     * Validate a session token and bootstrap the Auth context for this request.
     * Used by AdminRouter cookie-based auth check (standalone).
     * On WordPress, always returns true — WP handles session via its own cookie.
     */
    public static function checkToken(string $token): bool
    {
        if (method_exists(self::driver(), 'checkToken')) {
            return self::driver()->checkToken($token);
        }

        // WordPress: session handled by WP cookies — treat any call as valid
        // (AdminRouter::isAuthenticated() is only called on standalone)
        return self::check();
    }

    /** Log out the current user. */
    public static function logout(): void
    {
        self::driver()->logout();
    }
}
