<?php

declare(strict_types=1);

namespace App\Module\Directory\Domain\Entity;

use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Delete;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Patch;
use ApiPlatform\Metadata\Post;
use App\Module\Directory\Infrastructure\Doctrine\DoctrineAddressRepository;
use App\Shared\Domain\Attribute\Auditable;
use App\Shared\Domain\Contract\BlamableInterface;
use App\Shared\Domain\Contract\TimestampableInterface;
use App\Shared\Domain\Trait\TimestampableBlamableTrait;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Attribute\Groups;

#[Auditable]
#[ApiResource(
    operations: [
        new GetCollection(paginationEnabled: false, security: "is_granted('directory.clients.view') or is_granted('directory.prospects.view') or is_granted('directory.providers.view')"),
        new Get(security: "is_granted('directory.clients.view') or is_granted('directory.prospects.view') or is_granted('directory.providers.view')"),
        new Post(security: "is_granted('directory.clients.manage') or is_granted('directory.prospects.manage') or is_granted('directory.providers.manage')"),
        new Patch(security: "is_granted('directory.clients.manage') or is_granted('directory.prospects.manage') or is_granted('directory.providers.manage')"),
        new Delete(security: "is_granted('directory.clients.manage') or is_granted('directory.prospects.manage') or is_granted('directory.providers.manage')"),
    ],
    normalizationContext: ['groups' => ['address:read']],
    denormalizationContext: ['groups' => ['address:write']],
    order: ['id' => 'ASC'],
)]
#[ApiFilter(SearchFilter::class, properties: ['client' => 'exact', 'prospect' => 'exact', 'prestataire' => 'exact'])]
#[ORM\Entity(repositoryClass: DoctrineAddressRepository::class)]
#[ORM\Table(name: 'directory_address')]
class Address implements TimestampableInterface, BlamableInterface
{
    use TimestampableBlamableTrait;

    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    #[Groups(['address:read'])]
    private ?int $id = null;

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

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

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

    #[ORM\Column(length: 20, nullable: true)]
    #[Groups(['address:read', 'address:write', 'client:read', 'prospect:read'])]
    private ?string $postalCode = null;

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

    #[ORM\Column(length: 2)]
    #[Groups(['address:read', 'address:write', 'client:read', 'prospect:read'])]
    private string $country = 'FR';

    #[ORM\ManyToOne(targetEntity: Client::class)]
    #[ORM\JoinColumn(name: 'client_id', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
    #[Groups(['address:read', 'address:write'])]
    private ?Client $client = null;

    #[ORM\ManyToOne(targetEntity: Prospect::class)]
    #[ORM\JoinColumn(name: 'prospect_id', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
    #[Groups(['address:read', 'address:write'])]
    private ?Prospect $prospect = null;

    #[ORM\ManyToOne(targetEntity: Prestataire::class)]
    #[ORM\JoinColumn(name: 'prestataire_id', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
    #[Groups(['address:read', 'address:write'])]
    private ?Prestataire $prestataire = null;

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

    public function getLabel(): ?string
    {
        return $this->label;
    }

    public function setLabel(?string $label): static
    {
        $this->label = $label;

        return $this;
    }

    public function getStreet(): ?string
    {
        return $this->street;
    }

    public function setStreet(?string $street): static
    {
        $this->street = $street;

        return $this;
    }

    public function getStreetComplement(): ?string
    {
        return $this->streetComplement;
    }

    public function setStreetComplement(?string $streetComplement): static
    {
        $this->streetComplement = $streetComplement;

        return $this;
    }

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

    public function setPostalCode(?string $postalCode): static
    {
        $this->postalCode = $postalCode;

        return $this;
    }

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

    public function setCity(?string $city): static
    {
        $this->city = $city;

        return $this;
    }

    public function getCountry(): string
    {
        return $this->country;
    }

    public function setCountry(string $country): static
    {
        $this->country = $country;

        return $this;
    }

    public function getClient(): ?Client
    {
        return $this->client;
    }

    public function setClient(?Client $client): static
    {
        $this->client = $client;

        return $this;
    }

    public function getProspect(): ?Prospect
    {
        return $this->prospect;
    }

    public function setProspect(?Prospect $prospect): static
    {
        $this->prospect = $prospect;

        return $this;
    }

    public function getPrestataire(): ?Prestataire
    {
        return $this->prestataire;
    }

    public function setPrestataire(?Prestataire $prestataire): static
    {
        $this->prestataire = $prestataire;

        return $this;
    }
}
