<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\Address;

final class BusinessIdentifierRules
{
    public static function hasCompany(?string $company): bool
    {
        return null !== self::normalizeText($company);
    }

    public static function normalizeIdentifier(?string $value): ?string
    {
        if (null === $value) {
            return null;
        }

        $value = mb_strtoupper(mb_trim($value));
        $value = preg_replace('/[\s\-.]/u', '', $value);

        return '' === $value ? null : $value;
    }

    public static function normalizeCountry(?string $country): ?string
    {
        if (null === $country) {
            return null;
        }

        $country = mb_trim($country);

        if ('' === $country) {
            return null;
        }

        return mb_strtoupper($country);
    }

    public static function requiresSiret(?string $country): bool
    {
        return 'FR' === self::normalizeCountry($country);
    }

    public static function requiresSiretForCompany(?string $country, ?string $company): bool
    {
        return self::requiresSiret($country) && self::hasCompany($company);
    }

    public static function isValidSiret(?string $siret): bool
    {
        $siret = self::normalizeIdentifier($siret);

        if (null === $siret) {
            return true;
        }

        if (1 !== preg_match('/^\d{14}$/', $siret)) {
            return false;
        }

        $sum = 0;
        $length = strlen($siret);

        for ($index = 0; $index < $length; ++$index) {
            $digit = (int) $siret[$index];

            if (0 === $index % 2) {
                $digit *= 2;

                if ($digit > 9) {
                    $digit -= 9;
                }
            }

            $sum += $digit;
        }

        return 0 === $sum % 10;
    }

    public static function isValidVatId(?string $vatId, ?string $country = null): bool
    {
        $vatId = self::normalizeIdentifier($vatId);

        if (null === $vatId) {
            return true;
        }

        if (1 !== preg_match('/^[A-Z0-9]+$/', $vatId)) {
            return false;
        }

        if (1 === preg_match('/^[A-Z]{2}/', $vatId)) {
            return self::matchesVatPattern($vatId);
        }

        $country = self::normalizeCountry($country);

        if ('FR' === $country) {
            return 1 === preg_match('/^[A-Z0-9]{2}\d{9}$/', $vatId);
        }

        return 1 === preg_match('/^[A-Z0-9]{4,16}$/', $vatId);
    }

    private static function matchesVatPattern(string $vatId): bool
    {
        $prefix = substr($vatId, 0, 2);
        $body = substr($vatId, 2);

        return match ($prefix) {
            'FR' => 1 === preg_match('/^[A-Z0-9]{2}\d{9}$/', $body),
            'DE' => 1 === preg_match('/^\d{9}$/', $body),
            'ES' => 1 === preg_match('/^[A-Z0-9]\d{7}[A-Z0-9]$/', $body),
            'IT' => 1 === preg_match('/^\d{11}$/', $body),
            'NL' => 1 === preg_match('/^\d{9}B\d{2}$/', $body),
            'BE' => 1 === preg_match('/^0?\d{9}$/', $body),
            default => 1 === preg_match('/^[A-Z0-9]{2,14}$/', $body),
        };
    }

    private static function normalizeText(?string $value): ?string
    {
        if (null === $value) {
            return null;
        }

        $value = mb_trim($value);

        return '' === $value ? null : $value;
    }
}
