<?php

/*
 * This file is part of the Serenity 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 Serenity\CoreBundle\Shared\ValueObject;

use Doctrine\ORM\Mapping as ORM;
use libphonenumber\PhoneNumber;
use Misd\PhoneNumberBundle\Validator\Constraints\PhoneNumber as AssertPhoneNumber;
use Symfony\Component\Intl\Countries;
use Symfony\Component\Validator\Constraints as Assert;

#[ORM\Embeddable]
final class Address
{
    #[Assert\NotBlank()]
    #[Assert\Length(min: 2, max: 255)]
    #[ORM\Column(type: 'string', length: 255)]
    private string $street;

    #[Assert\NotBlank()]
    #[Assert\Length(min: 2, max: 10)]
    #[ORM\Column(type: 'string', length: 10)]
    private string $postalCode;

    #[Assert\NotBlank()]
    #[Assert\Length(min: 2, max: 255)]
    #[ORM\Column(type: 'string', length: 255)]
    private string $city;

    #[Assert\NotBlank()]
    #[Assert\Length(min: 2, max: 2)]
    #[ORM\Column(type: 'string', length: 2)]
    private string $country;

    #[AssertPhoneNumber(type: [AssertPhoneNumber::MOBILE])]
    #[ORM\Column(type: 'phone_number')]
    private ?PhoneNumber $mobilePhone;

    #[Assert\Length(min: 2, max: 1024)]
    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $streetComplement;

    #[Assert\Length(min: 2, max: 2)]
    #[ORM\Column(type: 'string', length: 2, nullable: true)]
    private ?string $state;

    public function __construct(string $street, string $postalCode, string $city, string $country, ?PhoneNumber $mobilePhone = null, ?string $streetComplement = null, ?string $state = null)
    {
        $this->street = $street;
        $this->postalCode = $postalCode;
        $this->city = $city;
        $this->country = $country;
        $this->mobilePhone = $mobilePhone;
        $this->streetComplement = $streetComplement;
        $this->state = $state;
    }

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

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

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

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

    public function getCountryName(?string $locale = null): string
    {
        return Countries::getName($this->country, $locale);
    }

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

    public function getCountryAlpha3Code(): string
    {
        return Countries::getAlpha3Code($this->country);
    }

    public function getCountryNumericCode(): string
    {
        return Countries::getNumericCode($this->country);
    }

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

    public function getState(): ?string
    {
        return $this->state;
    }

    public function getMobilePhone(): ?PhoneNumber
    {
        return $this->mobilePhone;
    }

    public function isValidCountryAlpha2Code(string $alpha2Code): bool
    {
        return Countries::exists($alpha2Code);
    }

    public function isValidCountryAlpha3Code(string $alpha3Code): bool
    {
        return Countries::alpha3CodeExists($alpha3Code);
    }

    public function isEqual(self $otherAddress): bool
    {
        return $this->street === $otherAddress->getStreet()
          && $this->postalCode === $otherAddress->getPostalCode()
          && $this->country === $otherAddress->getCountry()
          && $this->city === $otherAddress->getCity()
          && $this->mobilePhone === $otherAddress->getMobilePhone()
          && $this->streetComplement === $otherAddress->getStreetComplement()
          && $this->state === $otherAddress->getState();
    }
}
