"""App Page Object 基类 — 封装移动端页面共享的通用操作。

每个 App 页面应继承 AppBasePage，在 __init__ 中声明所有定位器。

Usage:
    class DriverHomePage(AppBasePage):
        def __init__(self, driver, platform):
            super().__init__(driver, platform)
            self.order_tab = driver.find_element(AppiumBy.ACCESSIBILITY_ID, "tab_orders")
"""

from datetime import datetime
from pathlib import Path

from appium.webdriver.common.appiumby import AppiumBy
from appium.webdriver.webdriver import WebDriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

SCREENSHOTS_DIR = Path("output/screenshots")


class AppBasePage:
    """App Page Object 基类。"""

    def __init__(self, driver: WebDriver, platform: str, timeout_ms: int = 30_000):
        self.driver = driver
        self.platform = platform          # "android" | "ios"
        self.timeout = timeout_ms / 1000  # WebDriverWait 使用秒

    # ── 通用等待 ──

    def wait_visible_by_id(self, accessibility_id: str, timeout_s: float | None = None) -> None:
        """等待 accessibility_id 对应的元素可见。"""
        wait = WebDriverWait(self.driver, timeout=timeout_s or self.timeout)
        wait.until(
            EC.visibility_of_element_located((AppiumBy.ACCESSIBILITY_ID, accessibility_id))
        )

    def wait_visible_by_text(self, text: str, timeout_s: float | None = None) -> None:
        """等待页面上出现指定文本。"""
        wait = WebDriverWait(self.driver, timeout=timeout_s or self.timeout)

        locator = (
            AppiumBy.XPATH, f"//*[@text='{text}']"
            if self.platform == "android"
            else (AppiumBy.XPATH, f"//*[@label='{text}']")
        )
        wait.until(EC.visibility_of_element_located(locator))

    # ── 通用操作 ──

    def tap_by_id(self, accessibility_id: str) -> None:
        """按 accessibility_id 点击元素（推荐优先使用）。"""
        self.wait_visible_by_id(accessibility_id)
        self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, accessibility_id).click()

    def tap_by_text(self, text: str) -> None:
        """按文本点击元素。"""
        strategy = AppiumBy.XPATH
        locator = (
            f"//*[@text='{text}']"
            if self.platform == "android"
            else f"//*[@label='{text}']"
        )
        wait = WebDriverWait(self.driver, timeout=self.timeout)
        wait.until(EC.visibility_of_element_located((strategy, locator)))
        self.driver.find_element(strategy, locator).click()

    def fill_by_id(self, accessibility_id: str, value: str) -> None:
        """按 accessibility_id 找到输入框并填入内容。"""
        self.wait_visible_by_id(accessibility_id)
        element = self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, accessibility_id)
        element.clear()
        element.send_keys(value)

    def scroll_down(self) -> None:
        """向下滑动（从屏幕 70% 滑到 30%）。"""
        size = self.driver.get_window_size()
        self.driver.swipe(
            start_x=size["width"] // 2,
            start_y=int(size["height"] * 0.7),
            end_x=size["width"] // 2,
            end_y=int(size["height"] * 0.3),
            duration=500,
        )

    # ── 截图 ──

    def screenshot(self, name: str) -> str:
        """关键节点截图，返回文件路径。"""
        scenario_dir = SCREENSHOTS_DIR / self.__class__.__name__
        scenario_dir.mkdir(parents=True, exist_ok=True)
        ts = datetime.now().strftime("%Y%m%d_%H%M%S")
        path = str(scenario_dir / f"{name}_{self.platform}_{ts}.png")
        self.driver.save_screenshot(path)
        return path
