"""
debug_benry_login.py - ベンリー新UI ログイン画面状態調査スクリプト（改良版）

headless 実行時にベンリーのログイン画面が実際どんな状態で表示されているかを
スクリーンショット・HTMLダンプで詳細に記録する。

複数時点でスクリーンショットを撮影:
  t1: networkidle 直後
  t2: .loading/.spinner が消えた後
  t3: さらに 5秒後（最終確認）

ログイン操作は行わない。DB接続不要。

Usage:
    python tools/debug_benry_login.py
"""

import logging
import sys
from pathlib import Path

from playwright.sync_api import Page, sync_playwright
from playwright_stealth import Stealth

# ---------------------------------------------------------------------------
# 定数
# ---------------------------------------------------------------------------
BENRY_URL    = "https://mrvenrey.jp/#/admin"
TOOLS_DIR    = Path(__file__).parent
DUMP_PATH    = TOOLS_DIR / "debug_benry_dump.txt"
SS_T1_PATH   = TOOLS_DIR / "debug_benry_t1.png"
SS_T2_PATH   = TOOLS_DIR / "debug_benry_t2.png"
SS_T3_PATH   = TOOLS_DIR / "debug_benry_t3.png"
PAGE_TIMEOUT = 30_000  # ms

# 注目キーワード（outerHTML付き詳細ダンプ対象）
FOCUS_KEYWORDS = ["別アカウント", "ログイン", "様"]

# ---------------------------------------------------------------------------
# ロガー
# ---------------------------------------------------------------------------
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
)
logger = logging.getLogger(__name__)


# ---------------------------------------------------------------------------
# スクリーンショット保存
# ---------------------------------------------------------------------------
def save_ss(page: Page, path: Path, label: str) -> None:
    try:
        page.screenshot(path=str(path), full_page=True)
        logger.info("スクリーンショット保存[%s]: %s", label, path)
    except Exception as e:
        logger.warning("スクリーンショット失敗[%s]: %s", label, e)


# ---------------------------------------------------------------------------
# Angular ローディング待機
# ---------------------------------------------------------------------------
def wait_for_angular(page: Page, label: str) -> None:
    """
    .loading / .spinner 等が消えるまで最大 15 秒待機。
    消えなくても続行する。
    """
    loading_sels = [
        ".loading",
        ".spinner",
        "[class*='loading']",
        "[class*='spinner']",
        "mat-progress-bar",
        "mat-spinner",
    ]
    for sel in loading_sels:
        try:
            el = page.locator(sel)
            if el.count() > 0 and el.first.is_visible():
                logger.info("[%s] ローディング要素(%s)を検出、消えるまで待機...", label, sel)
                el.first.wait_for(state="hidden", timeout=15_000)
                logger.info("[%s] ローディング消滅を確認", label)
                break
        except Exception:
            pass


# ---------------------------------------------------------------------------
# ページ情報ダンプ（最終状態）
# ---------------------------------------------------------------------------
def dump_page(page: Page) -> str:
    lines = []
    sep = "=" * 70

    # --- URL / タイトル ---
    lines.append(sep)
    lines.append("  最終状態ダンプ (t3: networkidle + Angular待機 + 5秒後)")
    lines.append(sep)
    lines.append(f"[URL]   {page.url}")
    lines.append(f"[TITLE] {page.title()}")
    lines.append("")

    # --- body innerText（画面全体のテキスト）---
    lines.append("--- body innerText（画面に見えているテキスト）---")
    try:
        body_text = page.locator("body").inner_text()
        lines.append(body_text[:3000])
    except Exception as e:
        lines.append(f"[取得エラー: {e}]")
    lines.append("")

    # --- 全 input 要素 ---
    lines.append("--- <input> 要素 一覧（is_visible 含む）---")
    inputs = page.locator("input")
    count = inputs.count()
    if count == 0:
        lines.append("  (なし)")
    for i in range(count):
        el = inputs.nth(i)
        attrs = {}
        for attr in ["type", "name", "id", "placeholder", "formcontrolname", "class", "autocomplete"]:
            v = el.get_attribute(attr)
            if v is not None:
                attrs[attr] = v
        try:
            visible = el.is_visible()
        except Exception:
            visible = "?"
        try:
            outer = el.evaluate("el => el.outerHTML")
        except Exception:
            outer = "(取得不可)"
        lines.append(f"  [{i}] visible={visible}  attrs={attrs}")
        lines.append(f"       outerHTML={outer[:300]}")
    lines.append("")

    # --- 全 button 要素 ---
    lines.append("--- <button> 要素 一覧（is_visible 含む）---")
    buttons = page.locator("button")
    count = buttons.count()
    if count == 0:
        lines.append("  (なし)")
    for i in range(count):
        el = buttons.nth(i)
        try:
            txt     = el.inner_text().strip()
            cls     = el.get_attribute("class") or ""
            bid     = el.get_attribute("id") or ""
            visible = el.is_visible()
            outer   = el.evaluate("el => el.outerHTML")
            lines.append(f"  [{i}] visible={visible}  text={txt!r}  id={bid!r}  class={cls!r}")
            lines.append(f"       outerHTML={outer[:300]}")
        except Exception as e:
            lines.append(f"  [{i}] [取得エラー: {e}]")
    lines.append("")

    # --- テキストがある <a> 要素 ---
    lines.append("--- <a> 要素（テキストありのみ / is_visible 含む）---")
    anchors = page.locator("a")
    count = anchors.count()
    found_any = False
    for i in range(count):
        el = anchors.nth(i)
        try:
            txt = el.inner_text().strip()
            if not txt:
                continue
            href    = el.get_attribute("href") or ""
            cls     = el.get_attribute("class") or ""
            visible = el.is_visible()
            lines.append(f"  [{i}] visible={visible}  text={txt!r}  href={href!r}  class={cls!r}")
            found_any = True
        except Exception:
            pass
    if not found_any:
        lines.append("  (テキストあり <a> なし)")
    lines.append("")

    # --- 注目キーワードを含む要素の詳細 ---
    lines.append(f"--- 注目キーワード {FOCUS_KEYWORDS} を含む要素の詳細 ---")
    for kw in FOCUS_KEYWORDS:
        found = False
        for tag in ["button", "a", "span", "div", "p", "h1", "h2", "h3"]:
            try:
                loc = page.locator(f"{tag}:has-text('{kw}')")
                n = loc.count()
                for i in range(n):
                    el = loc.nth(i)
                    try:
                        txt     = el.inner_text().strip()
                        cls     = el.get_attribute("class") or ""
                        visible = el.is_visible()
                        outer   = el.evaluate("el => el.outerHTML")
                        lines.append(f"  keyword={kw!r}  tag={tag}  [{i}] visible={visible}  text={txt!r}  class={cls!r}")
                        lines.append(f"    outerHTML={outer[:400]}")
                        found = True
                    except Exception:
                        pass
            except Exception:
                pass
        if not found:
            lines.append(f"  keyword={kw!r}: 該当要素なし")
    lines.append("")

    # --- ページHTML 先頭 3000文字 ---
    lines.append("--- ページHTML 先頭3000文字 ---")
    try:
        lines.append(page.content()[:3000])
    except Exception as e:
        lines.append(f"[取得エラー: {e}]")
    lines.append("")

    return "\n".join(lines)


