<?php

declare(strict_types=1);

namespace App\Entity;

use App\Repository\PaiementRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: PaiementRepository::class)]
#[ORM\Table(name: 'paiements')]
#[ORM\UniqueConstraint(name: 'UNIQ_PAIEMENT_NUMERO_RECU', columns: ['numero_recu'])]
#[ORM\Index(name: 'IDX_PAIEMENT_ECOLE_DATE', columns: ['ecole_id', 'date_paiement', 'statut'])]
#[ORM\HasLifecycleCallbacks]
class Paiement
{
    public const MODE_ESPECES = 'ESPECES';
    public const MODE_MOBILE_MONEY = 'MOBILE_MONEY';
    public const MODE_ORANGE_MONEY = 'ORANGE_MONEY';
    public const MODE_MTN_MOMO = 'MTN_MOMO';
    public const MODE_VIREMENT = 'VIREMENT';
    public const MODE_AUTRE = 'AUTRE';

    public const STATUT_VALIDE = 'VALIDE';
    public const STATUT_ANNULE = 'ANNULE';

    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\ManyToOne]
    #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
    private ?Ecole $ecole = null;

    #[ORM\ManyToOne]
    #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
    private ?Etudiant $etudiant = null;

    #[ORM\ManyToOne]
    #[ORM\JoinColumn(onDelete: 'SET NULL')]
    private ?AnneeScolaire $anneeScolaire = null;

    #[ORM\ManyToOne]
    #[ORM\JoinColumn(onDelete: 'SET NULL')]
    private ?Inscription $inscription = null;

    #[ORM\Column(length: 60, unique: true)]
    private ?string $numeroRecu = null;

    #[ORM\Column(type: Types::DATE_MUTABLE)]
    private ?\DateTimeInterface $datePaiement = null;

    #[ORM\Column(type: Types::DECIMAL, precision: 12, scale: 2)]
    private ?string $montantTotal = null;

    #[ORM\Column(length: 40, nullable: true)]
    private ?string $modePaiement = null;

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

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

    #[ORM\Column(length: 30, options: ['default' => self::STATUT_VALIDE])]
    private string $statut = self::STATUT_VALIDE;

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

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

    /**
     * @var Collection<int, LignePaiement>
     */
    #[ORM\OneToMany(mappedBy: 'paiement', targetEntity: LignePaiement::class, cascade: ['persist'], orphanRemoval: true)]
    private Collection $lignes;

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

    public function getId(): ?int { return $this->id; }
    public function getEcole(): ?Ecole { return $this->ecole; }
    public function setEcole(?Ecole $ecole): static { $this->ecole = $ecole; return $this; }
    public function getEtudiant(): ?Etudiant { return $this->etudiant; }
    public function setEtudiant(?Etudiant $etudiant): static { $this->etudiant = $etudiant; return $this; }
    public function getAnneeScolaire(): ?AnneeScolaire { return $this->anneeScolaire; }
    public function setAnneeScolaire(?AnneeScolaire $anneeScolaire): static { $this->anneeScolaire = $anneeScolaire; return $this; }
    public function getInscription(): ?Inscription { return $this->inscription; }
    public function setInscription(?Inscription $inscription): static { $this->inscription = $inscription; return $this; }
    public function getNumeroRecu(): ?string { return $this->numeroRecu; }
    public function setNumeroRecu(string $numeroRecu): static { $this->numeroRecu = trim($numeroRecu); return $this; }
    public function getDatePaiement(): ?\DateTimeInterface { return $this->datePaiement; }
    public function setDatePaiement(\DateTimeInterface $datePaiement): static { $this->datePaiement = \DateTime::createFromInterface($datePaiement); return $this; }
    public function getMontantTotal(): ?string { return $this->montantTotal; }
    public function setMontantTotal(string|int|float $montantTotal): static { $this->montantTotal = (string) $montantTotal; return $this; }
    public function getModePaiement(): ?string { return $this->modePaiement; }
    public function setModePaiement(?string $modePaiement): static { $this->modePaiement = $this->nullableUpper($modePaiement); return $this; }
    public function getReference(): ?string { return $this->reference; }
    public function setReference(?string $reference): static { $this->reference = $this->nullableTrim($reference); return $this; }
    public function getObservation(): ?string { return $this->observation; }
    public function setObservation(?string $observation): static { $this->observation = $this->nullableTrim($observation); return $this; }
    public function getStatut(): string { return $this->statut; }
    public function setStatut(string $statut): static { $this->statut = mb_strtoupper(trim($statut)); return $this; }
    public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; }
    public function getUpdatedAt(): ?\DateTimeImmutable { return $this->updatedAt; }
    /** @return Collection<int, LignePaiement> */
    public function getLignes(): Collection { return $this->lignes; }
    /** @param iterable<LignePaiement> $lignes */
    public function setLignes(iterable $lignes): static { foreach ($this->lignes->toArray() as $ligne) { $this->removeLigne($ligne); } foreach ($lignes as $ligne) { $this->addLigne($ligne); } return $this; }
    public function addLigne(LignePaiement $ligne): static { if (!$this->lignes->contains($ligne)) { $this->lignes->add($ligne); $ligne->setPaiement($this); } return $this; }
    public function removeLigne(LignePaiement $ligne): static { if ($this->lignes->removeElement($ligne) && $ligne->getPaiement() === $this) { $ligne->setPaiement(null); } return $this; }

    #[ORM\PrePersist]
    public function initializeTimestamps(): void { $now = new \DateTimeImmutable(); $this->createdAt ??= $now; $this->updatedAt = $now; $this->datePaiement ??= new \DateTimeImmutable(); }
    #[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; }
    private function nullableUpper(?string $value): ?string { $value = $this->nullableTrim($value); return $value !== null ? mb_strtoupper($value) : null; }
}
