<?php
declare(strict_types=1);

namespace App\Core;

use App\Models\CustomerUser;
use App\Models\Tenant;
use App\Services\PortalAccess;
use App\Services\Timezone;

final class Auth
{
    private static ?self $instance = null;
    private ?array $user = null;
    private ?array $tenant = null;
    private ?array $account = null;

    private function __construct()
    {
        $userId = Session::get('customer_id');
        if (!$userId) {
            return;
        }
        $this->user = CustomerUser::findActive((int) $userId);
        if (!$this->user) {
            $this->logout();
            return;
        }
        $this->tenant = Session::get('tenant');
        $this->account = Session::get('account');
        $tenantId = (int) Session::get('tenant_id');
        if ($tenantId) {
            $fresh = Tenant::find($tenantId);
            if ($fresh) {
                $this->tenant = $fresh;
                Session::set('tenant', $fresh);
            }
        }
        if (!$this->tenant || !$this->account) {
            $this->logout();
            return;
        }
        Timezone::apply($this->tenant['timezone'] ?? null);
    }

    public static function instance(): self
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function check(): bool
    {
        return $this->user !== null && $this->account !== null;
    }

    public function user(): ?array
    {
        return $this->user;
    }

    public function id(): ?int
    {
        return $this->user ? (int) $this->user['id'] : null;
    }

    public function tenant(): ?array
    {
        return $this->tenant;
    }

    public function tenantId(): ?int
    {
        return $this->tenant ? (int) $this->tenant['id'] : null;
    }

    public function account(): ?array
    {
        return $this->account;
    }

    public function accountId(): ?int
    {
        return $this->account ? (int) $this->account['id'] : null;
    }

    public function canSee(string $page): bool
    {
        if (!$this->check()) {
            return false;
        }
        return PortalAccess::allows($page, $this->user, $this->tenant);
    }

    public function login(array $user, array $tenant, array $account): void
    {
        Session::regenerate();
        Session::set('customer_id', (int) $user['id']);
        Session::set('tenant_id', (int) $tenant['id']);
        Session::set('tenant', $tenant);
        Session::set('account', $account);
        Csrf::token();
        $this->user = $user;
        $this->tenant = $tenant;
        $this->account = $account;
        Timezone::apply($tenant['timezone'] ?? null);
        self::$instance = $this;
    }

    public function logout(): void
    {
        Session::destroy();
        $this->user = null;
        $this->tenant = null;
        $this->account = null;
        Timezone::apply(null);
        self::$instance = new self();
    }
}
