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

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.hypos.contractPrepare.data.*;
import cz.moneta.test.dsl.util.TestUtils;
import cz.moneta.test.dsl.util.data.hypos.*;
import lombok.Builder;
import lombok.Getter;

import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Builder
@Getter
public class HyposClient {
    private NonClient nonClient;
    private String stayType;
    private String livingType;
    private String clientRelation;
    private BusinessIncome businessIncome;
    private List<EmployeeIncome> employeeIncomes;
    private List<OtherIncome> otherIncomes;
    private List<Expenditure> expenditures;
    private String household;
    private String firstIdentityType;
    private String secondIdentityType;
    private String cardifType;
    private Boolean employee;
    private String pep;

    /**
     * Creating new address used for prepare contract data.
     *
     * @return Address with yaml data.
     */
    private Address createAddress(HyposAddressYamlData hyposAddressYamlData) {
        return Address.builder()
                .street(hyposAddressYamlData.getStreet())
                .descriptiveNumber(hyposAddressYamlData.getDescriptiveNumber())
                .orientationNumber(hyposAddressYamlData.getOrientationNumber())
                .city(hyposAddressYamlData.getCity())
                .zip(hyposAddressYamlData.getZip())
                .country(hyposAddressYamlData.getCountry())
                .build();
    }

    /**
     * Creating new NonClient object used for prepare contract data with generated person.
     *
     * @return NonClient with yaml/default data.
     */
    private NonClient createNonClient(HyposClientYamlData hyposClientYamlData, Harness harness) {
        String birthNumber = harness.tasks().common().getRcMinMaxAge(20, 30);
        return harness.data().newNonClient()
                .withBirthNumber(birthNumber)
                .withEmail(TestUtils.getEmailBasedOnRc(birthNumber))
                .withPlaceOfBirth(hyposClientYamlData.getPlaceOfBirth())
                .withNationality(hyposClientYamlData.getNationality())
                .withMaritalStatus(MaritalStatus.SINGLE)
                .withEducationLevel(EducationLevel.HIGHER)
                .withOccupationStatus(OccupationStatus.FULL_TIME_EMPLOYEE)
                .withOccupationType(OccupationType.IT_GUYS)
                .withAccommodationType(AccommodationType.PARENTS)
                .withResidencyAddress(this.createAddress(hyposClientYamlData.getResidencyAddress()))
                .withIdCard(new IdCard("207373011", LocalDate.now(), LocalDate.now().plusYears(5)));
    }

    /**
     * Creating new NonClient object used for prepare contract data with specific person.
     *
     * @return NonClient with yaml/default data.
     */
    private NonClient createNonClient(HyposClientYamlData hyposClientYamlData, Person person, Harness harness) {
        return harness.data().newNonClient()
                .withBirthNumber(person.getBirthNumber())
                .withEmail(TestUtils.getEmailBasedOnRc(person.getBirthNumber()))
                .withFirstName(person.getFirstName())
                .withLastName(person.getLastName())
                .withPlaceOfBirth(hyposClientYamlData.getPlaceOfBirth())
                .withNationality(hyposClientYamlData.getNationality())
                .withMaritalStatus(MaritalStatus.SINGLE)
                .withEducationLevel(EducationLevel.HIGHER)
                .withOccupationStatus(OccupationStatus.FULL_TIME_EMPLOYEE)
                .withOccupationType(OccupationType.IT_GUYS)
                .withAccommodationType(AccommodationType.PARENTS)
                .withResidencyAddress(this.createAddress(hyposClientYamlData.getResidencyAddress()))
                .withIdCard(new IdCard("207373011", LocalDate.now(), LocalDate.now().plusYears(5)));
    }

    /**
     * Creating new expenditures used for prepare contract data.
     *
     * @return List<Expenditure> with yaml data.
     */
    private List<Expenditure> createExpenditures(List<ExpenditureYamlData> expenditureYamlData) {
        return expenditureYamlData.stream()
                .map(m -> Expenditure.builder()
                        .type(m.getType())
                        .amount(m.getAmount())
                        .correction(m.getCorrection())
                        .build())
                .collect(Collectors.toList());
    }

