<?php

declare(strict_types=1);

namespace App\SuperAdmin\Domain\Model\SuperAdmin;

use App\Shared\Domain\AggregateRoot;
use App\SuperAdmin\Domain\Event\SuperAdminCree;
use App\SuperAdmin\Domain\Event\SuperAdminDesactive;
use App\SuperAdmin\Domain\Exception\SuperAdminDejaActifException;
use App\SuperAdmin\Domain\Exception\SuperAdminNonActifException;
use DateTimeImmutable;

/**
 * Aggregate Root for Super Admin — lives in the master database, not per-tenant.
 *
 * A Super Admin can manage all establishments and switch between tenant contexts.
 * Authentication is separate from regular users (different user provider, different table).
 */
final class SuperAdmin extends AggregateRoot
{
    public private(set) ?DateTimeImmutable $lastLoginAt = null;

    private function __construct(
        public private(set) SuperAdminId $id,
        public private(set) string $email,
        public private(set) string $hashedPassword,
        public private(set) string $firstName,
        public private(set) string $lastName,
        public private(set) SuperAdminStatus $status,
        public private(set) DateTimeImmutable $createdAt,
    ) {
    }

    public static function creer(
        string $email,
        string $hashedPassword,
        string $firstName,
        string $lastName,
        DateTimeImmutable $createdAt,
    ): self {
        $superAdmin = new self(
            id: SuperAdminId::generate(),
            email: $email,
            hashedPassword: $hashedPassword,
            firstName: $firstName,
            lastName: $lastName,
            status: SuperAdminStatus::ACTIF,
            createdAt: $createdAt,
        );

        $superAdmin->recordEvent(new SuperAdminCree(
            superAdminId: $superAdmin->id,
            email: $superAdmin->email,
            occurredOn: $createdAt,
        ));

        return $superAdmin;
    }

    public function enregistrerConnexion(DateTimeImmutable $at): void
    {
        if ($this->status !== SuperAdminStatus::ACTIF) {
            throw SuperAdminNonActifException::pourConnexion($this->id);
        }

        $this->lastLoginAt = $at;
    }

    public function desactiver(DateTimeImmutable $at): void
    {
        if ($this->status !== SuperAdminStatus::ACTIF) {
            throw SuperAdminNonActifException::pourDesactivation($this->id);
        }

        $this->status = SuperAdminStatus::INACTIF;

        $this->recordEvent(new SuperAdminDesactive(
            superAdminId: $this->id,
            occurredOn: $at,
        ));
    }

    public function reactiver(DateTimeImmutable $at): void
    {
        if ($this->status === SuperAdminStatus::ACTIF) {
            throw SuperAdminDejaActifException::pourReactivation($this->id);
        }

        $this->status = SuperAdminStatus::ACTIF;
    }

    public function peutSeConnecter(): bool
    {
        return $this->status === SuperAdminStatus::ACTIF;
    }

    /**
     * @internal For Infrastructure use only
     */
    public static function reconstitute(
        SuperAdminId $id,
        string $email,
        string $hashedPassword,
        string $firstName,
        string $lastName,
        SuperAdminStatus $status,
        DateTimeImmutable $createdAt,
        ?DateTimeImmutable $lastLoginAt = null,
    ): self {
        $superAdmin = new self(
            id: $id,
            email: $email,
            hashedPassword: $hashedPassword,
            firstName: $firstName,
            lastName: $lastName,
            status: $status,
            createdAt: $createdAt,
        );

        $superAdmin->lastLoginAt = $lastLoginAt;

        return $superAdmin;
    }
}
