package cz.moneta.test.dsl.hypos.pages.contract.realty;

import cz.moneta.test.dsl.hypos.components.Menu;
import cz.moneta.test.dsl.hypos.pages.HyposPageFlow;
import cz.moneta.test.harness.endpoints.hypos.HyposEndpoint;
import cz.moneta.test.harness.support.web.*;
import org.junit.jupiter.api.Assertions;

import java.util.Arrays;

import static cz.moneta.test.dsl.hypos.pages.contract.realty.ValuationDetailPage.H1_ORDERVALUATION;

@Wait(value = H1_ORDERVALUATION, waitSecondsForElement = 180)
public interface ValuationDetailPage extends HyposPageFlow<ValuationDetailPage>, Menu {
    String autoComment = "Automation Test";

    String H1_ORDERVALUATION = "//h1[text()='Objednávka ocenění']";
    String H2_RISKS = "//h2[text()='Rizika a stanovení podmínek']";
    String H2_FINAL = "//h2[text()='Finální ocenění']";
    String H3_COMPARATIVE_METHOD = "//h3[text()='Porovnávací metoda']";
    String H3_VALUATIONCOMPLETED = "//h3[text()='Ocenění bylo uloženo']";
    String H2_REALTYDESCRIPTION = "//h2[text()='Popis nemovitosti']";

    String A_TAKE = "//a[@id='assign-link']";
    String A_GIVE = "//a[@id='forward-link']";
    String A_DEFER = "//a[@id='delay-link']";
    String A_CANCEL = "//a[@id='cancel-link']";
    String A_PROCESSORDER = "//a[@id='final-valuation-process' and contains(text(),'Zpracovat')]";

    String TD_LASTOPERATION = "//table[@id='appr-order-events']/tbody/tr[1]/td[2]";
    String TD_LASTOPERATION_COMMENT = "//table[@id='appr-order-events']/tbody/tr[1]/td[3]";
    String TD_VALUATIONTYPE = "//th[text()='Způsob zpracování - výchozí']/following-sibling::td[1]";

    String INPUT_GIVE_ORDER = "//input[@value='Předat objednávku']";
    String INPUT_DEFER_ORDER = "//input[@value='Odložit objednávku']";
    String INPUT_DELAY_UNTIL = "//input[@name='delayUntil']";
    String INPUT_CANCEL = "//input[@value='Zrušit objednávku']";
    String INPUT_CURRENT_PRICE = "//input[@name='final_valuation[results][data][current_price]']";
    String INPUT_JKSO_PRICE = "//input[@id='results-auto-reproduction-price-flat']";
    String INPUT_REPRODUCTIVE_PRICE = "//input[@id='results-reproduction-price-flat']";
    String INPUT_FLAT_AREA = "//input[@id='flat-floor-area']";
    String INPUT_FLAT_AREA_OTHER = "//input[@id='flat-floor-area-other']";
    String INPUT_LOCAL_INVESTIGATION_DATE = "//input[@id='results-local-investigation-date']";

    String SELECT_FLAT_HEATING = "//select[@id='flat-heating']";
    String SELECT_FLAT_HEATING_MEDIUM = "//select[@name='realty[flat][unit_heating_medium_tp]']";
    String CHECKBOX_FLAT_AIRCONDITION = "//input[@name='realty[flat][unit_airconditioning_system_flag]' and @value='0']";
    String INPUT_BUILD_APART_CNT = "//input[@id='build-apart-cnt']";
    String CHECKBOX_BUILD_GAS = "//input[@name='realty[flat_building][build_conn_gas_distr_flag]' and @value='0']";
    String CHECKBOX_BUILD_SOLAR_POWER = "//input[@name='realty[flat_building][build_solar_power_plant_flag]' and @value='0']";

