<?php

declare(strict_types=1);

namespace App\Entity;

use App\Repository\EcoleRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;

#[ORM\Entity(repositoryClass: EcoleRepository::class)]
#[ORM\Table(name: 'ecoles')]
#[ORM\HasLifecycleCallbacks]
#[UniqueEntity(fields: ['slug'], message: 'Ce slug est déjà utilisé.')]
#[UniqueEntity(fields: ['sousDomaine'], message: 'Ce sous-domaine est déjà utilisé.')]
class Ecole
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\ManyToOne(inversedBy: 'ecoles')]
    #[ORM\JoinColumn(onDelete: 'SET NULL')]
    private ?Theme $themePublic = null;

    #[ORM\Column(length: 180)]
    #[Assert\NotBlank(message: 'Le nom de la madrassa est obligatoire.')]
    #[Assert\Length(max: 180)]
    private ?string $nom = null;

    #[ORM\Column(length: 120, unique: true)]
    #[Assert\NotBlank(message: 'Le slug est obligatoire.')]
    #[Assert\Regex(pattern: '/^[a-z0-9-]+$/', message: 'Utilisez uniquement des lettres minuscules, chiffres et tirets.')]
    #[Assert\Length(max: 120)]
    private ?string $slug = null;

    #[ORM\Column(length: 120, unique: true)]
    #[Assert\NotBlank(message: 'Le sous-domaine est obligatoire.')]
    #[Assert\Regex(pattern: '/^[a-z0-9-]+$/', message: 'Utilisez uniquement des lettres minuscules, chiffres et tirets.')]
    #[Assert\Length(max: 120)]
    private ?string $sousDomaine = null;

    #[ORM\Column(length: 12)]
    #[Assert\NotBlank(message: 'Le préfixe matricule est obligatoire.')]
    #[Assert\Length(max: 12)]
    private ?string $prefixeMatricule = null;

    #[ORM\Column(options: ['default' => 0])]
    #[Assert\PositiveOrZero]
    private int $dernierNumeroMatricule = 0;

    #[ORM\Column(length: 255, nullable: true)]
    #[Assert\Length(max: 255)]
    private ?string $logo = null;

    #[ORM\Column(length: 255, nullable: true)]
    #[Assert\Length(max: 255)]
    private ?string $favicon = null;

    #[ORM\Column(length: 255, nullable: true)]
    #[Assert\Length(max: 255)]
    private ?string $heroImage = null;

    #[ORM\Column(length: 255, nullable: true)]
    #[Assert\Length(max: 255)]
    private ?string $presentationImage1 = null;

    #[ORM\Column(length: 255, nullable: true)]
    #[Assert\Length(max: 255)]
    private ?string $presentationImage2 = null;

    #[ORM\Column(length: 255, nullable: true)]
    #[Assert\Length(max: 255)]
    private ?string $presentationImage3 = null;

    #[ORM\Column(length: 255, nullable: true)]
    #[Assert\Length(max: 255)]
    private ?string $imageSignatureAdministration = null;

    #[ORM\Column(length: 255, nullable: true)]
    #[Assert\Length(max: 255)]
    private ?string $imageCachetAdministration = null;

    #[ORM\Column(type: Types::TEXT, nullable: true)]
    private ?string $description = null;

    #[ORM\Column(length: 255, nullable: true)]
    #[Assert\Length(max: 255)]
    private ?string $slogan = null;

    #[ORM\Column(length: 180, nullable: true)]
    #[Assert\Email(message: 'Veuillez saisir une adresse email valide.')]
    #[Assert\Length(max: 180)]
    private ?string $email = null;

    #[ORM\Column(length: 30, nullable: true)]
    #[Assert\Length(max: 30)]
    private ?string $telephone1 = null;

    #[ORM\Column(length: 30, nullable: true)]
    #[Assert\Length(max: 30)]
    private ?string $telephone2 = null;

    #[ORM\Column(length: 30, nullable: true)]
    #[Assert\Length(max: 30)]
    private ?string $whatsapp = null;

    #[ORM\Column(length: 120, nullable: true)]
    #[Assert\Length(max: 120)]
    private ?string $whatsappInstanceId = null;

    #[ORM\Column(length: 255, nullable: true)]
    #[Assert\Length(max: 255)]
    private ?string $whatsappApiToken = null;

    #[ORM\Column(options: ['default' => false])]
    private bool $whatsappInstanceActive = false;

    #[ORM\Column(length: 255, nullable: true)]
    #[Assert\Length(max: 255)]
    private ?string $adresse = null;

    #[ORM\Column(length: 120, nullable: true)]
    #[Assert\Length(max: 120)]
    private ?string $ville = null;

    #[ORM\Column(length: 120, nullable: true)]
    #[Assert\Length(max: 120)]
    private ?string $pays = null;

    #[ORM\Column(length: 20, nullable: true)]
    #[Assert\Regex(pattern: '/^#[0-9A-Fa-f]{6}$/', message: 'La couleur doit être au format hexadécimal, par exemple #0F5C45.')]
    private ?string $couleurPrincipale = null;

    #[ORM\Column(length: 20, nullable: true)]
    #[Assert\Regex(pattern: '/^#[0-9A-Fa-f]{6}$/', message: 'La couleur doit être au format hexadécimal, par exemple #DDEFE7.')]
    private ?string $couleurSecondaire = null;

    #[ORM\Column(length: 20, nullable: true)]
    #[Assert\Regex(pattern: '/^#[0-9A-Fa-f]{6}$/', message: 'La couleur doit être au format hexadécimal, par exemple #C79A3B.')]
    private ?string $couleurAccent = null;

    #[ORM\Column(length: 255, nullable: true)]
    #[Assert\Length(max: 255)]
    private ?string $heroTitle = null;

    #[ORM\Column(type: Types::TEXT, nullable: true)]
    private ?string $heroSubtitle = null;

    #[ORM\Column(length: 255, nullable: true)]
    #[Assert\Length(max: 255)]
    private ?string $aboutTitle = null;

    #[ORM\Column(type: Types::TEXT, nullable: true)]
    private ?string $aboutText = null;

    #[ORM\Column(length: 255, nullable: true)]
    #[Assert\Length(max: 255)]
    private ?string $ctaTitle = null;

    #[ORM\Column(type: Types::TEXT, nullable: true)]
    private ?string $ctaText = null;

    #[ORM\Column(type: Types::TEXT, nullable: true)]
    private ?string $reglementInterieur = null;

    #[ORM\Column(options: ['default' => true])]
    private bool $active = true;

    #[ORM\Column(type: Types::DATETIME_IMMUTABLE)]
    private ?\DateTimeImmutable $createdAt = null;

    #[ORM\Column(type: Types::DATETIME_IMMUTABLE)]
    private ?\DateTimeImmutable $updatedAt = null;

    /**
     * @var Collection<int, User>
     */
    #[ORM\OneToMany(mappedBy: 'ecole', targetEntity: User::class)]
    private Collection $users;

    /**
     * @var Collection<int, TenantDomain>
     */
    #[ORM\OneToMany(mappedBy: 'ecole', targetEntity: TenantDomain::class, cascade: ['persist'], orphanRemoval: true)]
    #[ORM\OrderBy(['canonical' => 'DESC', 'host' => 'ASC'])]
    private Collection $tenantDomains;

    public function __construct()
    {
        $this->users = new ArrayCollection();
        $this->tenantDomains = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getThemePublic(): ?Theme
    {
        return $this->themePublic;
    }

    public function setThemePublic(?Theme $themePublic): static
    {
        $this->themePublic = $themePublic;

        return $this;
    }

    public function getNom(): ?string
    {
        return $this->nom;
    }

    public function setNom(string $nom): static
    {
        $this->nom = trim($nom);

        return $this;
    }

    public function getSlug(): ?string
    {
        return $this->slug;
    }

    public function setSlug(string $slug): static
    {
        $this->slug = mb_strtolower(trim($slug));

        return $this;
    }

    public function getSousDomaine(): ?string
    {
        return $this->sousDomaine;
    }

    public function setSousDomaine(string $sousDomaine): static
    {
        $this->sousDomaine = mb_strtolower(trim($sousDomaine));

        return $this;
    }

    public function getPrefixeMatricule(): ?string
    {
        return $this->prefixeMatricule;
    }

    public function setPrefixeMatricule(string $prefixeMatricule): static
    {
        $this->prefixeMatricule = mb_strtoupper(trim($prefixeMatricule));

        return $this;
    }

    public function getDernierNumeroMatricule(): int
    {
        return $this->dernierNumeroMatricule;
    }

    public function setDernierNumeroMatricule(int $dernierNumeroMatricule): static
    {
        $this->dernierNumeroMatricule = max(0, $dernierNumeroMatricule);

        return $this;
    }

    public function getLogo(): ?string
    {
        return $this->logo;
    }

    public function setLogo(?string $logo): static
    {
        $this->logo = $this->nullableTrim($logo);

        return $this;
    }

    public function getFavicon(): ?string
    {
        return $this->favicon;
    }

    public function setFavicon(?string $favicon): static
    {
        $this->favicon = $this->nullableTrim($favicon);

        return $this;
    }

    public function getHeroImage(): ?string
    {
        return $this->heroImage;
    }

    public function setHeroImage(?string $heroImage): static
    {
        $this->heroImage = $this->nullableTrim($heroImage);

        return $this;
    }

    public function getPresentationImage1(): ?string
    {
        return $this->presentationImage1;
    }

    public function setPresentationImage1(?string $presentationImage1): static
    {
        $this->presentationImage1 = $this->nullableTrim($presentationImage1);

        return $this;
    }

    public function getPresentationImage2(): ?string
    {
        return $this->presentationImage2;
    }

    public function setPresentationImage2(?string $presentationImage2): static
    {
        $this->presentationImage2 = $this->nullableTrim($presentationImage2);

        return $this;
    }

    public function getPresentationImage3(): ?string
    {
        return $this->presentationImage3;
    }

    public function setPresentationImage3(?string $presentationImage3): static
    {
        $this->presentationImage3 = $this->nullableTrim($presentationImage3);

        return $this;
    }

    public function getImageSignatureAdministration(): ?string
    {
        return $this->imageSignatureAdministration;
    }

    public function setImageSignatureAdministration(?string $imageSignatureAdministration): static
    {
        $this->imageSignatureAdministration = $this->nullableTrim($imageSignatureAdministration);

        return $this;
    }

    public function getImageCachetAdministration(): ?string
    {
        return $this->imageCachetAdministration;
    }

    public function setImageCachetAdministration(?string $imageCachetAdministration): static
    {
        $this->imageCachetAdministration = $this->nullableTrim($imageCachetAdministration);

        return $this;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function setDescription(?string $description): static
    {
        $this->description = $this->nullableTrim($description);

        return $this;
    }

    public function getSlogan(): ?string
    {
        return $this->slogan;
    }

    public function setSlogan(?string $slogan): static
    {
        $this->slogan = $this->nullableTrim($slogan);

        return $this;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(?string $email): static
    {
        $email = $this->nullableTrim($email);
        $this->email = $email !== null ? mb_strtolower($email) : null;

        return $this;
    }

    public function getTelephone1(): ?string
    {
        return $this->telephone1;
    }

    public function setTelephone1(?string $telephone1): static
    {
        $this->telephone1 = $this->nullableTrim($telephone1);

        return $this;
    }

    public function getTelephone2(): ?string
    {
        return $this->telephone2;
    }

    public function setTelephone2(?string $telephone2): static
    {
        $this->telephone2 = $this->nullableTrim($telephone2);

        return $this;
    }

    public function getWhatsapp(): ?string
    {
        return $this->whatsapp;
    }

    public function setWhatsapp(?string $whatsapp): static
    {
        $this->whatsapp = $this->nullableTrim($whatsapp);

        return $this;
    }

    public function getWhatsappInstanceId(): ?string
    {
        return $this->whatsappInstanceId;
    }

    public function setWhatsappInstanceId(?string $whatsappInstanceId): static
    {
        $this->whatsappInstanceId = $this->nullableTrim($whatsappInstanceId);

        return $this;
    }

    public function getWhatsappApiToken(): ?string
    {
        return $this->whatsappApiToken;
    }

    public function setWhatsappApiToken(?string $whatsappApiToken): static
    {
        $this->whatsappApiToken = $this->nullableTrim($whatsappApiToken);

        return $this;
    }

    public function isWhatsappInstanceActive(): bool
    {
        return $this->whatsappInstanceActive;
    }

    public function setWhatsappInstanceActive(bool $whatsappInstanceActive): static
    {
        $this->whatsappInstanceActive = $whatsappInstanceActive;

        return $this;
    }

    public function getAdresse(): ?string
    {
        return $this->adresse;
    }

    public function setAdresse(?string $adresse): static
    {
        $this->adresse = $this->nullableTrim($adresse);

        return $this;
    }

    public function getVille(): ?string
    {
        return $this->ville;
    }

    public function setVille(?string $ville): static
    {
        $this->ville = $this->nullableTrim($ville);

        return $this;
    }

    public function getPays(): ?string
    {
        return $this->pays;
    }

    public function setPays(?string $pays): static
    {
        $this->pays = $this->nullableTrim($pays);

        return $this;
    }

    public function getCouleurPrincipale(): ?string
    {
        return $this->couleurPrincipale;
    }

    public function setCouleurPrincipale(?string $couleurPrincipale): static
    {
        $this->couleurPrincipale = $this->nullableTrim($couleurPrincipale);

        return $this;
    }

    public function getCouleurSecondaire(): ?string
    {
        return $this->couleurSecondaire;
    }

    public function setCouleurSecondaire(?string $couleurSecondaire): static
    {
        $this->couleurSecondaire = $this->nullableTrim($couleurSecondaire);

        return $this;
    }

    public function getCouleurAccent(): ?string
    {
        return $this->couleurAccent;
    }

    public function setCouleurAccent(?string $couleurAccent): static
    {
        $this->couleurAccent = $this->nullableTrim($couleurAccent);

        return $this;
    }

    public function getHeroTitle(): ?string
    {
        return $this->heroTitle;
    }

    public function setHeroTitle(?string $heroTitle): static
    {
        $this->heroTitle = $this->nullableTrim($heroTitle);

        return $this;
    }

    public function getHeroSubtitle(): ?string
    {
        return $this->heroSubtitle;
    }

    public function setHeroSubtitle(?string $heroSubtitle): static
    {
        $this->heroSubtitle = $this->nullableTrim($heroSubtitle);

        return $this;
    }

    public function getAboutTitle(): ?string
    {
        return $this->aboutTitle;
    }

    public function setAboutTitle(?string $aboutTitle): static
    {
        $this->aboutTitle = $this->nullableTrim($aboutTitle);

        return $this;
    }

    public function getAboutText(): ?string
    {
        return $this->aboutText;
    }

    public function setAboutText(?string $aboutText): static
    {
        $this->aboutText = $this->nullableTrim($aboutText);

        return $this;
    }

    public function getCtaTitle(): ?string
    {
        return $this->ctaTitle;
    }

    public function setCtaTitle(?string $ctaTitle): static
    {
        $this->ctaTitle = $this->nullableTrim($ctaTitle);

        return $this;
    }

    public function getCtaText(): ?string
    {
        return $this->ctaText;
    }

    public function setCtaText(?string $ctaText): static
    {
        $this->ctaText = $this->nullableTrim($ctaText);

        return $this;
    }

    public function getReglementInterieur(): ?string
    {
        return $this->reglementInterieur;
    }

    public function setReglementInterieur(?string $reglementInterieur): static
    {
        $this->reglementInterieur = $this->nullableTrim($reglementInterieur);

        return $this;
    }

    public function isActive(): bool
    {
        return $this->active;
    }

    public function setActive(bool $active): static
    {
        $this->active = $active;

        return $this;
    }

    public function getCreatedAt(): ?\DateTimeImmutable
    {
        return $this->createdAt;
    }

    public function getUpdatedAt(): ?\DateTimeImmutable
    {
        return $this->updatedAt;
    }

    /**
     * @return Collection<int, User>
     */
    public function getUsers(): Collection
    {
        return $this->users;
    }

    /**
     * @return Collection<int, TenantDomain>
     */
    public function getTenantDomains(): Collection
    {
        return $this->tenantDomains;
    }

    public function addTenantDomain(TenantDomain $tenantDomain): static
    {
        if (!$this->tenantDomains->contains($tenantDomain)) {
            $this->tenantDomains->add($tenantDomain);
            $tenantDomain->setEcole($this);
        }

        return $this;
    }

    public function removeTenantDomain(TenantDomain $tenantDomain): static
    {
        if ($this->tenantDomains->removeElement($tenantDomain) && $tenantDomain->getEcole() === $this) {
            $tenantDomain->setEcole(null);
        }

        return $this;
    }

    public function getCanonicalTenantDomain(): ?TenantDomain
    {
        foreach ($this->tenantDomains as $tenantDomain) {
            if ($tenantDomain->isActive() && $tenantDomain->isCanonical()) {
                return $tenantDomain;
            }
        }

        return null;
    }

    /**
     * @return list<string>
     */
    public function getActiveAliasHosts(): array
    {
        $hosts = [];

        foreach ($this->tenantDomains as $tenantDomain) {
            if ($tenantDomain->isActive() && !$tenantDomain->isCanonical() && $tenantDomain->getHost()) {
                $hosts[] = $tenantDomain->getHost();
            }
        }

        return $hosts;
    }

    public function getDisplayLocation(): string
    {
        return trim(sprintf('%s%s%s', $this->ville ?? '', $this->ville && $this->pays ? ', ' : '', $this->pays ?? '')) ?: 'Non renseigné';
    }

    #[ORM\PrePersist]
    public function initializeTimestamps(): void
    {
        $now = new \DateTimeImmutable();
        $this->createdAt ??= $now;
        $this->updatedAt = $now;
    }

    #[ORM\PreUpdate]
    public function refreshUpdatedAt(): void
    {
        $this->updatedAt = new \DateTimeImmutable();
    }

    private function nullableTrim(?string $value): ?string
    {
        $value = $value !== null ? trim($value) : null;

        return $value !== '' ? $value : null;
    }
}
