<?php

namespace App\Entity;

use App\Repository\AttestationRepository;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: AttestationRepository::class)]
class Attestation
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 64, unique: true)]
    private string $reference;

    #[ORM\Column(length: 50)]
    private string $type;

    #[ORM\Column(length: 255)]
    private string $ip;

    #[ORM\Column(length: 255)]
    private string $email;

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

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

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

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

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

    #[ORM\Column(length: 20, options: ['default' => 'pending'])]
    private string $status = 'pending';

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

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

    public function __construct(string $type, string $ip, string $email, string $hmacSecret)
    {
        $this->type = $type;
        $this->ip = $ip;
        $this->email = $email;
        $this->createdAt = new \DateTimeImmutable();
        $this->reference = $this->generateReference();
        $this->hmac = $this->generateHmac($hmacSecret);
    }

    private function generateReference(): string
    {
        $prefix = match ($this->type) {
            'access' => 'ACC',
            'deletion' => 'DEL',
            'no_data' => 'ABS',
            default => 'ATT', // @codeCoverageIgnore
        };

        $rev = strtoupper(bin2hex(random_bytes(4)));

        return sprintf('RGPD-%s-%s-%s', $prefix, $this->createdAt->format('dmY'), $rev);
    }

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

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

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

    public function getReference(): string
    {
        return $this->reference;
    }

    public function getType(): string
    {
        return $this->type;
    }

    public function getIp(): string
    {
        return $this->ip;
    }

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

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

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

    public function getEmailTracking(): ?EmailTracking
    {
        return $this->emailTracking;
    }

    public function setEmailTracking(?EmailTracking $emailTracking): static
    {
        $this->emailTracking = $emailTracking;

        return $this;
    }

    public function getPdfFileUnsigned(): ?string
    {
        return $this->pdfFileUnsigned;
    }

    public function setPdfFileUnsigned(?string $path): static
    {
        $this->pdfFileUnsigned = $path;

        return $this;
    }

    public function getPdfFileSigned(): ?string
    {
        return $this->pdfFileSigned;
    }

    public function setPdfFileSigned(?string $path): static
    {
        $this->pdfFileSigned = $path;

        return $this;
    }

    public function getPdfFileCertificate(): ?string
    {
        return $this->pdfFileCertificate;
    }

    public function setPdfFileCertificate(?string $path): static
    {
        $this->pdfFileCertificate = $path;

        return $this;
    }

    public function getSubmitterId(): ?int
    {
        return $this->submitterId;
    }

    public function setSubmitterId(?int $submitterId): static
    {
        $this->submitterId = $submitterId;

        return $this;
    }

    public function getStatus(): string
    {
        return $this->status;
    }

    public function markAsSigned(): static
    {
        $this->status = 'signed';

        return $this;
    }

    public function markAsSent(): static
    {
        $this->status = 'sent';

        return $this;
    }

    public function verify(string $secret): bool
    {
        $payload = implode('|', [
            $this->reference,
            $this->type,
            $this->ip,
            $this->email,
            $this->createdAt->format('Y-m-d\TH:i:s'),
        ]);

        return hash_equals($this->hmac, hash_hmac('sha256', $payload, $secret));
    }
}
