package ru.kovbasa.pages;

import com.microsoft.playwright.ElementHandle;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Mouse;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.options.AriaRole;
import java.util.Optional;
import ru.kovbasa.playwright.TestConfig;
import ru.kovbasa.utils.UiActions;

public class ClickhousePage extends BasePage {

    public ClickhousePage(Page page, TestConfig config) {
        super(page, config);
    }

    public void open() {
        openPath("/lessons/clickhouse/");
    }

    public Locator getTeacherCards() {
        Locator section = getTeachersSection();
        if (section.count() == 0) {
            return page.locator("[data-qa*='teacher'], [class*='teacher'],"
                    + " [class*='Teacher'], [class*='trainer'], [class*='Tutor'],"
                    + " [class*='swiper-slide'], [class*='carousel']");
        }
        Locator cards = section.locator("[data-qa*='teacher-card'],"
                + " [class*='teacher-card'], [class*='teacher__card'],"
                + " [data-qa*='teacher'], [class*='teacher'], [class*='Teacher'],"
                + " [class*='trainer'], [class*='Tutor'],"
                + " [class*='swiper-slide'], [class*='carousel']");

        if (cards.count() == 0) {
            cards = section.locator("a:has(h3), a:has(h4), li, article");
        }
        if (cards.count() == 0) {
            cards = section.locator("div");
        }
        return cards;
    }

    public void dragTeachersCarousel() {
        Locator section = getTeachersSection();
        ElementHandle scrollContainer = findScrollableContainer(section);
        if (scrollContainer == null) {
            return;
        }

        Optional<Double> before = getScrollLeft(scrollContainer);
        String activeBefore = getCardName(getActiveTeacherCard());
        scrollContainer.scrollIntoViewIfNeeded();

        var box = scrollContainer.boundingBox();
        if (box == null) {
            return;
        }

        double startX = box.x + box.width * 0.8;
        double endX = box.x + box.width * 0.2;
        double y = box.y + box.height * 0.5;

        page.mouse().move(startX, y);
        page.mouse().down();
        page.mouse().move(endX, y, new Mouse.MoveOptions().setSteps(12));
        page.mouse().up();

        if (before.isPresent()) {
            page.waitForTimeout(500);
            Optional<Double> after = getScrollLeft(scrollContainer);
            if (after.isPresent() && before.get().equals(after.get())) {
                scrollContainer.evaluate("el => el.scrollLeft += el.clientWidth");
            }
        } else {
            page.evaluate("() => {\n"
                    + "  const swiperEl = document.querySelector('.swiper');\n"
                    + "  if (swiperEl && swiperEl.swiper) { swiperEl.swiper.slideNext(); }\n"
                    + "}");
        }
        String activeAfter = getCardName(getActiveTeacherCard());
        if (activeAfter.equals(activeBefore)) {
            page.evaluate("() => {\n"
                    + "  const swiperEl = document.querySelector('.swiper');\n"
                    + "  if (swiperEl && swiperEl.swiper) { swiperEl.swiper.slideNext(); }\n"
                    + "}");
            page.waitForTimeout(300);
        }
    }

    public Optional<Double> getTeachersScrollLeft() {
        Locator section = getTeachersSection();
        ElementHandle scrollContainer = findScrollableContainer(section);
        return getScrollLeft(scrollContainer);
    }

    public String getPopupTeacherName() {
        return getCardName(getActiveTeacherCard());
    }

    public void openTeacherPopup(Locator card) {
        UiActions.closeCommonPopups(page);
        card.scrollIntoViewIfNeeded();
        Locator clickable = card.locator("a, button, [role='button']").first();
        if (clickable.count() > 0) {
            clickable.click(new Locator.ClickOptions().setForce(true));
        } else {
            card.click(new Locator.ClickOptions().setForce(true));
        }
        getActiveTeacherCard().waitFor(new Locator.WaitForOptions().setTimeout(10000));
    }

