<?php

/*
 * This file is part of Respect/Validation.
 *
 * (c) Alexandre Gomes Gaigalas <alganet@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE file
 * that was distributed with this source code.
 */
declare (strict_types=1);
namespace ZOOlanders\YOOessentials\Vendor\Respect\Validation\Rules;

use function array_keys;
use function array_map;
use function array_pop;
use function array_sum;
use function intval;
use function is_numeric;
use function is_string;
use function str_split;
use function strlen;
/**
 * Validates Portugal's fiscal identification number (NIF)
 *
 *
 * @see https://pt.wikipedia.org/wiki/N%C3%BAmero_de_identifica%C3%A7%C3%A3o_fiscal
 *
 * @author Gonçalo Andrade <goncalo.andrade95@gmail.com>
 */
final class PortugueseNif extends AbstractRule
{
    /**
     * {@inheritDoc}
     */
    public function validate($input) : bool
    {
        // Validate format and length
        if (!is_string($input)) {
            return \false;
        }
        if (!is_numeric($input)) {
            return \false;
        }
        if (strlen($input) != 9) {
            return \false;
        }
        $digits = array_map(static fn(string $digit) => intval($digit), str_split($input));
        // Validate first and second digits
        switch ($digits[0]) {
            case 4:
                switch ($digits[1]) {
                    case 5:
                        break;
                    default:
                        return \false;
                }
                break;
            case 7:
                switch ($digits[1]) {
                    case 0:
                    case 1:
                    case 2:
                    case 4:
                    case 5:
                    case 7:
                    case 8:
                    case 9:
                        break;
                    default:
                        return \false;
                }
                break;
            case 9:
                switch ($digits[1]) {
                    case 0:
                    case 1:
                    case 8:
                    case 9:
                        break;
                    default:
                        return \false;
                }
                break;
            default:
                break;
        }
        // Validate check digit
        $checkDigit = array_pop($digits);
        $digitKeys = array_keys($digits);
        $sumTerms = array_map(static fn(int $digit, int $position) => $digit * (9 - $position), $digits, $digitKeys);
        $sum = array_sum($sumTerms);
        $modulus = $sum % 11;
        if ($modulus == 0 || $modulus == 1) {
            return $checkDigit == 0;
        }
        return $checkDigit == 11 - $modulus;
    }
}
