import asyncio
from link_agregator.utils.logger import logger
import random

async def smooth_scroll_to(page, selector):
    """
    Wykonuje smooth scroll do elementu po selektorze. Zwraca True jeśli się udało.
    """
    try:
        scroll_js = """
        async (selector) => {
            const el = document.querySelector(selector);
            if (!el) return false;
            let lastY = window.scrollY;
            let targetY = el.getBoundingClientRect().top + window.scrollY - window.innerHeight / 2;
            let step = (targetY - window.scrollY) > 0 ? 30 : -30;
            while (Math.abs(window.scrollY - targetY) > 20) {
                window.scrollBy(0, step);
                await new Promise(r => setTimeout(r, 16));
                if (Math.abs(window.scrollY - lastY) < 2) break;
                lastY = window.scrollY;
            }
            el.scrollIntoView({behavior: "smooth", block: "center"});
            return true;
        }
        """
        res = await page.evaluate(scroll_js, selector)
        await asyncio.sleep(0.7)
        logger.info(f"[ACTION] Manualnie smooth scrolled to: {selector} (result: {res})")
        return res
    except Exception as exc:
        logger.warning(f"[ACTION] Manual smooth scroll failed: {selector}: {exc}")
        return False

async def click_action(page, selector, **kwargs):
    """
    Smooth scroll do elementu i kliknij po selektorze.
    """
    locator = page.locator(selector)
    try:
        if await locator.count() > 0:
            await smooth_scroll_to(page, selector)
            await locator.first.click(timeout=kwargs.get('timeout', 20000))
            logger.info(f"[ACTION] Clicked: {selector}")
        else:
            logger.warning(f"[ACTION] Selector not found for click: {selector}")
    except Exception as exc:
        logger.warning(f"[ACTION] Click failed: {selector}: {exc}")

async def click_text_action(page, selector=None, **kwargs):
    """
    Smooth scroll do elementu z tekstem (case-insensitive), potem kliknij.
    Użyj parametru 'text'.
    """
    text = kwargs.get('text')
    if not text:
        logger.warning("[ACTION] click_text_action bez 'text' w parametrach!")
        return
    xpath = f"//*[contains(translate(normalize-space(text()), '{text.upper()}', '{text.lower()}'), '{text.lower()}')]"
    locator = page.locator(f"xpath={xpath}")
    try:
        count = await locator.count()
        for i in range(count):
            el = locator.nth(i)
            visible = await el.is_visible()
            if visible:
                # Najpierw smooth scroll do tego elementu
                element_handle = await el.element_handle()
                if element_handle:
                    selector_str = await element_handle.evaluate("el => el.tagName.toLowerCase() + (el.id ? '#' + el.id : '')")
                else:
                    selector_str = None
                if selector_str:
                    await smooth_scroll_to(page, selector_str)
                else:
                    await el.scroll_into_view_if_needed(timeout=kwargs.get('timeout', 2000))
                await el.click(timeout=kwargs.get('timeout', 2000))
                logger.info(f"[ACTION] Clicked element with text: '{text}'")
                return
        logger.warning(f"[ACTION] Nie znaleziono widocznego elementu z tekstem: '{text}'")
    except Exception as exc:
        logger.warning(f"[ACTION] Click by text failed: '{text}': {exc}")

async def scroll_action(page, selector, **kwargs):
    await smooth_scroll_to(page, selector)

async def wait_action(page, selector, **kwargs):
    try:
        await page.wait_for_selector(selector, timeout=kwargs.get('timeout', 4000))
        logger.info(f"[ACTION] Waited for: {selector}")
    except Exception as exc:
        logger.warning(f"[ACTION] Wait for failed: {selector}: {exc}")

async def delay_action(page, selector=None, **kwargs):
    ms = kwargs.get("delay", 500)
    await asyncio.sleep(ms/1000)
    logger.info(f"[ACTION] Delay {ms}ms")

async def scroll_to_bottom_action(page, selector=None, **kwargs):
    await page.evaluate("window.scrollTo(0, document.body.scrollHeight);")
    logger.info(f"[ACTION] Scrolled to bottom of page")

# --- Rejestr ---
ACTION_HANDLERS = {
    "click": click_action,
    "click_text": click_text_action,
    "scroll": scroll_action,
    "scroll_to_bottom": scroll_to_bottom_action,
    "wait_for": wait_action,
    "delay": delay_action,
}

def allowed_action_types():
    return list(ACTION_HANDLERS.keys())

async def run_actions_on_page(page, actions: list):
    actions = sorted(actions, key=lambda x: x.get("index", 0))
    for action in actions:
        action_type = action.get("action_type")
        selector = action.get("selector", None)
        handler = ACTION_HANDLERS.get(action_type)
        if not handler:
            logger.warning(f"[ACTION] Nieznany typ akcji: {action_type}")
            continue
        kwargs = {k: v for k, v in action.items() if k not in ("action_type", "selector", "index")}
        await handler(page, selector, **kwargs)
        delay = random.uniform(0.1, 1.4)
        logger.info(f"[ACTION] Random delay after action: {delay:.2f}s")
        await asyncio.sleep(delay)
