"""
GH店名取得デバッグスクリプト

headless=True のまま GH 管理画面へログインし、
遷移後の状態（URL・タイトル・本文・エラー要素）を
テキストファイルとスクリーンショットに保存する。

Usage:
    python debug_shop_name.py <client_id> girlsheaven

出力:
    python/tools/debug_shop_result.txt  -- 状態テキスト
    python/tools/debug_shop_result.png  -- スクリーンショット
"""

import argparse
import logging
import random
import sys
from datetime import datetime
from pathlib import Path

from playwright.sync_api import sync_playwright
from playwright_stealth import Stealth

sys.path.append(str(Path(__file__).resolve().parents[1]))
from config.database import execute_query

GH_LOGIN_URL = "https://manager.girlsheaven-job.net/"
PAGE_TIMEOUT = 30_000

VIEWPORTS = [
    {"width": 1280, "height": 800},
    {"width": 1366, "height": 768},
    {"width": 1920, "height": 1080},
    {"width": 1440, "height": 900},
]

OUT_DIR = Path(__file__).parent
TXT_OUT = OUT_DIR / "debug_shop_result.txt"
PNG_OUT = OUT_DIR / "debug_shop_result.png"

logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)


# ---------------------------------------------------------------------------
# DB
# ---------------------------------------------------------------------------
def get_media_settings(client_id: int, media_name: str) -> dict | None:
    """media_settings から login_id / login_pass を取得する（カゴヤDB）。"""
    rows = execute_query(
        "SELECT login_id, login_pass FROM media_settings "
        "WHERE client_id = %s AND media_name = %s AND is_active = 1 LIMIT 1",
        (client_id, media_name),
        local=False,
    )
    if not rows:
        return None
    return {"login_id": rows[0]["login_id"], "login_pass": rows[0]["login_pass"]}


# ---------------------------------------------------------------------------
# ブラウザ
# ---------------------------------------------------------------------------
def build_browser(p):
    """headless=True でブラウザを起動し、ステルス設定済みの page を返す。"""
    browser = p.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=random.choice(VIEWPORTS),
        locale="ja-JP",
        timezone_id="Asia/Tokyo",
        extra_http_headers={
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
            "Accept-Language": "ja,en-US;q=0.7,en;q=0.3",
            "Accept-Encoding": "gzip, deflate, br",
            "Connection": "keep-alive",
            "Upgrade-Insecure-Requests": "1",
            "Sec-Fetch-Dest": "document",
            "Sec-Fetch-Mode": "navigate",
            "Sec-Fetch-Site": "none",
            "Sec-Fetch-User": "?1",
        },
    )
    page = context.new_page()
    Stealth().apply_stealth_sync(page)
    return browser, page


# ---------------------------------------------------------------------------
# 状態収集
# ---------------------------------------------------------------------------
def collect_debug_info(page) -> dict:
    """ページの現在状態をまとめて dict で返す。例外が出ても可能な範囲で収集する。"""
    info: dict = {}

    # URL / タイトル
    info["url"] = page.url
    try:
        info["title"] = page.title()
    except Exception as e:
        info["title"] = f"(取得失敗: {e})"

    # body テキスト（先頭 2000 文字）
    try:
        info["body_text"] = page.inner_text("body")[:2000]
    except Exception as e:
        info["body_text"] = f"(取得失敗: {e})"

    # #globalHeaderLoginStatus
    try:
        el = page.locator("#globalHeaderLoginStatus")
        info["login_status_exists"] = el.count() > 0
        info["login_status_text"] = el.inner_text().strip() if info["login_status_exists"] else ""
    except Exception as e:
        info["login_status_exists"] = False
        info["login_status_text"] = f"(取得失敗: {e})"

    # エラー要素（複数セレクタを試す）
    error_texts: list[str] = []
    for sel in [
        ".error", ".alert", ".alert-danger", ".alert-error",
        ".login-error", "#errorMsg", "#loginError",
        "[class*='error']", "[class*='alert']",
    ]:
        try:
            els = page.locator(sel)
            for i in range(min(els.count(), 5)):
                t = els.nth(i).inner_text().strip()
                if t:
                    error_texts.append(f"{sel}: {t}")
        except Exception:
            pass
    info["error_elements"] = error_texts

    return info


