/*
 *  Copyright (c) 2025 John Ahlroos / Devsoap
 *
 *  Creative Commons Attribution-NoDerivatives 4.0 International Public License
 *
 *  By exercising the Licensed Rights (defined below), You accept and agree
 *  to be bound by the terms and conditions of this Creative Commons
 *  Attribution-NoDerivatives 4.0 International Public License ("Public
 *  License"). To the extent this Public License may be interpreted as a
 *  contract, You are granted the Licensed Rights in consideration of Your
 *  acceptance of these terms and conditions, and the Licensor grants You
 *  such rights in consideration of benefits the Licensor receives from
 *  making the Licensed Material available under these terms and
 *  conditions.
 *
 *  Refer to LICENSE file or https://creativecommons.org/licenses/by-nd/4.0 for full license.
 *
 */

package com.devsoap.tincheck.countries;

import com.devsoap.tincheck.tin.TinCountry;
import jakarta.inject.Singleton;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDate;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Getter
@Singleton
@RequiredArgsConstructor
@ToString(of = {"countryCode", "countryName"})
public class Country_BG implements TinCountry {

    private final String countryCode = "BG";
    private final String countryName = "Bulgaria";

    private static final int[] WEIGHTS = new int[]{2,4,8,5,10,9,7,3,6};

    @Override
    public String generate(LocalDate yearOfBirth, Gender gender, Random randomGenerator) {
        var year = StringUtils.leftPad((yearOfBirth.getYear() % 100) + "", 2, '0');

        var month = StringUtils.leftPad(yearOfBirth.getMonthValue()+"",2,'0');
        if (yearOfBirth.isBefore(LocalDate.of(1990,1,1))) {
            month = StringUtils.leftPad((20 + yearOfBirth.getMonthValue())+"",2,'0');
        } else if(yearOfBirth.isAfter(LocalDate.of(1999,12,31))) {
            month = StringUtils.leftPad((40 + yearOfBirth.getMonthValue())+"",2,'0');
        }

        var day = StringUtils.leftPad(yearOfBirth.getDayOfMonth()+"",2,'0');
        var rand = randomGenerator.ints(3, 0,10)
                .mapToObj(i -> i+"")
                .collect(Collectors.joining());
        return year + month + day + rand + generateCheckDigit(year+month+day+rand);
    }

    @Override
    public boolean formatCheck(String tin) {
        return StringUtils.isNumeric(tin) && tin.length() == 10;
    }

    private int generateCheckDigit(String tin) {
        var digits = extractDigits(tin);
        var sum = IntStream.range(0,9)
                .map(i -> digits[i] * WEIGHTS[i])
                .sum() % 11;
       return sum == 10 ? 0 : sum;
    }

}