package cz.moneta.test.regression.commercial.smallbusiness.digital.backendtests;

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.wso2.objects.smallbusiness.DoSmeDepositProductOfferRequest;
import cz.moneta.test.dsl.wso2.objects.smallbusiness.DoSmeDepositProductOfferResponse;
import cz.moneta.test.harness.annotations.JiraTestCase;
import cz.moneta.test.harness.annotations.TestCase;
import cz.moneta.test.harness.annotations.TestScenario;
import org.junit.jupiter.api.Order;

import java.util.Arrays;
import java.util.Set;

import static cz.moneta.test.harness.annotations.Environment.TST1;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

@TestScenario(name = "Deposit product offer does not return duplicated fee plans for saving account.")
public class DoSmeDepositProductOfferTest {

    @TestCase(name = "Health worker resident new to bank - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1164")
    @Order(1)
    public void smeDepositOffer_healthWorkersResidentNTB_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderNewToBank()
                .clientType("2")
                .legalFormId(null)
                .nace("1750000")
                .residence("1")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Health worker non resident new to bank - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1165")
    @Order(2)
    public void smeDepositOffer_healthWorkersNonResidentNTB_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderNewToBank()
                .clientType("2")
                .legalFormId(null)
                .nace("1750000")
                .residence("2")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Company notary resident - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1166")
    @Order(3)
    public void smeDepositOffer_companyNotaryResident_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderNewToBank()
                .clientType("3")
                .legalFormId(null)
                .nace("1691000")
                .residence("1")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Entrepreneur notary resident - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1167")
    @Order(4)
    public void smeDepositOffer_entrepreneurNotaryResident_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderNewToBank()
                .clientType("2")
                .legalFormId(null)
                .nace("1691000")
                .residence("1")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Municipality resident new to bank - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1168")
    @Order(5)
    public void smeDepositOffer_municipalitiesResidentNewToBank_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderNewToBank()
                .clientType("3")
                .legalFormId("711")
                .nace("1841000")
                .residence("1")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Municipality resident client - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1169")
    @Order(6)
    public void smeDepositOffer_municipalitiesResidentClient_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderClient()
                .clientType("3")
                .legalFormId("711")
                .nace("1841000")
                .residence("1")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Municipality non resident new to bank - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1170")
    @Order(7)
    public void smeDepositOffer_municipalitiesNonResidentClient_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderNewToBank()
                .clientType("3")
                .legalFormId("711")
                .nace("1841000")
                .residence("2")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Religious organisation resident new to bank - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1171")
    @Order(8)
    public void smeDepositOffer_religiousOrganisationResidentNewToBank_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderNewToBank()
                .clientType("3")
                .legalFormId("721")
                .nace("1949100")
                .residence("1")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Religious organisation resident client - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1172")
    @Order(9)
    public void smeDepositOffer_religiousOrganisationResidentClient_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderClient()
                .clientType("3")
                .legalFormId("721")
                .nace("1949100")
                .residence("1")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Housing cooperative associations resident new to bank - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1173")
    @Order(10)
    public void smeDepositOffer_housingCooperativeAssociationsResidentNewToBank_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderNewToBank()
                .clientType("3")
                .legalFormId("145")
                .nace("1410000")
                .residence("1")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Housing cooperative associations non resident new to bank - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1174")
    @Order(11)
    public void smeDepositOffer_housingCooperativeAssociationsNonResidentNewToBank_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderNewToBank()
                .clientType("3")
                .legalFormId("145")
                .nace("1410000")
                .residence("2")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Housing cooperative associations resident new to bank - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1175")
    @Order(12)
    public void smeDepositOffer_housingCooperativeAssociationsResidentClient_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderClient()
                .clientType("3")
                .legalFormId("145")
                .nace("1410000")
                .residence("1")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Housing cooperative associations non resident client - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1176")
    @Order(13)
    public void smeDepositOffer_housingCooperativeAssociationsNonResidentClient_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderClient()
                .clientType("3")
                .legalFormId("145")
                .nace("1410000")
                .residence("2")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Non bank institution resident - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1177")
    @Order(14)
    public void smeDepositOffer_nonBankInstitutionsResident_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderClient()
                .clientType("3")
                .legalFormId(null)
                .nace("1642000")
                .residence("1")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Bank institution resident - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1178")
    @Order(15)
    public void smeDepositOffer_bankInstitutionsResident_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderClient()
                .clientType("3")
                .legalFormId(null)
                .nace("1641900")
                .residence("1")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Entrepreneur resident new to bank - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1163")
    @Order(16)
    public void smeDepositOffer_entrepreneurResidentNewToBank_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderNewToBank()
                .clientType("2")
                .legalFormId(null)
                .nace("1014700")
                .residence("1")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Entrepreneur resident client - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1179")
    @Order(17)
    public void smeDepositOffer_entrepreneurResidentClient_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderClient()
                .clientType("2")
                .legalFormId(null)
                .nace("1014700")
                .residence("1")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Entrepreneur non resident new to bank - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1180")
    @Order(18)
    public void smeDepositOffer_entrepreneurNonResidentNewToBank_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderNewToBank()
                .clientType("2")
                .legalFormId(null)
                .nace("1014700")
                .residence("2")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Entrepreneur non resident client - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1181")
    @Order(19)
    public void smeDepositOffer_entrepreneurNonResidentClient_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderClient()
                .clientType("2")
                .legalFormId(null)
                .nace("1014700")
                .residence("2")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Company resident new to bank - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1182")
    @Order(20)
    public void smeDepositOffer_companyResidentNewToBank_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderNewToBank()
                .clientType("3")
                .legalFormId(null)
                .nace("1014700")
                .residence("1")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Company resident client - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1183")
    @Order(21)
    public void smeDepositOffer_companyResidentClient_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderClient()
                .clientType("3")
                .legalFormId(null)
                .nace("1014700")
                .residence("1")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Company non resident new to bank - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1184")
    @Order(22)
    public void smeDepositOffer_companyNonResidentNewToBank_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderNewToBank()
                .clientType("3")
                .legalFormId(null)
                .nace("1014700")
                .residence("2")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Company non resident client - check for duplicate fee plans.", environments = {TST1})
    @JiraTestCase(id = "SBD-T1185")
    @Order(23)
    public void smeDepositOffer_companyNonResidentClient_shouldNotHaveDuplicatedOffer(Harness harness) {
        var request = requestBuilderClient()
                .clientType("3")
                .legalFormId(null)
                .nace("1014700")
                .residence("2")
                .build();

        var response = sendRequest(request, harness);

        assertFalse(hasDuplicates(response));
    }

