package cz.moneta.test.dsl.hypos.pages.hypokalkulacka;

import cz.moneta.test.dsl.hypos.pages.HyposPageFlow;
import cz.moneta.test.dsl.util.DateUtils;
import cz.moneta.test.dsl.util.data.hypos.HyposContract;
import cz.moneta.test.dsl.util.data.hypos.OtherIncome;
import cz.moneta.test.harness.context.StoreAccessor;
import cz.moneta.test.harness.endpoints.hypos.HyposEndpoint;
import cz.moneta.test.harness.support.web.*;

import java.util.Optional;

import static cz.moneta.test.dsl.hypos.enums.OtherIncomeType.*;
import static cz.moneta.test.dsl.hypos.pages.hypokalkulacka.HypokalkulackaClientIncomePage.SAVE_INCOME_BUTTON;

@Wait(value = SAVE_INCOME_BUTTON, until = Until.VISIBLE)
public interface HypokalkulackaClientIncomePage extends HyposPageFlow<HypokalkulackaClientIncomePage>, StoreAccessor {
    String MAIN_INCOME_TABLE = "//table[@id='form-main-income']";

    String EMPLOYEE_INCOME_GROSS_INPUT = MAIN_INCOME_TABLE + "//input[@id='income-salary-gross']";
    String EMPLOYEE_INCOME_NET_INPUT = MAIN_INCOME_TABLE + "//input[@id='income-salary-net']";
    String EMPLOYEE_INCOME_CURRENCY_SELECT = MAIN_INCOME_TABLE + "//select[@id='income-employee-currency']";
    String EMPLOYEE_INCOME_ICO_INPUT = MAIN_INCOME_TABLE + "//input[@id='income-ico']";
    String EMPLOYEE_INCOME_START_DATE_INPUT = MAIN_INCOME_TABLE + "//input[@id='income-emp-date']";
    String EMPLOYEE_INCOME_TYPE_INPUT = MAIN_INCOME_TABLE + "//select[@id='income-type']";
    String EMPLOYEE_INCOME_PROFESSION_INPUT = MAIN_INCOME_TABLE + "//input[@id='income-profession']";
    String EMPLOYEE_INCOME_PHONE_INPUT = MAIN_INCOME_TABLE + "//input[@id='income-corp-phone']";
    String EMPLOYEE_INCOME_SPECIAL_RELATION_CHECKBOX = MAIN_INCOME_TABLE + "//input[@id='income-special-relation-no']";
    String EMPLOYEE_INCOME_DETAIL_BUTTON = MAIN_INCOME_TABLE + "//a[contains(@class,'income-main-detailed-link')]";

    String BUSINESS_INCOME_TURNOVER_LATEST_INPUT = "//input[@id='income-business-turnover-latest']";
    String BUSINESS_INCOME_TAX_BASE_LATEST_INPUT = "//input[@id='income-business-tax-base-latest']";
    String BUSINESS_INCOME_PAID_TAX_INPUT = "//input[@id='income-business-paid-tax']";
    String BUSINESS_INCOME_COST_ACCOUNTING_SELECT = "//select[@id='income-business-cost-accounting']";
    String BUSINESS_INCOME_CODE_INPUT = "//input[@id='income-business-code']/preceding-sibling::input";
    String BUSINESS_INCOME_CODE_LINK = "//ul[contains(@class,'ui-autocomplete')]//a[contains(text(),'%s')]";
    String BUSINESS_INCOME_TURNOVER_PENULTIMATE_INPUT = "//input[@id='income-business-turnover-penultimate']";
    String BUSINESS_INCOME_TAX_BASE_PENULTIMATE_INPUT = "//input[@id='income-business-tax-base-penultimate']";
    String BUSINESS_INCOME_ICO_INPUT = "//input[@id='income-business-ico']";
    String BUSINESS_INCOME_START_INPUT = "//input[@id='income-business-start']";
    String BUSINESS_INCOME_CURRENCY_SELECT = "//select[@id='income-business-currency']";
    String BUSINESS_INCOME_PHONE_INPUT = "//input[@id='income-business-corp-phone']";
    String BUSINESS_INCOME_DETAIL_BUTTON = "//a[contains(@class,'income-business-detailed-link')]";

