"""App 端公共模块 — driver 创建 + ensure_logged_in 工厂。

所有 App 端 conftest 调用 share_* 函数即可，避免重复代码。
"""

from datetime import datetime
from pathlib import Path

import pytest

SCREENSHOTS_DIR = Path("output/screenshots")


def create_driver(section_config: dict, platform: str):
    """创建 Appium driver。

    Args:
        section_config: 配置中对应端的 section（如 config["driver_android"]）
        platform: "android" | "ios"
    """
    try:
        from appium import webdriver
        from appium.options.android import UiAutomator2Options
        from appium.options.ios import XCUITestOptions
    except ImportError:
        pytest.skip("Appium-Python-Client 未安装，跳过 App 测试。")

    appium_host = section_config.get("appium_host", "http://localhost:4723")

    if platform == "android":
        options = UiAutomator2Options()
        options.device_name = section_config["device_name"]
        options.app_package = section_config["app_package"]
        options.app_activity = section_config["app_activity"]
        options.no_reset = section_config.get("no_reset", True)
        options.new_command_timeout = section_config.get("new_command_timeout", 120)
        options.automation_name = "UiAutomator2"
    else:
        options = XCUITestOptions()
        options.device_name = section_config["device_name"]
        options.bundle_id = section_config["bundle_id"]
        options.no_reset = section_config.get("no_reset", True)
        options.new_command_timeout = section_config.get("new_command_timeout", 120)
        options.automation_name = "XCUITest"

    return webdriver.Remote(appium_host, options=options)


def make_ensure_logged_in(
    section_config: dict,
    config: dict,
    account_role: str,
    home_indicator: str = "tab_home",
):
    """创建一个 ensure_logged_in 闭包。

    策略：
        1. 反复点击返回键，直到底部导航栏（首页/货源/我的）全部可见
        2. 点击"我的"tab，检查"登录/注册"文本是否存在
        3. 不存在 → 已登录；存在 → 未登录

    Args:
        section_config: App 端配置
        config: 全局配置
        account_role: 默认账号角色名（如 "driver"、"shipper"）
        home_indicator: 未使用，保留兼容
    """
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from appium.webdriver.common.appiumby import AppiumBy

    def _ensure_logged_in(driver, timeout_s: float = 10.0) -> None:
        skip_login = section_config.get("skip_login", True)
        wait = WebDriverWait(driver, timeout=timeout_s)

        # ── 底部导航栏三个 tab 定位（使用 text 定位，更可靠）──
        home_tab = (AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("首页")')
        freight_tab = (AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("货源")')
        mine_tab = (AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("我的")')

        # ── 步骤1: 返回到一级页面 ──
        # 不断点返回键，直到三个底部导航 tab 都可见
        max_back_presses = 20
        for _ in range(max_back_presses):
            home_visible = _is_displayed(driver, home_tab)
            freight_visible = _is_displayed(driver, freight_tab)
            mine_visible = _is_displayed(driver, mine_tab)

            if home_visible and freight_visible and mine_visible:
                break

            # 不在一级页面 → 点击返回
            try:
                driver.back()
                driver.implicitly_wait(1)
            except Exception:
                break

        # ── 步骤2: 点击"我的"tab ──
        wait.until(EC.visibility_of_element_located(mine_tab))
        driver.find_element(*mine_tab).click()
        driver.implicitly_wait(1)

        # ── 步骤3: 判断登录态 ──
        login_check = (AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("登录/注册")')
        try:
            el = driver.find_element(*login_check)
            if el.is_displayed():
                if skip_login:
                    raise RuntimeError(
                        "APP 未登录！请在设备上手动完成一次登录（含验证码），"
                        "之后重新运行用例即可。\n如需自动化登录，请设置 skip_login: false。"
                    )
                _perform_ui_login(driver, config["accounts"].get(account_role, {}), wait)
                return
        except RuntimeError:
            raise
        except Exception:
            pass  # 没找到"登录/注册" → 已登录

        # ── 步骤4: 回到首页 ──
        try:
            wait.until(EC.visibility_of_element_located(home_tab))
            driver.find_element(*home_tab).click()
        except Exception:
            pass

    return _ensure_logged_in


def _is_displayed(driver, locator) -> bool:
    """检查元素是否可见（不抛异常）。"""
    try:
        el = driver.find_element(*locator)
        return el.is_displayed()
    except Exception:
        return False


def _perform_ui_login(driver, account: dict, wait) -> None:
    """执行 UI 自动登录（skip_login: false 时使用）。"""
    from appium.webdriver.common.appiumby import AppiumBy

    phone = account.get("phone", "")
    password = account.get("password", "")

    # 点击登录入口
    login_entry = (AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("登录/注册")')
    wait.until(lambda d: d.find_element(*login_entry))
    driver.find_element(*login_entry).click()
    driver.implicitly_wait(1)

    # 填写手机号
    phone_input = (AppiumBy.ID, "com.arpa.ynchenggangdriver:id/ed_phone")
    wait.until(lambda d: d.find_element(*phone_input))
    driver.find_element(*phone_input).send_keys(phone)

    # 填写密码
    password_input = (AppiumBy.ID, "com.arpa.ynchenggangdriver:id/ed_pwd")
    driver.find_element(*password_input).send_keys(password)

    # 点击登录
    login_btn = (AppiumBy.ID, "com.arpa.ynchenggangdriver:id/tv_login")
    driver.find_element(*login_btn).click()
    driver.implicitly_wait(2)

    # 回到首页
    home_tab = (
        AppiumBy.ANDROID_UIAUTOMATOR,
        'new UiSelector().resourceId("com.arpa.ynchenggangdriver:id/fixed_bottom_navigation_icon").instance(0)',
    )
    try:
        wait.until(lambda d: d.find_element(*home_tab))
        driver.find_element(*home_tab).click()
    except Exception:
        pass


def save_failure_screenshot(driver, section_config, platform, request):
    """失败自动截图（各端 conftest teardown 中调用）。"""
    if (
        section_config.get("screenshot_on_failure", True)
        and hasattr(request.node, "rep_call")
        and request.node.rep_call.failed
    ):
        scenario_dir = SCREENSHOTS_DIR / request.node.name
        scenario_dir.mkdir(parents=True, exist_ok=True)
        ts = datetime.now().strftime("%Y%m%d_%H%M%S")
        path = str(scenario_dir / f"FAIL_{platform}_{ts}.png")
        driver.save_screenshot(path)


@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    outcome = yield
    rep = outcome.get_result()
    setattr(item, f"rep_{rep.when}", rep)