    public void clickPopupNext() {
        Locator nextButton = page.locator(
                ".swiper-button-next, button[aria-label*='След'], button[aria-label*='Next'],"
                        + " button:has-text('>')").first();
        if (nextButton.count() > 0) {
            nextButton.click(new Locator.ClickOptions().setForce(true));
            return;
        }
        Boolean moved = (Boolean) page.evaluate("() => {\n"
                + "  const swiperEl = document.querySelector('.swiper');\n"
                + "  if (swiperEl && swiperEl.swiper) { swiperEl.swiper.slideNext(); return true; }\n"
                + "  return false;\n"
                + "}");
        if (!Boolean.TRUE.equals(moved)) {
            page.keyboard().press("ArrowRight");
        }
    }

    public void clickPopupPrev() {
        String before = getPopupTeacherName();
        Locator prevButton = page.locator(
                ".swiper-button-prev, button[aria-label*='Пред'], button[aria-label*='Prev'],"
                        + " button:has-text('<')").first();
        if (prevButton.count() > 0) {
            prevButton.click(new Locator.ClickOptions().setForce(true));
        } else {
            Boolean moved = (Boolean) page.evaluate("() => {\n"
                    + "  const swiperEl = document.querySelector('.swiper');\n"
                    + "  if (swiperEl && swiperEl.swiper) { swiperEl.swiper.slidePrev(); return true; }\n"
                    + "  return false;\n"
                    + "}");
            if (!Boolean.TRUE.equals(moved)) {
                page.keyboard().press("ArrowLeft");
            }
        }
        page.waitForTimeout(300);
        String after = getPopupTeacherName();
        if (after.equals(before)) {
            page.evaluate("() => {\n"
                    + "  const swiperEl = document.querySelector('.swiper');\n"
                    + "  if (swiperEl && swiperEl.swiper) { swiperEl.swiper.slidePrev(); }\n"
                    + "}");
            page.waitForTimeout(300);
        }
    }

    public Locator getTeacherDialog() {
        Locator active = getActiveTeacherCard();
        if (active.count() > 0) {
            return active;
        }
        return page.locator("[role='dialog'], [class*='modal'], [class*='popup']").first();
    }

    public Locator getActiveTeacherCard() {
        Locator active = page.locator(".swiper-slide-active");
        if (active.count() > 0) {
            return active.first();
        }
        return getTeacherCards().first();
    }

    private String getCardName(Locator card) {
        Locator name = card.locator("h3, h4, [class*='name'], p").first();
        if (name.count() > 0) {
            String text = name.textContent();
            return text == null ? "" : text.trim();
        }
        String text = card.textContent();
        return text == null ? "" : text.trim();
    }

    private Locator getTeachersSection() {
        Locator byHeading = page.getByRole(AriaRole.HEADING,
                new Page.GetByRoleOptions().setName("Преподаватели"));
        Locator section = byHeading.locator("xpath=ancestor::section");
        if (section.count() == 0) {
            section = page.locator("section").filter(
                    new Locator.FilterOptions().setHasText("Преподаватели")
            ).first();
        }
        if (section.count() == 0) {
            Locator heading = page.locator("text=/Преподаватели|Teachers/").first();
            section = heading.locator("xpath=ancestor::section|ancestor::div").first();
        }
        return section;
    }

    private ElementHandle findScrollableContainer(Locator section) {
        String script = """
                section => {
                  const byClass = section.querySelector(
                    '[class*="swiper"], [class*="carousel"], [class*="slider"],'
                    + ' [class*="scroll"], [class*="teachers"]'
                  );
                  if (byClass) {
                    return byClass;
                  }
                  return Array.from(section.querySelectorAll('*'))
                    .find(el => el.scrollWidth > el.clientWidth);
                }
                """;
        return section.evaluateHandle(script).asElement();
    }

    private Optional<Double> getScrollLeft(ElementHandle handle) {
        if (handle == null) {
            return Optional.empty();
        }
        Number value = (Number) handle.evaluate("el => el.scrollLeft");
        return value == null ? Optional.empty() : Optional.of(value.doubleValue());
    }
}