    String OTHER_INCOME_INPUT = "//input[@id='income-%s']";
    String OTHER_INCOME_CURRENCY_SELECT = "//select[@id='income-%s-currency']";
    String OTHER_INCOME_PAID_TO_MMB_CHECKBOX = "//input[@id='%1$s-paid-to-mmb-%2$s']";
    String OTHER_INCOME_PARENTAL_CONTRIBUTION_DATE = "//input[@id='income-parental-contribution-date']";
    String OTHER_INCOME_COOPERATOVE_FLAT_RENTAL = "//input[@id='q-cooperative-flat-rental-n']";
    String OTHER_INCOME_OWN_COMPANY_RENTAL = "//input[@id='q-own-company-rental-n']";
    String OTHER_INCOME_OWN_PLEDGE_RENTAL = "//input[@id='q-own-pledge-rental-n']";
    String SAVE_INCOME_BUTTON = MAIN_INCOME_TABLE + "//following::div/input[@value='Uložit']";
    String INCOME_TAB = "(//div[@id='income-tabs']//span[contains(text(),'%1$s')])[%2$s]";
    String ADD_INCOME = "//div[@id='add-income']";
    String ADD_INCOME_SUBMIT = "//button[@id='submit-add-income']";

    @TypeInto(EMPLOYEE_INCOME_GROSS_INPUT)
    HypokalkulackaClientIncomePage fillGrossSalary(int grossSalary);

    @TypeInto(EMPLOYEE_INCOME_NET_INPUT)
    HypokalkulackaClientIncomePage fillNetSalary(int netSalary);

    @Select(EMPLOYEE_INCOME_CURRENCY_SELECT)
    HypokalkulackaClientIncomePage selectCurrencyForEmployee(String currency);

    @TypeInto(EMPLOYEE_INCOME_ICO_INPUT)
    @KeyPress(value = Key.ENTER, andWait = @Wait(value = LOADER, until = Until.GONE))
    HypokalkulackaClientIncomePage fillEmployerIco(String ico);

    @TypeInto(EMPLOYEE_INCOME_START_DATE_INPUT)
    HypokalkulackaClientIncomePage fillEmploymentStartDate(String startDate);

    @Select(EMPLOYEE_INCOME_TYPE_INPUT)
    HypokalkulackaClientIncomePage fillEmploymentType(String employmentType);

    @TypeInto(EMPLOYEE_INCOME_PROFESSION_INPUT)
    HypokalkulackaClientIncomePage fillProfession(String profession);

    @Click(EMPLOYEE_INCOME_SPECIAL_RELATION_CHECKBOX)
    HypokalkulackaClientIncomePage clickSpecialRelation();

    @TypeInto(value = EMPLOYEE_INCOME_PHONE_INPUT, clear = true)
    HypokalkulackaClientIncomePage fillCorpPhone(String phone);

    @Click(EMPLOYEE_INCOME_DETAIL_BUTTON)
    HypokalkulackaClientIncomeEmployeeDetailPage clickIncomeEmployeeDetails();

    @Click(BUSINESS_INCOME_DETAIL_BUTTON)
    HypokalkulackaClientIncomeBusinessDetailPage clickIncomeBusinessDetails();

    @TypeInto(BUSINESS_INCOME_TURNOVER_LATEST_INPUT)
    HypokalkulackaClientIncomePage fillTurnoverLatest(int turnoverLatest);

    @TypeInto(BUSINESS_INCOME_TAX_BASE_LATEST_INPUT)
    HypokalkulackaClientIncomePage fillTaxBaseLatest(int taxBaseLatest);

    @TypeInto(BUSINESS_INCOME_PAID_TAX_INPUT)
    HypokalkulackaClientIncomePage fillPaidTax(int paidTax);

    @TypeInto(value = BUSINESS_INCOME_CODE_INPUT)
    HypokalkulackaClientIncomePage fillCode(String code);

    @Click(value = BUSINESS_INCOME_CODE_LINK, isStringDynamicXpath = true)
    HypokalkulackaClientIncomePage clickCode(String code);

    @TypeInto(BUSINESS_INCOME_TURNOVER_PENULTIMATE_INPUT)
    HypokalkulackaClientIncomePage fillTurnoverPenultimate(int turnoverPenultimate);

    @TypeInto(BUSINESS_INCOME_TAX_BASE_PENULTIMATE_INPUT)
    HypokalkulackaClientIncomePage fillTaxBasePenultimate(int taxBasePenultimate);

    @TypeInto(BUSINESS_INCOME_ICO_INPUT)
    HypokalkulackaClientIncomePage fillBusinessIco(String ico);

    @TypeInto(BUSINESS_INCOME_START_INPUT)
    HypokalkulackaClientIncomePage fillBusinessStartDate(String businessStartDate);

    @TypeInto(value = BUSINESS_INCOME_PHONE_INPUT, clear = true)
    HypokalkulackaClientIncomePage fillBusinessCorpPhone(String phone);

    @Select(BUSINESS_INCOME_COST_ACCOUNTING_SELECT)
    HypokalkulackaClientIncomePage selectCostAccounting(String costAccounting);

