<?php

declare (strict_types=1);
/**
 * \DragonBe\Vies
 *
 * @author  Paweł Krzaczkowski <krzaczek+github@gmail.com>
 * @license  MIT
 */
namespace FormEnhancerDeps\DragonBe\Vies\Validator;

/**
 * Class ValidatorNL
 * @package DragonBe\Vies\Validator
 *
 * VAT format: [C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 C12]
 */
class ValidatorNL extends ValidatorAbstract
{
    /**
     * Check Character: 10-A, 11-B .... 35-Z, 36-+, 37-*
     *
     * @var array
     */
    protected $checkCharacter = ['A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20, 'L' => 21, 'M' => 22, 'N' => 23, 'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27, 'S' => 28, 'T' => 29, 'U' => 30, 'V' => 31, 'W' => 32, 'X' => 33, 'Y' => 34, 'Z' => 35, '+' => 36, '*' => 37];
    /**
     * {@inheritdoc}
     */
    public function validate(string $vatNumber): bool
    {
        if (strlen($vatNumber) != 12) {
            return \false;
        }
        if (strtoupper($vatNumber[9]) != 'B') {
            return \false;
        }
        return $this->validateCommercial($vatNumber) || $this->validateSoleProprietor($vatNumber);
    }
    /**
     * Range:
     *      C1 ... C9 Numeric from 0 to 9
     *      C10 Alphabetic “B”
     *      C11 ... C12 Numeric from 0 to 9
     *
     * Rules:
     * C9
     *      A1 = C1*9 + C2*8 + C3*7 + C4*6 + C5*5 + C6*4 + C7*3 + C8*2
     *      A2 = A1 modulo 11
     *      If A2 = 10 then number is invalid
     *      else C9 = A2
     *
     * [C11 C12]
     *      >00
     *
     * @param string $vatNumber
     * @return bool
     */
    protected function validateCommercial(string $vatNumber): bool
    {
        if ((int) substr($vatNumber, -2) == 0) {
            return \false;
        }
        $checksum = (int) $vatNumber[8];
        $weights = [9, 8, 7, 6, 5, 4, 3, 2];
        $checkVal = $this->sumWeights($weights, $vatNumber);
        $checkVal = $checkVal % 11 > 9 ? 0 : $checkVal % 11;
        return $checkVal == $checksum;
    }
    /**
     * Range:
     *      C1 ... C9 0-9 A-Z + *
     *      C10 Alphabetic “B”
     *      C11 ... C12 Numeric from 0 to 9
     *
     * [C11 C12]
     *      02 - 98
     *
     * @param string $vatNumber
     * @return bool
     */
    protected function validateSoleProprietor(string $vatNumber): bool
    {
        if (!preg_match("#^[A-Z0-9+*]{9}B[0-9]{2}\$#u", $vatNumber)) {
            return \false;
        }
        $sumBase = array_reduce(str_split($vatNumber), function ($acc, $e) {
            if (ctype_digit($e)) {
                return $acc . $e;
            }
            return $acc . $this->checkCharacter[$e];
        }, '2321');
        if (\PHP_INT_SIZE === 4 && extension_loaded('bcmath')) {
            return bcmod($sumBase, '97') === '1';
        } else {
            return (int) $sumBase % 97 === 1;
        }
    }
}
