<?php

declare(strict_types=1);

namespace App\Services;

use App\Models\LoginResult;
use App\Models\User;

/**
 * Karvi Partner API authentication — session stores the full API login response.
 */
final class AuthService
{
    private const SESSION_KEY = 'admin_api';
    private const SESSION_RESPONSE_KEY = 'admin_api_response';

    public function __construct(
        private readonly ApiService $api,
    ) {
    }

    public function startSession(): void
    {
        if (function_exists('auth_start')) {
            auth_start();
            return;
        }

        if (session_status() === PHP_SESSION_NONE) {
            @session_start();
        }
    }

    public function login(string $email, string $password): LoginResult
    {
        $this->startSession();
        $this->clearError();

        $email = trim($email);
        if ($email === '' || $password === '') {
            $message = function_exists('__') ? __('login_error') : 'Email and password are required.';
            $this->setError($message);

            return LoginResult::fail($message);
        }

        $response = $this->api->login($email, $password);

        if (!$response['success'] || !is_array($response['data'])) {
            $message = (string)($response['message'] ?? 'Login failed.');
            $this->setError($message);

            return LoginResult::fail($message, $response['data'], (int)$response['http_status']);
        }

        $data = $response['data'];

        if (empty($data['success']) || empty($data['token'])) {
            $message = (string)($data['message'] ?? 'Login API did not return an access token.');
            $this->setError($message);

            return LoginResult::fail($message, $data, (int)$response['http_status']);
        }

        $user = User::fromApiResponse($data);
        $this->storeUser($user, $data);

        return LoginResult::ok(
            $user,
            (string)($data['message'] ?? 'Login successful.'),
            $data,
            (int)$response['http_status']
        );
    }

    /** @param array<string,mixed> $apiResponse Complete login API response body. */
    public function storeUser(User $user, array $apiResponse): void
    {
        $this->startSession();

        $_SESSION['admin_logged_in'] = true;
        $_SESSION[self::SESSION_KEY] = $user->toSessionArray();
        $_SESSION[self::SESSION_RESPONSE_KEY] = $apiResponse;
        $_SESSION['admin_username'] = $user->loginId !== '' ? $user->loginId : ($user->email ?? '');
        unset($_SESSION['auth_last_error']);

        session_regenerate_id(true);
    }

    public function user(): ?User
    {
        $this->startSession();
        $data = $_SESSION[self::SESSION_KEY] ?? null;

        return is_array($data) ? User::fromSessionArray($data) : null;
    }

    /** @return array<string,mixed>|null */
    public function apiResponse(): ?array
    {
        $this->startSession();
        $data = $_SESSION[self::SESSION_RESPONSE_KEY] ?? null;

        return is_array($data) ? $data : null;
    }

    public function token(): ?string
    {
        $user = $this->user();

        return $user?->token;
    }

    public function isAuthenticated(): bool
    {
        return $this->token() !== null;
    }

    public function logout(): void
    {
        $this->startSession();
        $_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();
    }

    public function lastError(): string
    {
        $this->startSession();

        return (string)($_SESSION['auth_last_error'] ?? '');
    }

    public function setError(string $message): void
    {
        $this->startSession();
        $_SESSION['auth_last_error'] = $message;
    }

    public function clearError(): void
    {
        $this->startSession();
        unset($_SESSION['auth_last_error']);
    }
}