    String SELECT_HOUSE_MAIN_BUILD_TYPE = "//select[@name='realty[house][main_rlt_build_subtp]']";
    String SELECT_HOUSE_RECONSTRUCTION = "//select[@name='realty[house][data][reconstruction]']";
    String SELECT_HOUSE_HEATING_SYSTEM = "//select[@name='realty[house][unit_heating_system_tp]']";
    String SELECT_HOUSE_HEATING_MEDIUM = "//select[@name='realty[house][unit_heating_medium_tp]']";
    String CHECKBOX_HOUSE_WATER_NETWORK = "//input[@name='realty[house][water_supply_network_public]' and @value='1']";
    String CHECKBOX_HOUSE_SEWERAGE_NETWORK = "//input[@name='realty[house][sewerage_supply_network_public]' and @value='1']";
    String CHECKBOX_HOUSE_SEWERAGE_NETWORK_OWN = "//input[@name='realty[house][sewerage_supply_network_own]' and @value='1']";
    String CHECKBOX_HOUSE_GAS_NETWORK = "//input[@name='realty[house][gas_supply_network_public]' and @value='1']";
    String CHECKBOX_HOUSE_SOLAR_POWER = "//input[@name='realty[house][build_solar_power_plant_flag]' and @value='0']";
    String CHECKBOX_HOUSE_AIRCONDITION = "//input[@name='realty[house][unit_airconditioning_system_flag]' and @value='0']";
    String CHECKBOX_HOUSE_FLOOR_DOWNSTAIR = "//input[@name='realty[house_building][build_floor_downstairs_flag]' and @value='0']";
    String CHECKBOX_HOUSE_FLOOR_UPSTAIR = "//input[@name='realty[house_building][build_floor_upstairs_cnt]' and @value='1']";
    String CHECKBOX_HOUSE_FLOOR_ATTIC = "//input[@name='realty[house_building][build_floor_tp_attic_flag]' and @value='1']";
    String INPUT_HOUSE_BUILT_UP_AREA = "//input[@name='realty[house_building][built_up_area]']";
    String INPUT_HOUSE_SURROUND_SPACE = "//input[@id='house-building-surround-space']";
    String INPUT_HOUSE_FLOOR_AREA = "//input[@id='house-building-residential-floor-area']";

    String TEXTAREA_FORWARDCOMMENT = "//textarea[@id='forward-comment']";
    String TEXTAREA_DELAYCOMMNET = "//textarea[@id='delay-comment']";
    String TEXTAREA_CANCELCOMMNET = "//textarea[@id='cancel-comment']";

    String BUTTON_COMPARATOR_ADD_REALTY = "//button[contains(text(),'Přidat nemovitost')]";
    String INPUT_COMPARATOR_REALTY_AREA = "(//input[@name='realty_area'])[last()]";
    String INPUT_COMPARATOR_LAND_AREA = "(//input[@name='land_area'])[last()]";
    String INPUT_COMPARATOR_PRICE = "(//input[@name='price'])[last()]";

    String BUTTON_SAVERISKS = "//form[@id='risk-form']//*[text()='Uložit sekci']";
    String BUTTON_SAVEALL = "//button[contains(text(),'Uložit vše')]";

    String DIV_LOADING = "//div[@class='loading']";

    @Wait(value = H3_VALUATIONCOMPLETED, waitSecondsForElement = 60)
    ValuationDetailPage waitForValuationCompleted();

    @TypeInto(value = INPUT_REPRODUCTIVE_PRICE, clear = true)
    ValuationDetailPage insertReproductivePrice(int price);

    @TypeInto(value = INPUT_CURRENT_PRICE, clear = true)
    ValuationDetailPage insertCurrentPrice(int price);

    @Click(A_PROCESSORDER)
    ValuationDetailPage clickProcess();

    @Click(H2_RISKS)
    ValuationDetailPage clickRisks();

    @Click(H2_FINAL)
    ValuationDetailPage clickFinalSection();

