<?php

namespace App\Entity;

use App\Repository\FactureRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Attribute as Vich;

#[ORM\Entity(repositoryClass: FactureRepository::class)]
#[Vich\Uploadable]
class Facture
{
    public const STATE_CREATED = 'created';
    public const STATE_SEND = 'send';
    public const STATE_PAID = 'paid';
    public const STATE_CANCEL = 'cancel';

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

    #[ORM\ManyToOne(targetEntity: OrderNumber::class)]
    #[ORM\JoinColumn(nullable: false)]
    private OrderNumber $orderNumber;

    #[ORM\ManyToOne(targetEntity: Advert::class, inversedBy: 'factures')]
    #[ORM\JoinColumn(nullable: true)]
    private ?Advert $advert = null;

    #[ORM\ManyToOne(targetEntity: Customer::class)]
    #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
    private ?Customer $customer = null;

    /**
     * Suffixe pour les factures multiples sur un meme advert (-1, -2, etc.).
     */
    #[ORM\Column(type: 'smallint', options: ['default' => 0])]
    private int $splitIndex = 0;

    #[ORM\Column(length: 128)]
    private string $hmac;

    #[ORM\Column(length: 20, options: ['default' => 'created'])]
    private string $state = self::STATE_CREATED;

    #[ORM\Column(type: 'decimal', precision: 10, scale: 2, options: ['default' => '0.00'])]
    private string $totalHt = '0.00';

    #[ORM\Column(type: 'decimal', precision: 10, scale: 2, options: ['default' => '0.00'])]
    private string $totalTva = '0.00';

    #[ORM\Column(type: 'decimal', precision: 10, scale: 2, options: ['default' => '0.00'])]
    private string $totalTtc = '0.00';

    #[ORM\Column]
    private bool $isPaid = false;

    #[ORM\Column(nullable: true)]
    private ?\DateTimeImmutable $paidAt = null;

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

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

    #[Vich\UploadableField(mapping: 'facture_pdf', fileNameProperty: 'facturePdf')]
    private ?File $facturePdfFile = null;

    #[ORM\Column]
    private \DateTimeImmutable $createdAt;

    #[ORM\Column(nullable: true)]
    private ?\DateTimeImmutable $updatedAt = null;

    /** @var Collection<int, FactureLine> */
    #[ORM\OneToMany(targetEntity: FactureLine::class, mappedBy: 'facture', cascade: ['persist', 'remove'], orphanRemoval: true)]
    #[ORM\OrderBy(['pos' => 'ASC'])]
    private Collection $lines;

    public function __construct(OrderNumber $orderNumber, string $hmacSecret)
    {
        $this->orderNumber = $orderNumber;
        $this->createdAt = new \DateTimeImmutable();
        $this->lines = new ArrayCollection();
        $this->hmac = $this->generateHmac($hmacSecret);
    }

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

    public function getOrderNumber(): OrderNumber
    {
        return $this->orderNumber;
    }

    public function getAdvert(): ?Advert
    {
        return $this->advert;
    }

    public function setAdvert(?Advert $advert): void
    {
        $this->advert = $advert;
    }

    public function getCustomer(): ?Customer
    {
        return $this->customer;
    }

    public function setCustomer(?Customer $customer): void
    {
        $this->customer = $customer;
    }

    public function getSplitIndex(): int
    {
        return $this->splitIndex;
    }

    public function setSplitIndex(int $splitIndex): void
    {
        $this->splitIndex = $splitIndex;
    }

    /**
     * Retourne le numero de facture complet.
     * Si splitIndex > 0, ajoute le suffixe -X (ex: 04/2026-00001-2).
     */
    public function getInvoiceNumber(): string
    {
        $num = $this->orderNumber->getNumOrder();

        return $this->splitIndex > 0 ? $num.'-'.$this->splitIndex : $num;
    }

    public function getHmac(): string
    {
        return $this->hmac;
    }

    public function getState(): string
    {
        return $this->state;
    }

    public function setState(string $state): void
    {
        $this->state = $state;
    }

    public function getTotalHt(): string
    {
        return $this->totalHt;
    }

    public function setTotalHt(string $totalHt): void
    {
        $this->totalHt = $totalHt;
    }

    public function getTotalTva(): string
    {
        return $this->totalTva;
    }

    public function setTotalTva(string $totalTva): void
    {
        $this->totalTva = $totalTva;
    }

    public function getTotalTtc(): string
    {
        return $this->totalTtc;
    }

    public function setTotalTtc(string $totalTtc): void
    {
        $this->totalTtc = $totalTtc;
    }

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

    public function setIsPaid(bool $isPaid): void
    {
        $this->isPaid = $isPaid;
    }

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

    public function setPaidAt(?\DateTimeImmutable $paidAt): void
    {
        $this->paidAt = $paidAt;
    }

    public function getPaidMethod(): ?string
    {
        return $this->paidMethod;
    }

    public function setPaidMethod(?string $paidMethod): void
    {
        $this->paidMethod = $paidMethod;
    }

    public function getFacturePdf(): ?string
    {
        return $this->facturePdf;
    }

    public function setFacturePdf(?string $facturePdf): void
    {
        $this->facturePdf = $facturePdf;
    }

    public function getFacturePdfFile(): ?File
    {
        return $this->facturePdfFile;
    }

    public function setFacturePdfFile(?File $facturePdfFile): void
    {
        $this->facturePdfFile = $facturePdfFile;
        if (null !== $facturePdfFile) {
            $this->updatedAt = new \DateTimeImmutable();
        }
    }

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

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

    public function setUpdatedAt(?\DateTimeImmutable $updatedAt): static
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }

    /** @return Collection<int, FactureLine> */
    public function getLines(): Collection
    {
        return $this->lines;
    }

    public function addLine(FactureLine $line): static
    {
        if (!$this->lines->contains($line)) {
            $this->lines->add($line);
        }

        return $this;
    }

    public function removeLine(FactureLine $line): static
    {
        $this->lines->removeElement($line);

        return $this;
    }

    public function verifyHmac(string $hmacSecret): bool
    {
        return hash_equals($this->hmac, $this->generateHmac($hmacSecret));
    }

    private function generateHmac(string $secret): string
    {
        $payload = implode('|', [
            'facture',
            $this->orderNumber->getNumOrder(),
            (string) $this->splitIndex,
            $this->createdAt->format('Y-m-d\TH:i:s'),
        ]);

        return hash_hmac('sha256', $payload, $secret);
    }
}
