<?php

declare(strict_types=1);

namespace App\Service;

use App\Entity\Ecole;
use App\Repository\EtudiantRepository;
use App\Repository\InscriptionRepository;

final class MatriculeGenerator
{
    public function __construct(
        private readonly InscriptionRepository $inscriptionRepository,
        private readonly EtudiantRepository $etudiantRepository,
    ) {
    }

    public function generateNumeroDossier(Ecole $ecole): string
    {
        $year = date('y');
        $prefix = 'DOS-'.$year.'-'.$this->schoolCode($ecole).'-';
        $next = $this->inscriptionRepository->countDossiersForYear($ecole, $year) + 1;

        do {
            $code = $prefix.str_pad((string) $next, 4, '0', STR_PAD_LEFT);
            ++$next;
        } while ($this->inscriptionRepository->findOneBy(['numeroDossier' => $code]) !== null);

        return $code;
    }

    public function generateMatriculeTemporaire(Ecole $ecole): string
    {
        $year = date('y');
        $prefix = 'TMP-'.$year.'-'.$this->matriculePrefix($ecole).'-';
        $next = $this->inscriptionRepository->countTemporaryForYear($ecole, $year) + 1;

        do {
            $code = $prefix.str_pad((string) $next, 4, '0', STR_PAD_LEFT);
            ++$next;
        } while (
            $this->inscriptionRepository->findOneBy(['matriculeTemporaire' => $code]) !== null
            || $this->etudiantRepository->findOneBy(['matriculeTemporaire' => $code]) !== null
        );

        return $code;
    }

    public function generateMatriculeDefinitif(Ecole $ecole): string
    {
        $year = date('y');
        $prefix = $this->matriculePrefix($ecole);
        $next = $ecole->getDernierNumeroMatricule() + 1;

        do {
            $code = $year.$prefix.str_pad((string) $next, 3, '0', STR_PAD_LEFT);
            ++$next;
        } while ($this->etudiantRepository->findOneBy(['matricule' => $code]) !== null);

        $ecole->setDernierNumeroMatricule($next - 1);

        return $code;
    }


    public function syncDernierNumeroFromMatricule(Ecole $ecole, ?string $matricule): void
    {
        $matricule = $matricule ? preg_replace('/\s+/', '', mb_strtoupper($matricule)) : null;
        if (!$matricule) {
            return;
        }

        $prefix = $this->matriculePrefix($ecole);
        if (!preg_match('/^\d{2}'.preg_quote($prefix, '/').'(\d+)$/', $matricule, $matches)) {
            return;
        }

        $numero = (int) $matches[1];
        if ($numero > $ecole->getDernierNumeroMatricule()) {
            $ecole->setDernierNumeroMatricule($numero);
        }
    }

    private function matriculePrefix(Ecole $ecole): string
    {
        $prefix = $ecole->getPrefixeMatricule() ?: $this->schoolCode($ecole);

        return preg_replace('/[^A-Z0-9]/', '', mb_strtoupper($prefix)) ?: 'SAL';
    }

    private function schoolCode(Ecole $ecole): string
    {
        $slug = $ecole->getSlug() ?: $ecole->getNom() ?: 'madrassa';

        return preg_replace('/[^A-Z0-9]/', '', mb_strtoupper($slug)) ?: 'MADRASSA';
    }
}