    @Click(H3_COMPARATIVE_METHOD)
    ValuationDetailPage clickComparativeMethod();

    @Wait(H2_REALTYDESCRIPTION)
    @Click(H2_REALTYDESCRIPTION)
    ValuationDetailPage clickRealtyDescription();

    @Click(value = BUTTON_SAVEALL, andWait = @Wait(value = BUTTON_SAVEALL, until = Until.CLICKABLE))
    ValuationDetailPage clickSaveAll();

    @Click(BUTTON_SAVERISKS)
    ValuationDetailPage clickSaveRisks();

    @Click(A_DEFER)
    ValuationDetailPage clickDeferOrder();

    @TypeInto(INPUT_DELAY_UNTIL)
    ValuationDetailPage insertDelayUntil(String delay);

    @TypeInto(TEXTAREA_DELAYCOMMNET)
    ValuationDetailPage insertDelayComment(String comment);

    @Click(INPUT_DEFER_ORDER)
    ValuationDetailPage clickDeferOrderInput();

    @AcceptAlert(waitSecondsForAlert = 10)
    ValuationDetailPage acceptAlert();

    @Click(A_CANCEL)
    ValuationDetailPage clickCancelOrder();

    @TypeInto(TEXTAREA_CANCELCOMMNET)
    ValuationDetailPage insertCancelComment(String comment);

    @Click(INPUT_CANCEL)
    ValuationDetailPage clickCancelOrderInput();

    @Click(A_GIVE)
    ValuationDetailPage clickGiveOrder();

    @TypeInto(TEXTAREA_FORWARDCOMMENT)
    ValuationDetailPage insertForwardComment(String comment);

    @Click(INPUT_GIVE_ORDER)
    ValuationDetailPage clickGiveOrderInput();

    @Click(A_TAKE)
    ValuationDetailPage clickTakeOrder();

    @CheckElementPresent(DIV_LOADING)
    ValuationDetailPage checkLoadingScreen();

    @Click(A_PROCESSORDER)
    ValuationDetailPage clickProcessOrder();

    @Click(CHECKBOX_FLAT_AIRCONDITION)
    ValuationDetailPage clickFlatAircondition();

    @Click(CHECKBOX_BUILD_GAS)
    ValuationDetailPage clickBuildGas();

    @Click(CHECKBOX_BUILD_SOLAR_POWER)
    ValuationDetailPage clickBuildSolarPower();

    @Select(SELECT_FLAT_HEATING)
    ValuationDetailPage selectFlatHeating(String heating);

    @Select(SELECT_FLAT_HEATING_MEDIUM)
    ValuationDetailPage selectFlatHeatingMedium(String medium);

    @TypeInto(INPUT_BUILD_APART_CNT)
    ValuationDetailPage insertBuildApart(String apart);

    @TypeInto(INPUT_COMPARATOR_REALTY_AREA)
    ValuationDetailPage insertComparatorRealtyArea(String area);

    @TypeInto(INPUT_COMPARATOR_LAND_AREA)
    ValuationDetailPage insertComparatorLandArea(String area);

    @TypeInto(INPUT_COMPARATOR_PRICE)
    ValuationDetailPage insertComparatorPrice(String price);

    @Click(BUTTON_COMPARATOR_ADD_REALTY)
    ValuationDetailPage clickComparatorAddRealty();

    @Select(SELECT_HOUSE_MAIN_BUILD_TYPE)
    ValuationDetailPage selectHouseMainBuildType(String buildType);

    @Select(SELECT_HOUSE_RECONSTRUCTION)
    ValuationDetailPage selectHouseReconstruction(String reconstruction);

    @Select(SELECT_HOUSE_HEATING_SYSTEM)
    ValuationDetailPage selectHouseHeatingSystem(String heatingSystem);

    @Select(SELECT_HOUSE_HEATING_MEDIUM)
    ValuationDetailPage selectHouseHeatingMedium(String medium);