# ---------------------------------------------------------------------------
# 出力
# ---------------------------------------------------------------------------
def write_txt(info: dict, extra_notes: str = "") -> None:
    """収集情報を TXT_OUT に書き出す。"""
    lines = [
        "=== GH店名取得 デバッグレポート ===",
        f"生成日時: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
        "",
        "【現在のURL】",
        info.get("url", "(不明)"),
        "",
        "【ページタイトル】",
        info.get("title", "(不明)"),
        "",
        "【#globalHeaderLoginStatus】",
        f"  存在: {info.get('login_status_exists', False)}",
        f"  テキスト: {info.get('login_status_text', '')}",
        "",
        "【エラー要素】",
    ]
    errors = info.get("error_elements", [])
    if errors:
        for e in errors:
            lines.append(f"  {e}")
    else:
        lines.append("  (なし)")

    lines += [
        "",
        "【bodyテキスト（先頭2000文字）】",
        info.get("body_text", "(不明)"),
    ]

    if extra_notes:
        lines += ["", "【補足・例外】", extra_notes]

    TXT_OUT.write_text("\n".join(lines), encoding="utf-8")
    logger.info("テキスト出力: %s", TXT_OUT)


# ---------------------------------------------------------------------------
# メイン処理
# ---------------------------------------------------------------------------
def run_debug(client_id: int, media_name: str) -> None:
    logger.info("デバッグ開始 | client_id=%d media=%s", client_id, media_name)

    # DB から認証情報を取得
    settings = get_media_settings(client_id, media_name)
    if settings is None:
        logger.error(
            "media_settings に client_id=%d / media=%s の有効な設定がありません "
            "(is_active=1 の行が必要です)",
            client_id,
            media_name,
        )
        sys.exit(1)
    logger.info("login_id 取得OK: %s", settings["login_id"])

    with sync_playwright() as p:
        browser, page = build_browser(p)
        debug_info: dict = {}
        extra_notes = ""

        try:
            # ステップ1: GH 管理画面を開く
            logger.info("GH管理画面にアクセス: %s", GH_LOGIN_URL)
            page.goto(GH_LOGIN_URL, timeout=PAGE_TIMEOUT, wait_until="domcontentloaded")
            page.wait_for_timeout(1500)

            # ステップ2: フォーム要素の存在確認
            for sel in ["#loginId", "#loginPass", "#login_btn"]:
                exists = page.locator(sel).count() > 0
                logger.info("セレクタ %-20s : %s", sel, "存在する ✓" if exists else "見つからない ✗")

            # ステップ3: 入力・クリック
            logger.info("ログイン情報を入力してボタンをクリックします")
            page.fill("#loginId", settings["login_id"])
            page.fill("#loginPass", settings["login_pass"])
            page.click("#login_btn")

            # ステップ4: wait_for_url を使わず時間待ちで「今どこにいるか」を確認
            logger.info("クリック後 5秒待機します（wait_for_url を使わず状態確認）")
            page.wait_for_timeout(5000)
            logger.info("URL（5秒後）: %s", page.url)

            try:
                page.wait_for_load_state("networkidle", timeout=10_000)
                logger.info("networkidle 到達")
            except Exception:
                logger.warning("networkidle タイムアウト（続行します）")

            logger.info("URL（networkidle後）: %s", page.url)

            # ステップ5: 状態収集
            debug_info = collect_debug_info(page)

        except Exception as e:
            extra_notes = f"{type(e).__name__}: {e}"
            logger.error("例外発生: %s", extra_notes)
            try:
                debug_info = collect_debug_info(page)
            except Exception:
                pass

        finally:
            # ステップ6: スクリーンショット（例外が出ても必ず実行）
            try:
                page.screenshot(path=str(PNG_OUT), full_page=True)
                logger.info("スクリーンショット保存: %s", PNG_OUT)
            except Exception as se:
                logger.error("スクリーンショット保存失敗: %s", se)

            # ステップ7: テキスト出力
            write_txt(debug_info, extra_notes)

            browser.close()


# ---------------------------------------------------------------------------
# エントリポイント
# ---------------------------------------------------------------------------
def main() -> None:
    parser = argparse.ArgumentParser(description="GH店名取得デバッグスクリプト（headless）")
    parser.add_argument("client_id", type=int, help="クライアントID")
    parser.add_argument(
        "media_name",
        type=str,
        choices=["girlsheaven"],
        help="媒体名（現在は girlsheaven のみ）",
    )
    args = parser.parse_args()
    run_debug(args.client_id, args.media_name)


if __name__ == "__main__":
    main()
