<?php

namespace App\Entity;

use App\Repository\AdvertRepository;
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: AdvertRepository::class)]
#[Vich\Uploadable]
class Advert
{
    public const STATE_CREATED = 'created';
    public const STATE_SEND = 'send';
    public const STATE_ACCEPTED = 'accepted';
    public const STATE_REFUSED = 'refused';
    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\OneToOne(targetEntity: Devis::class, inversedBy: 'advert')]
    #[ORM\JoinColumn(nullable: true)]
    private ?Devis $devis = null;

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

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

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

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $raisonMessage = null;

    #[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(length: 255, nullable: true)]
    private ?string $submissionId = null;

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

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

    #[Vich\UploadableField(mapping: 'advert_pdf', fileNameProperty: 'advertFile')]
    private ?File $advertFileUpload = null;

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

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

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

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

    /** @var Collection<int, AdvertPayment> */
    #[ORM\OneToMany(targetEntity: AdvertPayment::class, mappedBy: 'advert', cascade: ['persist', 'remove'])]
    #[ORM\OrderBy(['createdAt' => 'DESC'])]
    private Collection $payments;

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

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

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

    public function getDevis(): ?Devis
    {
        return $this->devis;
    }

    public function setDevis(?Devis $devis): void
    {
        $this->devis = $devis;
    }

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

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

    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 getRaisonMessage(): ?string
    {
        return $this->raisonMessage;
    }

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

    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 getSubmissionId(): ?string
    {
        return $this->submissionId;
    }

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

    public function getStripePaymentId(): ?string
    {
        return $this->stripePaymentId;
    }

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

    public function getAdvertFile(): ?string
    {
        return $this->advertFile;
    }

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

    public function getAdvertFileUpload(): ?File
    {
        return $this->advertFileUpload;
    }

    public function setAdvertFileUpload(?File $advertFileUpload): void
    {
        $this->advertFileUpload = $advertFileUpload;
        if (null !== $advertFileUpload) {
            $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, Facture> */
    public function getFactures(): Collection
    {
        return $this->factures;
    }

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

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

        return $this;
    }

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

        return $this;
    }

    /** @return Collection<int, AdvertPayment> */
    public function getPayments(): Collection
    {
        return $this->payments;
    }

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

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

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