    @Click(CHECKBOX_HOUSE_WATER_NETWORK)
    ValuationDetailPage clickHouseWaterNetwork();

    @Click(CHECKBOX_HOUSE_SEWERAGE_NETWORK)
    ValuationDetailPage clickHouseSewerageNetwork();

    @Click(CHECKBOX_HOUSE_SEWERAGE_NETWORK_OWN)
    ValuationDetailPage clickHouseSewerageNetworkOwn();

    @Click(CHECKBOX_HOUSE_GAS_NETWORK)
    ValuationDetailPage clickHouseGasNetwork();

    @Click(CHECKBOX_HOUSE_SOLAR_POWER)
    ValuationDetailPage clickHouseSolarPower();

    @Click(CHECKBOX_HOUSE_AIRCONDITION)
    ValuationDetailPage clickHouseAircondition();

    @Click(CHECKBOX_HOUSE_FLOOR_DOWNSTAIR)
    ValuationDetailPage clickHouseFloorDownstair();

    @Click(CHECKBOX_HOUSE_FLOOR_UPSTAIR)
    ValuationDetailPage clickHouseFloorUpstair();

    @Click(CHECKBOX_HOUSE_FLOOR_ATTIC)
    ValuationDetailPage clickHouseFloorAttic();

    @TypeInto(value = INPUT_HOUSE_BUILT_UP_AREA, clear = true)
    ValuationDetailPage insertBuiltUpArea(String area);

    @TypeInto(value = INPUT_HOUSE_SURROUND_SPACE, clear = true)
    ValuationDetailPage insertSurroundSpace(String area);

    @TypeInto(value = INPUT_HOUSE_FLOOR_AREA, clear = true)
    ValuationDetailPage insertFloorArea(String area);

    @TypeInto(INPUT_LOCAL_INVESTIGATION_DATE)
    ValuationDetailPage insertLocalInvestigationDate(String investigationDate);

    /**
     * Verify if last operation has correct comment in history of order.
     *
     * @return
     */
    @CustomAction
    default ValuationDetailPage verifyLastOperationComment() {
        HyposEndpoint endpoint = getEndpoint(HyposEndpoint.class);
        String lastOperationComment = endpoint.getText(TD_LASTOPERATION_COMMENT);
        String errorMessageComment = String.format("Order should have comment in last operation '%s', instead of this it has %s", autoComment, lastOperationComment);
        Assertions.assertEquals(lastOperationComment, autoComment, errorMessageComment);
        return null;
    }

    /**
     * Verifying if valuation has correct type according to predefined parameters.
     *
     * @param expectedType - String of expected valuation type.
     * @return
     */
    @CustomAction
    default ValuationDetailPage verifyValuationType(String expectedType) {
        HyposEndpoint endpoint = getEndpoint(HyposEndpoint.class);
        String valuationType = endpoint.getText(TD_VALUATIONTYPE);
        String errorMessage = String.format("Valuation has type %s, instead of expected type %s", valuationType, expectedType);
        Assertions.assertEquals(valuationType, expectedType, errorMessage);
        return null;
    }

    /**
     * Check shared elements in the header of valuation form.
     * Will be used for flats, houses and lands, because header is always same.
     * @return
     */
    @CustomAction
    default ValuationDetailPage checkSharedElements() {
        HyposEndpoint endpoint = getEndpoint(HyposEndpoint.class);

        String[] contractDetailElements = {"Číslo obchodu", "Způsob zpracování - výchozí", "Typ nemovitosti", "Účel ocenění", "Detail účelu ocenění",
                "Výše úvěru", "LTV z hypokalkulačky", "Broker", "Typ objednatele", "Klient", "Zpracovatel", "Kupní cena", "Dosud čerpáno", "Číslo objednávky ocenění",
                "Hypoteční bankéř", "Celek"};
        Arrays.stream(contractDetailElements).forEach(e -> endpoint.waitForElementsToLoad(5, String.format("//th[text() = '%s:']/following-sibling::td[1]", e)));

        String[] orderDetailElements = {"Kontaktní informace na osobu, která může zpřístupnit nemovitost", "Adresa nemovitosti", "Datum objednání",
                "Čas od objednání", "Odloženo do", "Požadovaný termín zhotovení"};

        Arrays.stream(orderDetailElements).forEach(e -> endpoint.waitForElementsToLoad(5, String.format("//td[text() = '%s:']/following-sibling::td", e)));

        return null;
    }

