package cz.moneta.test.dsl.util.data.client;

import cz.moneta.test.dsl.util.TestUtils;
import cz.moneta.test.dsl.util.code.lists.HCisVztahKBanceCIF;
import cz.moneta.test.harness.context.StoreAccessor;
import cz.moneta.test.harness.support.data.DataProvider;
import cz.moneta.test.harness.support.data.Date;
import cz.moneta.test.harness.support.data.Generate;
import cz.moneta.test.harness.support.data.Value;

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

import static cz.moneta.test.harness.support.data.GeneratorType.*;

public interface NonClient extends DataProvider<NonClient>, StoreAccessor {

    @Generate(FIRST_NAME)
    String firstName();

    @Generate(LAST_NAME)
    String lastName();

    default String fullName() {
        return String.format("%s %s", firstName(), lastName());
    }

    @Generate(RC)
    String birthNumber();

    @Generate(RC)
    String birthNumber(LocalDate from, LocalDate to);

    @Value("Praha")
    String placeOfBirth();

    @Value("Česká republika")
    String nationality();

    @Value("208243633")
    String idNumber();

    @Value("09.06.2027")
    String idNumberExpiration();

    /**
     * Check digit for default id number or set by method withIdNumber(). Not for generated ID.
     */
    default String idNumberCheckDigit() {
        return generate(ID_CARD_CHECK_DIGIT, idNumber(), birthNumber(), LocalDate.parse(idNumberExpiration(), DateTimeFormatter.ofPattern("d.M.yyyy")));
    }

    @Value("31.08.2026")
    String drivingLicenceExpiration();

    /**
     * Generated ID Card.
     * It can be hard setted by "withIdCard(new IdCard(String number, LocalDate validFrom, LocalDate validTo)"
     */
    default IdCard idCard() {
        LocalDate startDate = LocalDate.now().minusYears(50);
        if (birthNumber() == null) {
            this.birthNumber(startDate, startDate.plusYears(23));
        }
        return generate(ID_CARD, birthNumber());
    }

    default IdCard idCard(LocalDate dateOfBirth) {
        String rc = birthNumber(dateOfBirth, dateOfBirth);
        return generate(ID_CARD, rc);
    }

    /**
     * Generated ID Card, if it hasn't been changed by "withIdCard()"
     */
    default String idCardNumber() {
        return idCard().getNumber();
    }