# ---------------------------------------------------------------------------
# メイン
# ---------------------------------------------------------------------------
def main() -> None:
    logger.info("ベンリーログイン画面状態調査開始")
    logger.info("対象URL: %s", BENRY_URL)
    logger.info("出力先: %s / %s / %s / %s", SS_T1_PATH, SS_T2_PATH, SS_T3_PATH, DUMP_PATH)

    output_text = ""

    with sync_playwright() as pw:
        browser = pw.chromium.launch(
            headless=True,
            args=["--no-sandbox", "--disable-blink-features=AutomationControlled"],
        )
        context = browser.new_context(
            user_agent=(
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                "AppleWebKit/537.36 (KHTML, like Gecko) "
                "Chrome/124.0.0.0 Safari/537.36"
            ),
            viewport={"width": 1280, "height": 800},
            locale="ja-JP",
            timezone_id="Asia/Tokyo",
        )
        page = context.new_page()
        Stealth().apply_stealth_sync(page)
        page.set_default_timeout(PAGE_TIMEOUT)

        try:
            # --- t1: networkidle 直後 ---
            logger.info("[t1] ページ取得中 (wait_until=networkidle)...")
            page.goto(BENRY_URL, wait_until="networkidle", timeout=PAGE_TIMEOUT)
            logger.info("[t1] networkidle 完了: %s", page.url)
            save_ss(page, SS_T1_PATH, "t1_networkidle直後")

            # --- t2: Angular ローディング待機後 ---
            logger.info("[t2] Angular ローディング待機...")
            wait_for_angular(page, "t2")
            page.wait_for_timeout(1000)
            logger.info("[t2] Angular 待機完了")
            save_ss(page, SS_T2_PATH, "t2_Angular待機後")

            # --- t3: さらに 5秒後 ---
            logger.info("[t3] さらに 5秒待機...")
            page.wait_for_timeout(5000)
            logger.info("[t3] 5秒待機完了")
            save_ss(page, SS_T3_PATH, "t3_5秒後")

            # --- 詳細ダンプ（t3 の状態で）---
            logger.info("ページ情報ダンプ中...")
            output_text = dump_page(page)

        except Exception as e:
            logger.error("エラー: %s", e)
            output_text = f"[エラー発生]\n{e}\n"
            try:
                page.screenshot(path=str(SS_T1_PATH), full_page=True)
            except Exception:
                pass
            sys.exit(1)
        finally:
            browser.close()

    # --- ダンプファイル書き出し ---
    try:
        DUMP_PATH.write_text(output_text, encoding="utf-8")
        logger.info("ダンプ出力完了: %s", DUMP_PATH)
    except Exception as e:
        logger.error("ダンプファイル書き込み失敗: %s", e)
        sys.exit(1)

    logger.info("調査完了")


if __name__ == "__main__":
    main()