    /**
     * Check elements presence. Works only for elements with ID!
     * @param elements String array with same types of elements (selects, inputs etc...)
     * @param elementsType String element type to be checked.
     * @return
     */
    @CustomAction
    default ValuationDetailPage checkElements(String[] elements, String elementsType) {
        HyposEndpoint endpoint = getEndpoint(HyposEndpoint.class);
        Arrays.stream(elements).forEach(e -> endpoint.waitForElementsToLoad(5, String.format("//%s[@id = '%s']", elementsType, e)));
        return null;
    }

    /**
     * Get values used for reproductive price calculation and verify if value is correct.
     * @return
     */
    @CustomAction
    default ValuationDetailPage doCalculationAndVerify() {
        HyposEndpoint endpoint = getEndpoint(HyposEndpoint.class);

        double flatArea = Double.parseDouble(endpoint.getAttribute(INPUT_FLAT_AREA, "value").replace(",","."));
        double flatAreaOther = Double.parseDouble(endpoint.getAttribute(INPUT_FLAT_AREA_OTHER, "value").replace(",","."));
        double countedArea;

        if ((flatAreaOther / 2 )> 0.2 * flatArea){
            countedArea = flatArea + flatAreaOther * 0.2;
        } else {
            countedArea = flatArea + (flatAreaOther / 2);
        }

        double JKSOhodnota = Double.parseDouble(endpoint.getAttribute(INPUT_JKSO_PRICE,"value").replace(",","."));
        double expectedValue = Math.floor((countedArea * JKSOhodnota)/ 10000) * 10000;
        double reproductivePrice = Double.parseDouble(endpoint.getAttribute(INPUT_REPRODUCTIVE_PRICE, "value").replace(",","."));

        String message = String.format("Expected reporductive price value %s is not equal actual price %s.", expectedValue, reproductivePrice);
        Assertions.assertEquals(expectedValue, reproductivePrice, message);
        return null;
    }

    /**
     * Setting all risks to no, so valuation could be processed.
     *
     * @return
     */
    @CustomAction
    default ValuationDetailPage setAllRisksNo() {
        HyposEndpoint endpoint = getEndpoint(HyposEndpoint.class);
        String[] risks = {"redoc_registration", "pledge", "right_energy", "right_usage",
                "right_entry", "preemption", "other_restriction", "stopping", "real_usage", "unused",
                "under_construction", "other_risk", "engineering_networks", "foreign_land", "accessible",
                "lease_agreement", "flood_area"};

        Arrays.stream(risks).forEach(e -> endpoint.click(() -> String.format("//input[@name = 'risks[%s]' and @value = '0']", e)));

        return null;
    }

    /**
     * Verify if in history is correct last operation type.
     *
     * @param operationType String type of operation.
     * @return
     */
    @CustomAction
    default ValuationDetailPage verifyLastOperation(String operationType) {
        HyposEndpoint endpoint = getEndpoint(HyposEndpoint.class);
        endpoint.waitForElementsToLoad(10, Until.CLICKABLE, TD_LASTOPERATION);
        String lastOperation = endpoint.getText(TD_LASTOPERATION);
        String errorMessage = String.format("Order should have last operation '%s', instead of this it has %s", operationType, lastOperation);
        Assertions.assertTrue(lastOperation.contains(operationType), errorMessage);
        return null;
    }
}
