<?php

/*
 * This file is part of the VITICORE2 package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Behavior\Impl;

use CpCreation\VitiCore\Address\BusinessIdentifierRules;
use CpCreation\VitiCore\Behavior\HasAddress;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;

trait AddressTrait
{
    #[Assert\NotBlank(groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[Assert\Length(max: 12, groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[ORM\Column(type: 'string', length: 12, nullable: true)]
    private ?string $phone = null;

    #[Assert\NotBlank(groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[Assert\Length(max: 255, groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[ORM\Column(type: 'string', length: 255, nullable: true)]
    private ?string $lastname = null;

    #[Assert\NotBlank(groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[Assert\Length(max: 255, groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[ORM\Column(type: 'string', length: 255, nullable: true)]
    private ?string $firstname = null;

    #[Assert\Length(max: 255, groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[ORM\Column(type: 'string', length: 255, nullable: true)]
    private ?string $company = null;

    #[Assert\Length(max: 14, groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[ORM\Column(type: 'string', length: 14, nullable: true)]
    private ?string $siret = null;

    #[Assert\Regex(pattern: '/^[A-Za-z0-9]*$/', groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[Assert\Length(max: 16, groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[ORM\Column(type: 'string', length: 16, nullable: true)]
    private ?string $vatId = null;

    #[Assert\NotBlank(groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[Assert\Length(max: 255, groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[ORM\Column(type: 'string', length: 255, nullable: true)]
    private ?string $street = null;

    #[Assert\NotBlank(groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[Assert\Type(type: ['digit'], groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[Assert\Length(max: 8, groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[ORM\Column(type: 'string', length: 8, nullable: true)]
    private ?string $postal = null;

    #[Assert\NotBlank(groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[Assert\Length(min: 2, max: 255, groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[ORM\Column(type: 'string', length: 255, nullable: true)]
    private ?string $city = null;

    #[Assert\NotBlank(groups: ['Default', 'delivery_address', 'invoice_address'])]
    #[ORM\Column(type: 'string', length: 2, nullable: true)]
    private ?string $country = null;

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

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

    public function getLastname(): ?string
    {
        return $this->lastname;
    }

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

    public function getFirstname(): ?string
    {
        return $this->firstname;
    }

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

    public function getCompany(): ?string
    {
        return $this->company;
    }

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

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

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

    public function getVatId(): ?string
    {
        return $this->vatId;
    }

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

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

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

    public function getPostal(): ?string
    {
        return $this->postal;
    }

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

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

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

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

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

    #[Assert\Callback(groups: ['Default', 'delivery_address', 'invoice_address'])]
    public function validate(ExecutionContextInterface $context, $payload): void
    {
        if (null !== BusinessIdentifierRules::normalizeIdentifier($this->getVatId()) && !BusinessIdentifierRules::hasCompany($this->getCompany())) {
            $context
                ->buildViolation('This value should not be blank.')
                ->atPath('company')
                ->addViolation();
        }

        if (null !== BusinessIdentifierRules::normalizeIdentifier($this->getSiret()) && !BusinessIdentifierRules::hasCompany($this->getCompany())) {
            $context
                ->buildViolation('This value should not be blank.')
                ->atPath('company')
                ->addViolation();
        }

        if (!BusinessIdentifierRules::isValidVatId($this->getVatId(), $this->getCountry())) {
            $context
                ->buildViolation('address.vat_id.invalid')
                ->atPath('vatId')
                ->addViolation();
        }

        if (!BusinessIdentifierRules::isValidSiret($this->getSiret())) {
            $context
                ->buildViolation('address.siret.invalid')
                ->atPath('siret')
                ->addViolation();
        }

        if ($this->requiresSiret() && null === BusinessIdentifierRules::normalizeIdentifier($this->getSiret())) {
            $context
                ->buildViolation('This value should not be blank.')
                ->atPath('siret')
                ->addViolation();
        }
    }

    public function copy(?HasAddress $address): void
    {
        if (empty($address)) {
            return;
        }

        $this->setLastname($address->getLastname());
        $this->setFirstname($address->getFirstname());
        $this->setCompany($address->getCompany());
        $this->setSiret($address->getSiret());
        $this->setVatId($address->getVatId());
        $this->setStreet($address->getStreet());
        $this->setPostal($address->getPostal());
        $this->setCity($address->getCity());
        $this->setCountry($address->getCountry());
        $this->setPhone($address->getPhone());

        if (method_exists($address, 'getEmail') && method_exists($this, 'setEmail')) {
            $this->setEmail($address->getEmail());
        }
    }

    public function getName(): string
    {
        if ($this->company) {
            return $this->getCompany();
        }

        return $this->getFirstname().' '.$this->getLastname();
    }

    private function requiresSiret(): bool
    {
        return BusinessIdentifierRules::requiresSiretForCompany($this->getCountry(), $this->getCompany());
    }
}