    @Select(value = BUSINESS_INCOME_CURRENCY_SELECT, andWait = @Wait(value = SAVE_INCOME_BUTTON, until = Until.VISIBLE))
    HypokalkulackaClientIncomePage selectCurrencyForBusiness(String currency);

    @Click(value = SAVE_INCOME_BUTTON)
    HypokalkulackaPage clickSaveIncomeButton();

    @CustomAction
    default HypokalkulackaClientIncomePage selectTab(String incomeType, String income) {
        HyposEndpoint endpoint = getEndpoint(HyposEndpoint.class);
        endpoint.click(() -> String.format(INCOME_TAB, incomeType, income));
        return null;
    }

    @CustomAction
    default HypokalkulackaPage addOtherIncomeEmployee(HyposContract hyposContract, int client) {
        HyposEndpoint endpoint = getEndpoint(HyposEndpoint.class);
        hyposContract.getClients().get(client).getEmployeeIncomes().stream()
                .skip(1)
                .forEach(employeeIncome -> {
                    endpoint.click(() -> ADD_INCOME);
                    endpoint.click(() -> ADD_INCOME_SUBMIT);
                    endpoint.type(() -> EMPLOYEE_INCOME_GROSS_INPUT, String.valueOf(employeeIncome.getGrossSalary()), false);
                    endpoint.type(() -> EMPLOYEE_INCOME_NET_INPUT, String.valueOf(employeeIncome.getNetSalary()), false);
                    endpoint.type(() -> EMPLOYEE_INCOME_ICO_INPUT, employeeIncome.getIco(), false);
                    endpoint.type(() -> EMPLOYEE_INCOME_START_DATE_INPUT, employeeIncome.getStartDate(), false);
                    endpoint.selectByVisibleText(EMPLOYEE_INCOME_TYPE_INPUT, employeeIncome.getType());
                    endpoint.type(() -> EMPLOYEE_INCOME_PHONE_INPUT, employeeIncome.getPhone(), true);
                    endpoint.type(() -> EMPLOYEE_INCOME_PROFESSION_INPUT, employeeIncome.getProfession(), false);
                    endpoint.click(() -> EMPLOYEE_INCOME_SPECIAL_RELATION_CHECKBOX);
                    endpoint.selectByVisibleText(EMPLOYEE_INCOME_CURRENCY_SELECT, employeeIncome.getCurrency());
                });
        endpoint.click(() -> SAVE_INCOME_BUTTON);
        return null;
    }

    @CustomAction
    default HypokalkulackaClientIncomePage setOtherIncomes(HyposContract hyposContract, int client) {
        HyposEndpoint endpoint = getEndpoint(HyposEndpoint.class);
        hyposContract.getClients().get(client).getOtherIncomes()
                .forEach(otherIncome -> {
                    endpoint.type(() -> String.format(OTHER_INCOME_INPUT, otherIncome.getType()), otherIncome.getAmount(), false);
                    endpoint.selectByVisibleText(String.format(OTHER_INCOME_CURRENCY_SELECT, otherIncome.getType()), otherIncome.getCurrency());
                    if (otherIncome.getPaidToMmb() != null) {
                        endpoint.click(() -> String.format(OTHER_INCOME_PAID_TO_MMB_CHECKBOX, otherIncome.getType(), otherIncome.getPaidToMmb()));
                    }
                    if (otherIncome.getType().equals(PARENTAL_CONTRIBUTION.getValue())) {
                        endpoint.type(() -> OTHER_INCOME_PARENTAL_CONTRIBUTION_DATE,
                                DateUtils.getTodayDateIncrementedByDays(-30, "dd.MM.yyyy"), false);
                    }
                });
        return null;
    }

    @CustomAction
    default HypokalkulackaClientIncomePage clickIncomesRental(HyposContract hyposContract, int client) {
        HyposEndpoint endpoint = getEndpoint(HyposEndpoint.class);
        Optional<OtherIncome> rentalIncome = hyposContract.getClients().get(client).getOtherIncomes().stream()
                .filter(type -> type.getType().equals(RENTAL_ALLOWANCE_GROSS.getValue())
                        || type.getType().equals(RENTAL_ALLOWANCE_TAX_RETURN.getValue())
                        || type.getType().equals(RENTAL_ALLOWANCE.getValue()))
                .findAny();

        if (rentalIncome.isPresent()) {
            endpoint.click(() -> OTHER_INCOME_COOPERATOVE_FLAT_RENTAL);
            endpoint.click(() -> OTHER_INCOME_OWN_COMPANY_RENTAL);
            endpoint.click(() -> OTHER_INCOME_OWN_PLEDGE_RENTAL);
        }
        return null;
    }
}