from playwright.async_api import Page

from app.automation.helpers import human_delay, safe_click
from app.automation.selectors import (
    CONFIRM_EXCHANGE_TYPE,
    CONFIRM_TEAM_BLOCK,
    CONFIRM_PLAYLISTS,
    CONFIRM_STATS,
    CONFIRM_MESSAGE,
    CONFIRM_SEND_BUTTON,
)
from app.automation.tasks.popup import _dismiss_activation_guide

# Request Video + Two-way/One-way all land on Confirm; Send button id can vary.
_SEND_BUTTON_SELECTORS = (
    CONFIRM_SEND_BUTTON,
    "#sendExchange",
    "button#sendExchange",
    "button[id*='send' i]",
    "button[id*='Send' i]",
    "footer button:has-text('Send')",
    "button:has-text('Send your video')",
    "button:has-text('Send')",
    ".uni-btn--primary:has-text('Send')",
    "xpath=//button[contains(translate(., 'SEND', 'send'), 'send')]",
)


async def get_confirm_details(page: Page) -> dict:
    """
    GET /exchange/confirm
    Reads the final confirmation screen details before submitting.

    Do NOT call close_hudl_popups() — Confirm Your Exchange is a Hudl Modal;
    closing it removes #sendExchange and breaks Request Video Send.
    """
    await _dismiss_activation_guide(page)
    await human_delay(0.8, 1.4)

    # Wait briefly for confirm UI (classic footer or modal).
    try:
        await page.wait_for_function(
            """() => {
              const t = document.body?.innerText || '';
              if (/confirm your exchange/i.test(t)) return true;
              if (document.querySelector('#sendExchange')) return true;
              if (/request exchange with|exchange with/i.test(t) && /message/i.test(t)) return true;
              return false;
            }""",
            timeout=12000,
        )
    except Exception:
        pass

    exchange_name = ""
    exchange_type_locator = page.locator(CONFIRM_EXCHANGE_TYPE).first
    if await exchange_type_locator.count() > 0:
        text = await exchange_type_locator.inner_text()
        exchange_name = " ".join([t.strip() for t in text.split("\n") if t.strip()])
    if not exchange_name:
        # Request Video modal often uses a heading instead of .ex-exchange-type
        try:
            heading = await page.evaluate(
                """() => {
                  const t = document.body?.innerText || '';
                  const m = t.match(/((?:Request |Two-way |One-way )?Exchange with[^\n]*)/i);
                  return m ? m[1].trim() : '';
                }"""
            )
            exchange_name = heading or ""
        except Exception:
            pass

    school_name = ""
    school_image = None
    team_block = page.locator(CONFIRM_TEAM_BLOCK).first
    if await team_block.count() > 0:
        h5_locator = team_block.locator("h5").first
        if await h5_locator.count() > 0:
            school_name = (await h5_locator.inner_text()).strip()

        photo_locator = team_block.locator(".ex-team-photo").first
        if await photo_locator.count() > 0:
            style = await photo_locator.get_attribute("style") or ""
            if "url(" in style:
                school_image = style.split("url(")[1].split(")")[0].strip("'\"")

    if not school_name:
        try:
            school_name = await page.evaluate(
                """() => {
                  const h = document.querySelector(
                    '.ex-team-block h5, [class*="confirm"] h5, .smooth-modal h5, h5'
                  );
                  return (h?.innerText || '').trim();
                }"""
            )
        except Exception:
            school_name = ""

    video_names = []
    playlists_locator = page.locator(CONFIRM_PLAYLISTS)
    for i in range(await playlists_locator.count()):
        text = (await playlists_locator.nth(i).inner_text()).strip()
        if text:
            video_names.append(text)

    stats = []
    stats_locator = page.locator(CONFIRM_STATS).first
    if await stats_locator.count() > 0:
        li_locator = stats_locator.locator("li")
        count = await li_locator.count()
        if count > 0:
            for i in range(count):
                text = (await li_locator.nth(i).inner_text()).strip()
                if text:
                    stats.append(text)
        else:
            text = await stats_locator.inner_text()
            cleaned = " ".join([t.strip() for t in text.split("\n") if t.strip()])
            if cleaned:
                stats.append(cleaned)

    message = ""
    msg_locator = page.locator(CONFIRM_MESSAGE).first
    if await msg_locator.count() > 0:
        message = (await msg_locator.inner_text()).strip()
    if not message:
        try:
            message = await page.evaluate(
                """() => {
                  const label = [...document.querySelectorAll('h3,h4,p,span,div')]
                    .find(el => /^(message)$/i.test((el.innerText || '').trim()));
                  if (!label) return '';
                  let n = label.nextElementSibling;
                  while (n && !(n.innerText || '').trim()) n = n.nextElementSibling;
                  return (n?.innerText || '').trim().slice(0, 500);
                }"""
            )
        except Exception:
            message = ""

    return {
        "status": "ok",
        "action": "confirm_details",
        "url": page.url,
        "exchange_name": exchange_name,
        "school_name": school_name,
        "school_image": school_image,
        "video_names": video_names,
        "stats": stats,
        "message": message,
    }


async def _find_send_button(page: Page):
    for sel in _SEND_BUTTON_SELECTORS:
        loc = page.locator(sel).first
        try:
            if await loc.count() == 0:
                continue
            if await loc.is_visible():
                return loc, sel
        except Exception:
            continue
    return None, None


async def submit_exchange(page: Page) -> dict:
    """
    POST /exchange/confirm
    Clicks Send on Confirm Your Exchange (Two-way / One-way / Request Video).

    Never call close_hudl_popups() — that dismisses the confirm Hudl Modal.
    """
    await _dismiss_activation_guide(page)
    await human_delay(0.6, 1.0)

    submit_btn = None
    used = None
    # Wait up to ~15s for Send to appear (modal paint after notes Next).
    for _ in range(20):
        submit_btn, used = await _find_send_button(page)
        if submit_btn is not None:
            break
        await human_delay(0.4, 0.6)
        await _dismiss_activation_guide(page)

    if submit_btn is None:
        # Dump a short hint for logs
        try:
            hint = await page.evaluate(
                """() => ({
                  url: location.href,
                  hasConfirm: /confirm your exchange/i.test(document.body?.innerText || ''),
                  buttons: [...document.querySelectorAll('button')]
                    .slice(0, 20)
                    .map(b => ({ id: b.id, text: (b.innerText || '').trim().slice(0, 40) })),
                })"""
            )
            print(f"submit_exchange: Send button not found — {hint}")
        except Exception:
            pass
        raise RuntimeError(
            "Could not find Hudl Send button on Confirm Your Exchange. "
            "Make sure the message step completed and the confirm modal is open."
        )

    print(f"submit_exchange: clicking Send via {used}")
    try:
        await safe_click(submit_btn, timeout_ms=8000, force_after_ms=2500)
    except Exception:
        # Last resort DOM click
        handle = await submit_btn.element_handle()
        if handle is None:
            raise RuntimeError("Hudl Send button handle missing")
        await page.evaluate(
            "(el) => { el.scrollIntoView({ block: 'center' }); el.click(); }",
            handle,
        )

    await human_delay(2.0, 3.5)
    await _dismiss_activation_guide(page)

    return {
        "status": "ok",
        "action": "exchange_submitted",
        "url": page.url,
        "send_button": used,
        "message": "Exchange has been successfully submitted.",
    }
