# /apps/aroflo_connector_app/ui_automation/flows/users_select_user.py
from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from playwright.sync_api import Page

from ..core.artifacts import shot
from ..core.log import log_step

@dataclass
class UserSelectResult:
    found: bool
    page_index: int = 0
    matched_email: str | None = None


def _normalize(s: str) -> str:
    return (s or "").strip().lower()


def _wait_table_ready(page):
    # 1) Asegura que la tabla correcta exista
    page.wait_for_selector("table#tblUsers", timeout=30_000)

    # 2) Espera a que haya filas (aunque estén ocultas) en la tabla correcta
    page.wait_for_selector("table#tblUsers tbody tr", state="attached", timeout=30_000)

    # 3) Espera a que al menos una fila sea realmente visible (no display:none / height:0 / etc.)
    page.wait_for_function(
        """() => {
            const tbl = document.querySelector('table#tblUsers');
            if (!tbl) return false;
            const rows = Array.from(tbl.querySelectorAll('tbody tr'));
            if (rows.length === 0) return false;
            return rows.some(r => {
                const rect = r.getBoundingClientRect();
                const visible = !!(r.offsetParent) && rect.height > 0 && rect.width > 0;
                return visible;
            });
        }""",
        timeout=30_000
    )



def _find_row_by_email(page: Page, email: str):
    target = email.strip().lower()
    rows = page.locator("table#tblUsers tbody tr")

    # Filtra por texto contenido en la fila completa
    # (Playwright soporta has_text en locator)
    return rows.filter(has_text=target)


def _try_use_search_box(page: Page, email: str) -> bool:
    """
    Si la tabla tiene un input de búsqueda, úsalo.
    Esto reduce drásticamente paginación y hace la UI automation más rápida.
    """
    email = email.strip()

    candidates = [
        page.locator("input[type='search']").first,
        page.locator("input[placeholder*='Search']").first,
        page.locator("input[aria-label*='Search']").first,
        page.locator("input[name*='search']").first,
    ]

    for inp in candidates:
        try:
            if inp.count() == 0:
                continue
            inp.click(timeout=1500)
            inp.fill("")
            inp.type(email, delay=30)
            page.wait_for_timeout(800)  # deja que filtre
            return True
        except Exception:
            continue

    return False


def _click_next(page: Page) -> bool:
    """
    Intenta paginar. Ajusta los selectores cuando veas el DOM real del paginador.
    """
    candidates = [
        page.get_by_role("link", name="Next"),
        page.get_by_role("button", name="Next"),
        page.locator("a:has-text('Next')").first,
        page.locator("button:has-text('Next')").first,
        page.locator("[aria-label='Next']").first,
        page.locator(".afDataTable__paginate a:has-text('Next')").first,
    ]
    for c in candidates:
        try:
            if c.count() == 0:
                continue
            c.click(timeout=3000)
            page.wait_for_timeout(800)
            return True
        except Exception:
            continue
    return False


def users_select_user_by_email(
    page: Page,
    email: str,
    run_dir: Path | None = None,
    max_pages: int = 30,
    click_profile: bool = True,
    timeout_ms: int = 8_000,
    screenshot_on_fail: bool = False,
) -> UserSelectResult:

    email = email.strip()
    _wait_table_ready(page)

    # Optimización: si hay search box, úsalo
    _try_use_search_box(page, email)
    page.wait_for_timeout(500)

    for i in range(max_pages):
        _wait_table_ready(page)
        emails = page.locator("tbody tr td").all_inner_texts()
        # O más específico si puedes: td que parece ser email:
        # emails = page.locator("tbody tr td.afDataTable__cell--non-numeric").all_inner_texts()

        # imprime algunos para validar
        print("DEBUG TD texts sample:", [t.strip() for t in emails[:80]])


        row = _find_row_by_email(page, email)

        if run_dir:
            shot(page, run_dir, f"users-find-email-page-{i+1}")
            log_step(f"users-find-email-page-{i+1}", page)

        if row.count() == 1:
            if click_profile:
                # Click a cualquier link del row (nombre o apellido)
                row.first.locator('a[href*="thisUser=1"]').first.click(timeout=timeout_ms)
                page.wait_for_load_state("networkidle", timeout=timeout_ms)

            return UserSelectResult(found=True, page_index=i + 1, matched_email=email)

        if row.count() > 1:
            # Esto sería raro, pero mejor fallar explícito
            raise RuntimeError(f"Multiple rows matched email: {email}")

        # No encontrado: intenta paginar
        if not _click_next(page):
            break

        if screenshot_on_fail and run_dir:
            shot(page, run_dir, "users-find-email-not-found")
            log_step("users-find-email-not-found", page)


    return UserSelectResult(found=False)
