package ru.otus.mobile.screens;

import com.codeborne.selenide.ElementsCollection;
import com.codeborne.selenide.SelenideElement;
import io.appium.java_client.AppiumBy;
import ru.otus.mobile.config.AuthContext;
import ru.otus.mobile.config.MobileContext;
import ru.otus.mobile.ui.MobileUi;
import ru.otus.mobile.ui.UiWait;

import static com.codeborne.selenide.Selenide.$;

public class UsersScreen {

    public void open() {
        ensureLoggedIn();
        if (MobileUi.existsById("users_content")) {
            return;
        }
        dismissErrorDialogIfPresent();
        if (MobileUi.existsById("users_menu")) {
            MobileUi.byIdOrAccessibility("users_menu").click();
        } else if (MobileUi.existsById("go_to_users_tab")) {
            MobileUi.byIdOrAccessibility("go_to_users_tab").click();
        } else if (MobileUi.existsById("go_to_users")) {
            MobileUi.byIdOrAccessibility("go_to_users").click();
        }
        MobileUi.byIdOrAccessibility("users_content");
    }

    private void dismissErrorDialogIfPresent() {
        if (UiWait.exists(AppiumBy.id("android:id/alertTitle"))
                || UiWait.exists(AppiumBy.id("android:id/message"))) {
            com.codeborne.selenide.Selenide.$(AppiumBy.id("android:id/button1")).click();
        }
    }

    private void ensureLoggedIn() {
        LoginScreen loginScreen = new LoginScreen();
        if (!loginScreen.isVisible()) {
            return;
        }
        String username = AuthContext.username();
        String password = AuthContext.password();
        boolean allowRegister = AuthContext.allowRegister();
        if (password == null && username != null) {
            password = "Admin123";
        }
        if (username != null && password != null) {
            loginScreen.loginOrRegister(username, password, allowRegister);
        }
    }

    public void openFirstUser() {
        ElementsCollection users = MobileUi.allById("user_item");
        if (users.isEmpty()) {
            users = MobileUi.allById("list_item");
        }
        users.first().click();
    }

    public boolean openUserByName(String name) {
        String pkg = MobileContext.packageName();
        String safe = name.replace("\"", "\\\"");
        int maxSwipes = Integer.getInteger("users.search.swipes", 6);
        String selector = "new UiScrollable(new UiSelector().scrollable(true))"
                + ".setMaxSearchSwipes(" + maxSwipes + ")"
                + ".scrollIntoView(new UiSelector().textContains(\"" + safe + "\"))";
        try {
            $(AppiumBy.androidUIAutomator(selector));
            String xpath = "//android.view.ViewGroup[(@resource-id='" + pkg + ":id/user_item'"
                    + " or @resource-id='" + pkg + ":id/list_item') and .//*[contains(@text,\"" + safe + "\")]]";
            SelenideElement row = $(AppiumBy.xpath(xpath));
            if (row.exists()) {
                row.click();
                return true;
            }
            $(AppiumBy.androidUIAutomator(selector)).click();
            return true;
        } catch (Throwable ignored) {
            return false;
        }
    }

    public void openUserWithGift(String preferredName) {
        if (preferredName != null && !preferredName.isBlank() && Boolean.getBoolean("reservation.fast")) {
            if (openUserByName(preferredName) && openFirstWishlistWithGift()) {
                return;
            }
            throw new IllegalStateException("Preferred user not found or has no gifts to reserve.");
        }
        openFirstUserWithGift();
    }

    public void openFirstWishlist() {
        ElementsCollection wishlists = MobileUi.allById("wishlist_item");
        if (wishlists.isEmpty()) {
            wishlists = MobileUi.allById("list_item");
        }
        wishlists.first().click();
    }

    public void openFirstGift() {
        ElementsCollection gifts = MobileUi.allById("gift_item");
        if (gifts.isEmpty()) {
            gifts = MobileUi.allById("list_item");
        }
        gifts.first().click();
    }

    public boolean toggleReservation() {
        SelenideElement reserved = MobileUi.byIdOrAccessibility("reserved");
        boolean before = isChecked(reserved);
        reserved.click();
        return isChecked(reserved) != before;
    }

    private boolean isChecked(SelenideElement element) {
        String checked = element.getAttribute("checked");
        if (checked != null) {
            return Boolean.parseBoolean(checked);
        }
        String selected = element.getAttribute("selected");
        return Boolean.parseBoolean(selected);
    }

    private void openFirstUserWithGift() {
        int maxPages = Integer.getInteger("users.scan.pages", 1);
        for (int page = 0; page < maxPages; page++) {
            ElementsCollection users = MobileUi.allById("user_item");
            if (users.isEmpty()) {
                users = MobileUi.allById("list_item");
            }
            for (int i = 0; i < users.size(); i++) {
                users.get(i).click();
                if (openFirstWishlistWithGift()) {
                    return;
                }
                returnToUsersList();
            }
            String scrollForward = "new UiScrollable(new UiSelector().scrollable(true)).scrollForward()";
            $(AppiumBy.androidUIAutomator(scrollForward));
        }
        openFirstUser();
    }

    private boolean hasWishlists() {
        return MobileUi.existsById("wishlist_item")
                || MobileUi.existsById("list_item");
    }

    private boolean openFirstWishlistWithGift() {
        if (!hasWishlists()) {
            return false;
        }
        openFirstWishlist();
        if (hasGifts()) {
            return true;
        }
        MobileUi.back();
        return false;
    }

    private boolean hasGifts() {
        if (MobileUi.existsById("gift_item")) {
            return true;
        }
        return MobileUi.existsById("list_item");
    }

    private void returnToUsersList() {
        for (int i = 0; i < 2; i++) {
            if (MobileUi.existsById("users_content")
                    || MobileUi.existsById("user_item")) {
                return;
            }
            MobileUi.back();
        }
    }
}