    /**
     * Generated ID Card expiration, if it hasn't been changed by "withIdCard()"
     */
    default java.util.Date idCardExpiredRaw() {
        return java.util.Date.from(idCard().getValidTo().atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    /**
     * Check digit for generated ID card.
     */
    default String idCardCheckDigit() {
        return generate(ID_CARD_CHECK_DIGIT, idCard().getNumber(), birthNumber(), idCard().getValidTo());
    }

    //FIXME after generator repaired in TA-398
    //@Generate(PASSPORT_NUMBER)
    @Value("40199969")
    String passportId();

    //FIXME after generator repaired in TA-398
    //@Date(plusDays = 720)
    @Date(dayOfMonth = 28, month = 7, year = 2026)
    java.util.Date passportExpiryDateRaw();

    @Value("EK608907")
    String driverLicenceId();

    @Date(plusDays = 720)
    java.util.Date driveLicenceExpiryDateRaw();

    @Generate(ICO)
    String ico();

    @Generate(RESIDENCY_ADDRESS)
    Address residencyAddress();

    default Address businessAddress() {
        return Address.builder()
                .street("Vinohradská")
                .descriptiveNumber("168")
                .orientationNumber("2356")
                .city("Praha")
                .zip("10000")
                .country("CZ")
                .build();
    }

    @Value("2000")
    Integer residencyAddressSinceYear();

    @Date(dayOfMonth = 28, month = 1, year = 2000)
    java.util.Date currentAddressSinceRaw();

    @Generate(MOBILE_PHONE_NUMBER)
    String mobileNumber();

    @Generate(FIX_LINE_PHONE_NUMBER)
    String fixPhoneNumberWork();

    @Generate(FIX_LINE_PHONE_NUMBER)
    String fixPhoneNumberHome();

    @Value("dummy.A1A2A3A4A5A6A7A8@moneta.cz")
    String email();

    default MaritalStatus maritalStatus() {
        return MaritalStatus.SINGLE;
    }

    @Value("")
    String restrictedJoinedAssets();

    @Value("2000")
    Integer currentAddressSinceYear();

    default AccommodationType accommodationType() {
        return AccommodationType.OWN;
    }

    default EducationLevel educationLevel() {
        return EducationLevel.HIGHER;
    }

    default OccupationStatus occupationStatus() {
        return OccupationStatus.FULL_TIME_EMPLOYEE;
    }

    default OccupationType occupationType() {
        return OccupationType.MANAZER_REDITEL;
    }

    default IncomeType incomeType() {
        return IncomeType.EMPLOYMENT_INCOME;
    }

    default IncomeSubtype incomeSubtype() {
        return IncomeSubtype.EMPLOYMENT_PER_INDEFINITE;
    }

    @Generate(EMPLOYER)
    Employer employer();

    @Date(dayOfMonth = 1, month = 1, year = 2000)
    java.util.Date occupationEmploymentFromRaw();

    @Date(dayOfMonth = 1, month = 1, year = 2025)
    java.util.Date occupationEmploymentTillRaw();

    @Date(minusDays = 1)
    java.util.Date dateOfIssueConfirmationOfReceipt();

    @Value("it programátor/software developer")
    String occupationAdditionalInformation();

    @Value("false")
    boolean occupationTrialPeriod();

    @Value("false")
    boolean occupationOnNotice();

    @Value("true")
    boolean consentsDataProcessing();

    @Value("true")
    boolean consentsDebtRegisterCheck();

    @Value("")
    String familyBusiness();

    @Value("")
    String familyBusinessPercentage();

    @Value("60000")
    int netMonthlyIncome();

    default int netMonthlyIncomeInThousands() {
        return Math.round(netMonthlyIncome() / 1000);
    }

    @Value("70000")
    int homeIncome();

    @Value("1")
    String incomeSources();

    @Value("")
    String incomeTaxBase();

    @Value("0")
    Integer grossIncome();

    @Value("")
    String tax();

    @Value("")
    String taxableYear();

    @Value("0")
    int dependants();

    @Value("0")
    int otherLoanPayments();

    @Value("0")
    int wageDeductions();

    @Value("0")
    int otherExpenses();

    @Value("1000")
    int housingExpenses();

    @Value("1500000")
    int turnover();

    @Value("1200000")
    int netAnnuallyBusinessProfit();

    @Value("120000")
    int netMonthlyHouseholdIncome();

    default Gender gender() { return Gender.MAN; }

    default HCisVztahKBanceCIF relationshipToTheBank() {
        return HCisVztahKBanceCIF.NONE;
    }

    default String birthDate() {
        return TestUtils.parseBirthDateAsString(birthNumber());
    }

    NonClient withFirstName(String firstName);

    NonClient withLastName(String lastName);

    NonClient withBirthNumber(String birthNumber);

    NonClient withPlaceOfBirth(String placeOfBirth);

    NonClient withNationality(String nationality);

    NonClient withIdNumber(String idNumber);

    NonClient withIdNumberExpiration(String idNumberExpiration);

    NonClient withIdCard(IdCard idCard);

    NonClient withPassportId(String passportId);

    NonClient withPassportExpiryDateRaw(java.util.Date passportExpiryDateRaw);

    NonClient withDriverLicenceId(String driverLicenceId);

    NonClient withDriveLicenceExpiryDateRaw(java.util.Date driveLicenceExpiryDateRaw);

    NonClient withResidencyAddress(Address residencyAddress);

    NonClient withResidencyAddressSinceYear(Integer residencyAddressSinceYear);

    NonClient withCurrentAddressSinceRaw(java.util.Date currentAddressSinceRaw);

    NonClient withBusinessAddress(Address businessAddress);

    NonClient withMobileNumber(String mobileNumber);

    NonClient withFixPhoneNumberWork(String fixPhoneNumberWork);

    NonClient withFixPhoneNumberHome(String fixPhoneNumberHome);

    NonClient withEmail(String email);

    NonClient withMaritalStatus(MaritalStatus maritalStatus);

    NonClient withAccommodationType(AccommodationType accommodationType);

    NonClient withEducationLevel(EducationLevel educationLevel);

    NonClient withOccupationStatus(OccupationStatus occupationStatus);

    NonClient withOccupationType(OccupationType occupationType);

    NonClient withOccupationEmploymentFromRaw(java.util.Date occupationEmploymentFromRaw);

    NonClient withOccupationEmploymentTillRaw(java.util.Date occupationEmploymentTillRaw);

    NonClient withEmployer(Employer employer);

    NonClient withDateOfIssueConfirmationOfReceipt(java.util.Date dateOfIssueConfirmationOfReceipt);

    NonClient withOccupationAdditionalInformation(String occupationAdditionalInformation);

    NonClient withOccupationTrialPeriod(boolean occupationTrialPeriod);

    NonClient withOccupationOnNotice(boolean occupationOnNotice);

    NonClient withConsentsDataProcessing(boolean consentsDataProcessing);

    NonClient withConsentsDebtRegisterCheck(boolean consentsDebtRegisterCheck);

    NonClient withFamilyBusiness(String familyBusiness);

    NonClient withFamilyBusinessPercentage(String familyBusinessPercentage);

    NonClient withNetMonthlyIncome(int netMonthlyIncome);

    NonClient withNetMonthlyIncomeInThousands(int netMonthlyIncomeInThousands);

    NonClient withHomeIncome(int homeIncome);

    NonClient withIncomeTaxBase(String incomeTaxBase);

    NonClient withGrossIncome(Integer grossIncome);

    NonClient withTax(String tax);

    NonClient withTaxableYear(String taxableYear);

    NonClient withDependants(int dependants);

    NonClient withOtherLoanPayments(int otherLoanPayments);

    NonClient withWageDeductions(int wageDeductions);

    NonClient withOtherExpenses(int otherExpenses);

    NonClient withHousingExpenses(int housingExpenses);

    NonClient withIco(String ico);

    NonClient withIncomeSources(String incomeSources);

    NonClient withRelationshipToTheBank(HCisVztahKBanceCIF relationshipToTheBank);

    NonClient withIncomeType(IncomeType incomeType);

    NonClient withIncomeSubtype(IncomeSubtype incomeSubtype);

    NonClient withGender(Gender gender);

}