    @TestCase(name = "Has duplicates - check for duplicate fee plans.", environments = {TST1})
    @Order(25)
    public void hasDuplicates() {
        var responseWithDuplicates = DoSmeDepositProductOfferResponse.builder()
                .rsData(Arrays.asList(DoSmeDepositProductOfferResponse.RsData.builder()
                                .feePlan("1")
                                .build(),
                        DoSmeDepositProductOfferResponse.RsData.builder()
                                .feePlan("1")
                                .build()))
                .build();

        var responseWithoutDuplicates = DoSmeDepositProductOfferResponse.builder()
                .rsData(Arrays.asList(DoSmeDepositProductOfferResponse.RsData.builder()
                                .feePlan("1")
                                .build(),
                        DoSmeDepositProductOfferResponse.RsData.builder()
                                .feePlan("2")
                                .build()))
                .build();

        assertTrue(hasDuplicates(responseWithDuplicates));
        assertFalse(hasDuplicates(responseWithoutDuplicates));
    }

    private DoSmeDepositProductOfferResponse sendRequest(DoSmeDepositProductOfferRequest request, Harness harness) {
        return harness.tasks().wso2().restRequest()
                .prepareRequestFromUfo("/t/small.business/NAS/GET_SME_DEPOSIT_PRODUCT_OFFER_007/001")
                .withHeader("Content-Type", "application/json")
                .withPojoPayload(request)
                .post()
                .andAssertStatus(200)
                .mapResponseIntoObject(DoSmeDepositProductOfferResponse.class);
    }

    private Boolean hasDuplicates(DoSmeDepositProductOfferResponse response) {
        Set<String> seen = new java.util.HashSet<>();
        return response.getRsData().stream()
                .map(DoSmeDepositProductOfferResponse.RsData::getFeePlan)
                .anyMatch(p -> !seen.add(p));
    }

    private DoSmeDepositProductOfferRequest.DoSmeDepositProductOfferRequestBuilder requestBuilderNewToBank() {
        return DoSmeDepositProductOfferRequest.builder()
                .channelId("POS")
                .cif(null)
                .prodClass("13")
                .currencyIn("0");
    }

    private DoSmeDepositProductOfferRequest.DoSmeDepositProductOfferRequestBuilder requestBuilderClient() {
        return DoSmeDepositProductOfferRequest.builder()
                .channelId("POS")
                .cif("9070182556")
                .prodClass("13")
                .currencyIn("0");
    }
}
