<?php

declare(strict_types=1);

namespace App\Module\Transport\Domain\Entity;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use App\Module\Transport\Infrastructure\ApiPlatform\State\Provider\QualimatCarrierSearchProvider;
use DateTimeImmutable;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Attribute\Groups;
use Symfony\Component\Serializer\Attribute\SerializedName;

/**
 * Mapping ORM LECTURE SEULE sur la table existante `qualimat_carrier`
 * (referentiel des transporteurs agrees QUALIMAT, ERP-39). La table est
 * alimentee/soft-deletee EXCLUSIVEMENT par la commande console `app:qualimat:sync` ;
 * cette entite n'expose donc AUCUNE ecriture (ni Post/Patch/Delete).
 *
 * Role M4 (ERP-155/157) :
 *  - cible de la FK editable `carrier.qualimat_carrier_id` (§ 2.5) ;
 *  - embarquee (groupe `qualimat:read`) dans la liste et le detail Carrier pour
 *    afficher statut + date de validite QUALIMAT (RG-4.04) ;
 *  - endpoint de recherche `GET /api/qualimat_carriers?search=` pour la saisie
 *    assistee du nom (§ 4.7) — fuzzy name (+ siret), SEULEMENT les lignes actives,
 *    tri name ASC, paginee ; logique portee par QualimatCarrierSearchProvider.
 *
 * La table reste hors `schema_filter` Doctrine (doctrine.yaml) : c'est la
 * migration modulaire Version20260612150000 qui possede son DDL et ses COMMENT
 * (pas l'ORM). Lecture seule + referentiel synchronise => exclue de
 * EntitiesAreTimestampableBlamableTest et non #[Auditable].
 */
#[ApiResource(
    operations: [
        // Saisie assistee (§ 4.7 / RG-4.01) : ?search= fuzzy name (+ siret),
        // SEULEMENT les lignes actives, tri name ASC, paginee. La logique vit
        // dans le provider (forcage is_active + recherche multi-champs) car un
        // SearchFilter natif ne sait ni unifier name/siret sous un seul ?search=,
        // ni imposer cote serveur le filtre actif.
        new GetCollection(
            security: "is_granted('transport.carriers.view')",
            provider: QualimatCarrierSearchProvider::class,
            normalizationContext: ['groups' => ['qualimat:read', 'default:read']],
        ),
        new Get(
            security: "is_granted('transport.carriers.view')",
            normalizationContext: ['groups' => ['qualimat:read', 'default:read']],
        ),
    ],
)]
#[ORM\Entity]
// Mapping reproduisant a l'identique le DDL de la migration ERP-39
// (Version20260612150000) pour que `schema:update --force` reste un no-op :
// contrainte d'unicite siret + index is_active.
#[ORM\Table(name: 'qualimat_carrier')]
#[ORM\UniqueConstraint(name: 'uq_qualimat_carrier_siret', columns: ['siret'])]
#[ORM\Index(name: 'idx_qualimat_carrier_active', columns: ['is_active'])]
class QualimatCarrier
{
    #[ORM\Id]
    #[ORM\GeneratedValue(strategy: 'IDENTITY')]
    #[ORM\Column(type: 'bigint')]
    #[Groups(['qualimat:read'])]
    private ?string $id = null;

    #[ORM\Column(length: 20)]
    #[Groups(['qualimat:read'])]
    private ?string $siret = null;

    #[ORM\Column(length: 255)]
    #[Groups(['qualimat:read'])]
    private ?string $name = null;

    #[ORM\Column(length: 255, nullable: true)]
    #[Groups(['qualimat:read'])]
    private ?string $address = null;

    #[ORM\Column(name: 'postal_code', length: 10, nullable: true)]
    #[Groups(['qualimat:read'])]
    private ?string $postalCode = null;

    #[ORM\Column(length: 255, nullable: true)]
    #[Groups(['qualimat:read'])]
    private ?string $city = null;

    #[ORM\Column(length: 32, nullable: true)]
    #[Groups(['qualimat:read'])]
    private ?string $phone = null;

    #[ORM\Column(length: 64, nullable: true)]
    #[Groups(['qualimat:read'])]
    private ?string $department = null;

    #[ORM\Column(length: 32)]
    #[Groups(['qualimat:read'])]
    private ?string $status = null;

    #[ORM\Column(name: 'validity_date', type: 'date_immutable', nullable: true)]
    #[Groups(['qualimat:read'])]
    private ?DateTimeImmutable $validityDate = null;

    #[ORM\Column(name: 'is_active', options: ['default' => true])]
    #[Groups(['qualimat:read'])]
    #[SerializedName('isActive')]
    private bool $isActive = true;

    // Colonne technique de synchro (soft-delete) — mappee pour completude, non
    // serialisee. Alimentee par app:qualimat:sync. columnDefinition pin la
    // precision TIMESTAMP(6) du DDL ERP-39 pour eviter un ALTER de schema:update
    // (le datetime_immutable par defaut mapperait sur TIMESTAMP(0)).
    #[ORM\Column(name: 'last_synced_at', type: 'datetime_immutable', columnDefinition: 'TIMESTAMP(6) WITHOUT TIME ZONE NOT NULL')]
    private ?DateTimeImmutable $lastSyncedAt = null;

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

    public function getSiret(): ?string
    {
        return $this->siret;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function getAddress(): ?string
    {
        return $this->address;
    }

    public function getPostalCode(): ?string
    {
        return $this->postalCode;
    }

    public function getCity(): ?string
    {
        return $this->city;
    }

    public function getPhone(): ?string
    {
        return $this->phone;
    }

    public function getDepartment(): ?string
    {
        return $this->department;
    }

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

    public function getValidityDate(): ?DateTimeImmutable
    {
        return $this->validityDate;
    }

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

    public function getLastSyncedAt(): ?DateTimeImmutable
    {
        return $this->lastSyncedAt;
    }
}
