<?php

declare(strict_types=1);

namespace Gls\GlsPoland\Consignment\DTO;

use Gls\GlsPoland\AdePlus\SenderAddress\SenderAddress;
use Gls\GlsPoland\Country\IsoCode;
use Symfony\Component\Validator\Constraints as Assert;

class AddressDetails
{
    public const SENDER_ADDRESS_VALIDATION_GROUP = 'AdeSenderAddress';
    public const OTHER_ADDRESS_VALIDATION_GROUP = 'OtherAddress';
    public const CONTACT_INFO_VALIDATION_GROUP = 'ContactInfo';

    /**
     * @var string|null
     *
     * @Assert\Length(max="40")
     * @Assert\Email()
     */
    private $email;

    /**
     * @var string|null
     *
     * @Assert\Length(max="20")
     */
    private $phone;

    /**
     * @var string|null
     *
     * @Assert\NotBlank()
     * @Assert\Length(max="40", groups=AddressDetails::OTHER_ADDRESS_VALIDATION_GROUP)
     * @Assert\Length(max="30", groups=AddressDetails::SENDER_ADDRESS_VALIDATION_GROUP)
     */
    private $name1;

    /**
     * @var string|null
     *
     * @Assert\Length(max="40", groups=AddressDetails::OTHER_ADDRESS_VALIDATION_GROUP)
     * @Assert\Length(max="30", groups=AddressDetails::SENDER_ADDRESS_VALIDATION_GROUP)
     */
    private $name2;

    /**
     * @var string|null
     *
     * @Assert\Length(max="40", groups=AddressDetails::OTHER_ADDRESS_VALIDATION_GROUP)
     * @Assert\Length(max="30", groups=AddressDetails::SENDER_ADDRESS_VALIDATION_GROUP)
     */
    private $name3;

    /**
     * @var string|null
     *
     * @Assert\NotBlank()
     * @Assert\Regex(IsoCode::PATTERN)
     */
    private $countryIsoCode;

    /**
     * @var string|null
     *
     * @Assert\NotBlank()
     * @Assert\Length(max="16", groups=AddressDetails::OTHER_ADDRESS_VALIDATION_GROUP)
     * @Assert\Length(max="8", groups=AddressDetails::SENDER_ADDRESS_VALIDATION_GROUP)
     */
    private $zipCode;

    /**
     * @var string|null
     *
     * @Assert\NotBlank()
     * @Assert\Length(max="30", groups=AddressDetails::OTHER_ADDRESS_VALIDATION_GROUP)
     * @Assert\Length(max="40", groups=AddressDetails::SENDER_ADDRESS_VALIDATION_GROUP)
     */
    private $city;

    /**
     * @var string|null
     *
     * @Assert\NotBlank()
     * @Assert\Length(max="50", groups=AddressDetails::OTHER_ADDRESS_VALIDATION_GROUP)
     * @Assert\Length(max="40", groups=AddressDetails::SENDER_ADDRESS_VALIDATION_GROUP)
     */
    private $street;

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

    public function setEmail(?string $email): self
    {
        $this->email = $email;

        return $this;
    }

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

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

        return $this;
    }

    /**
     * @Assert\IsTrue(message="Contact info is required.", groups=AddressDetails::CONTACT_INFO_VALIDATION_GROUP)
     */
    public function hasContactInfo(): bool
    {
        return '' !== (string) $this->email || '' !== (string) $this->phone;
    }

    public function getName1(): string
    {
        return (string) $this->name1;
    }

    public function setName1(?string $name1): self
    {
        $this->name1 = $name1;

        return $this;
    }

    public function getName2(): ?string
    {
        return $this->name2;
    }

    public function setName2(?string $name2): self
    {
        $this->name2 = $name2;

        return $this;
    }

    public function getName3(): ?string
    {
        return $this->name3;
    }

    public function setName3(?string $name3): self
    {
        $this->name3 = $name3;

        return $this;
    }

    public function getCountryIsoCode(): string
    {
        return (string) $this->countryIsoCode;
    }

    public function setCountryIsoCode(?string $countryIsoCode): self
    {
        $this->countryIsoCode = $countryIsoCode;

        return $this;
    }

    public function getZipCode(): string
    {
        return (string) $this->zipCode;
    }

    public function setZipCode(?string $zipCode): self
    {
        $this->zipCode = $zipCode;

        return $this;
    }

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

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

        return $this;
    }

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

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

        return $this;
    }

    public function asAdeSenderAddress(): SenderAddress
    {
        return new SenderAddress(
            $this->getCountryIsoCode(),
            $this->getZipCode(),
            $this->getCity(),
            $this->getStreet(),
            $this->getName1(),
            (string) $this->getName2(),
            (string) $this->getName3()
        );
    }

    public static function fromAdeSenderAddress(SenderAddress $address): self
    {
        return (new self())
            ->setCountryIsoCode($address->getCountryIsoCode())
            ->setZipCode($address->getZipCode())
            ->setCity($address->getCity())
            ->setStreet($address->getStreet())
            ->setName1($address->getName1())
            ->setName2($address->getName2())
            ->setName3($address->getName3());
    }
}
