<?php

namespace App\Entity;

use App\Repository\DevisRepository;
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: DevisRepository::class)]
#[Vich\Uploadable]
class Devis
{
    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\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(nullable: true)]
    private ?int $submitterSiteconseilId = null;

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

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

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

    #[Vich\UploadableField(mapping: 'devis_pdf', fileNameProperty: 'unsignedPdf')]
    private ?File $unsignedPdfFile = null;

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

    #[Vich\UploadableField(mapping: 'devis_pdf', fileNameProperty: 'signedPdf')]
    private ?File $signedPdfFile = null;

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

    #[Vich\UploadableField(mapping: 'devis_pdf', fileNameProperty: 'auditPdf')]
    private ?File $auditPdfFile = null;

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

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

    #[ORM\OneToOne(targetEntity: Advert::class, mappedBy: 'devis')]
    private ?Advert $advert = null;

    /** @var Collection<int, DevisLine> */
    #[ORM\OneToMany(targetEntity: DevisLine::class, mappedBy: 'devis', 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 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 getSubmitterSiteconseilId(): ?int
    {
        return $this->submitterSiteconseilId;
    }

    public function setSubmitterSiteconseilId(?int $submitterSiteconseilId): void
    {
        $this->submitterSiteconseilId = $submitterSiteconseilId;
    }

    public function getSubmitterCustomerId(): ?int
    {
        return $this->submitterCustomerId;
    }

    public function setSubmitterCustomerId(?int $submitterCustomerId): void
    {
        $this->submitterCustomerId = $submitterCustomerId;
    }

    public function getSubmissionId(): ?string
    {
        return $this->submissionId;
    }

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

    public function getUnsignedPdf(): ?string
    {
        return $this->unsignedPdf;
    }

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

    public function getUnsignedPdfFile(): ?File
    {
        return $this->unsignedPdfFile;
    }

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

    public function getSignedPdf(): ?string
    {
        return $this->signedPdf;
    }

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

    public function getSignedPdfFile(): ?File
    {
        return $this->signedPdfFile;
    }

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

    public function getAuditPdf(): ?string
    {
        return $this->auditPdf;
    }

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

    public function getAuditPdfFile(): ?File
    {
        return $this->auditPdfFile;
    }

    public function setAuditPdfFile(?File $auditPdfFile): void
    {
        $this->auditPdfFile = $auditPdfFile;
        if (null !== $auditPdfFile) {
            $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;
    }

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

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

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

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

        return $this;
    }

    public function removeLine(DevisLine $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('|', [
            'devis',
            $this->orderNumber->getNumOrder(),
            $this->createdAt->format('Y-m-d\TH:i:s'),
        ]);

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