<?php

declare(strict_types=1);

namespace App\Scolarite\Domain\Model\Competency;

use App\Administration\Domain\Model\User\UserId;
use App\Scolarite\Domain\Event\ResultatCompetenceModifie;
use App\Scolarite\Domain\Event\ResultatCompetenceSaisi;
use App\Shared\Domain\AggregateRoot;
use App\Shared\Domain\Tenant\TenantId;
use DateTimeImmutable;

final class StudentCompetencyResult extends AggregateRoot
{
    public private(set) DateTimeImmutable $updatedAt;

    private function __construct(
        public private(set) StudentCompetencyResultId $id,
        public private(set) TenantId $tenantId,
        public private(set) CompetencyEvaluationId $competencyEvaluationId,
        public private(set) UserId $studentId,
        public private(set) string $levelCode,
        public private(set) DateTimeImmutable $createdAt,
    ) {
        $this->updatedAt = $createdAt;
    }

    public static function saisir(
        TenantId $tenantId,
        CompetencyEvaluationId $competencyEvaluationId,
        UserId $studentId,
        string $levelCode,
        DateTimeImmutable $now,
    ): self {
        $result = new self(
            id: StudentCompetencyResultId::generate(),
            tenantId: $tenantId,
            competencyEvaluationId: $competencyEvaluationId,
            studentId: $studentId,
            levelCode: $levelCode,
            createdAt: $now,
        );

        $result->recordEvent(new ResultatCompetenceSaisi(
            resultId: $result->id,
            competencyEvaluationId: (string) $competencyEvaluationId,
            studentId: (string) $studentId,
            levelCode: $levelCode,
            occurredOn: $now,
        ));

        return $result;
    }

    public function modifier(
        string $levelCode,
        DateTimeImmutable $now,
    ): void {
        if ($this->levelCode === $levelCode) {
            return;
        }

        $oldLevelCode = $this->levelCode;

        $this->levelCode = $levelCode;
        $this->updatedAt = $now;

        $this->recordEvent(new ResultatCompetenceModifie(
            resultId: $this->id,
            competencyEvaluationId: (string) $this->competencyEvaluationId,
            studentId: (string) $this->studentId,
            oldLevelCode: $oldLevelCode,
            newLevelCode: $levelCode,
            occurredOn: $now,
        ));
    }

    /**
     * @internal Pour usage Infrastructure uniquement
     */
    public static function reconstitute(
        StudentCompetencyResultId $id,
        TenantId $tenantId,
        CompetencyEvaluationId $competencyEvaluationId,
        UserId $studentId,
        string $levelCode,
        DateTimeImmutable $createdAt,
        DateTimeImmutable $updatedAt,
    ): self {
        $result = new self(
            id: $id,
            tenantId: $tenantId,
            competencyEvaluationId: $competencyEvaluationId,
            studentId: $studentId,
            levelCode: $levelCode,
            createdAt: $createdAt,
        );

        $result->updatedAt = $updatedAt;

        return $result;
    }
}