    /**
     * Creating new other incomes used for prepare contract data.
     *
     * @return List<OtherIncome> with yaml data.
     */
    private List<OtherIncome> createOtherIncomes(List<OtherIncomeYamlData> otherIncomeYamlData) {
        if (otherIncomeYamlData == null) return Collections.emptyList();
        return otherIncomeYamlData.stream()
                .map(m -> OtherIncome.builder()
                        .type(m.getType())
                        .amount(m.getAmount())
                        .currency(m.getCurrency())
                        .paidToMmb(m.getPaidToMmb())
                        .build())
                .collect(Collectors.toList());
    }

    /**
     * Creating new other incomes used for prepare contract data.
     *
     * @return List<OtherIncome> with yaml data.
     */
    private BusinessIncome createBusinessIncomes(BusinessIncomeYamlData businessIncomeYamlData) {
        if (businessIncomeYamlData == null) return null;
        return BusinessIncome.builder()
                .turnoverLatest(businessIncomeYamlData.getTurnoverLatest())
                .taxBaseLatest(businessIncomeYamlData.getTaxBaseLatest())
                .paidTax(businessIncomeYamlData.getPaidTax())
                .costAccounting(businessIncomeYamlData.getCostAccounting())
                .naceCode(businessIncomeYamlData.getNaceCode())
                .turnoverPenultimate(businessIncomeYamlData.getTurnoverPenultimate())
                .taxBasePenultimate(businessIncomeYamlData.getTaxBasePenultimate())
                .ico(businessIncomeYamlData.getIco())
                .currency(businessIncomeYamlData.getCurrency())
                .startDate(businessIncomeYamlData.getStartDate())
                .build();
    }

    /**
     * Creating new employee incomes used for prepare contract data.
     *
     * @return List<EmployeeIncome> with yaml data.
     */
    private List<EmployeeIncome> createEmployeeIncomes(List<EmployeeIncomeYamlData> employeeIncomeYamlData) {
        if (employeeIncomeYamlData == null) return Collections.emptyList();
        return employeeIncomeYamlData.stream()
                .map(m -> EmployeeIncome.builder()
                        .grossSalary(m.getGrossSalary())
                        .netSalary(m.getNetSalary())
                        .ico(m.getIco())
                        .startDate(m.getStartDate())
                        .type(m.getType())
                        .profession(m.getProfession())
                        .phone(m.getPhone())
                        .currency(m.getCurrency())
                        .build())
                .collect(Collectors.toList());
    }

    /**
     * Creating new clients used for prepare contract data.
     *
     * @return List<HyposClient> with yaml data.
     */
    public List<HyposClient> createHyposClients(HyposContractYamlData hyposContractYamlData, Person person, Harness harness) {
        return hyposContractYamlData.getClients().stream()
                .map(m -> HyposClient.builder()
                        .nonClient(person == null ? this.createNonClient(m, harness) : this.createNonClient(m, person, harness))
                        .stayType(m.getStayType())
                        .livingType(m.getLivingType())
                        .otherIncomes(this.createOtherIncomes(m.getOtherIncomes()))
                        .businessIncome(this.createBusinessIncomes(m.getBusinessIncomes()))
                        .employeeIncomes(this.createEmployeeIncomes(m.getEmployeeIncomes()))
                        .expenditures(this.createExpenditures(m.getExpenditures()))
                        .firstIdentityType(m.getFirstIdentityType())
                        .secondIdentityType(m.getSecondIdentityType())
                        .cardifType(m.getCardifType())
                        .clientRelation(m.getClientRelation())
                        .household(m.getHousehold())
                        .employee(m.getEmployee())
                        .pep(m.getPep())
                        .build())
                .collect(Collectors.toList());
    }
}