"""
バニラ 最大更新回数取得スクリプト

バニラ（qzin.jp）の店舗上位表示設定画面にある削除ボタンの個数を取得し、
media_settings の max_update_count に保存する。

Usage:
    python tools/get_update_count_vanilla.py <client_id>
"""

import argparse
import logging
import os
import sys
from datetime import datetime
from pathlib import Path

from playwright.sync_api import sync_playwright

sys.path.append(str(Path(__file__).resolve().parents[1]))
from config.database import execute_query, execute_update  # load_dotenv() は自動実行

# ---------------------------------------------------------------------------
# 定数
# ---------------------------------------------------------------------------
VANILLA_URL = "https://qzin.jp/entry/"
MEDIA_NAME  = "vanilla"

# ---------------------------------------------------------------------------
# ロガー設定
# ---------------------------------------------------------------------------
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
)
logger = logging.getLogger(__name__)


# ---------------------------------------------------------------------------
# DB ヘルパー
# ---------------------------------------------------------------------------
def get_media_settings(client_id: int) -> dict | None:
    """カゴヤDB の media_settings から vanilla の設定を取得する。"""
    rows = execute_query(
        """
        SELECT login_id, login_pass, is_active
        FROM media_settings
        WHERE client_id = %s AND media_name = %s
        LIMIT 1
        """,
        (client_id, MEDIA_NAME),
        local=False,
    )
    if not rows:
        return None
    row = rows[0]
    return {
        "login_id":   row["login_id"],
        "login_pass": row["login_pass"],
        "is_active":  row["is_active"],
    }


def save_max_update_count(client_id: int, count: int) -> None:
    """media_settings の max_update_count を更新する。"""
    execute_update(
        """
        UPDATE media_settings
        SET max_update_count = %s
        WHERE client_id = %s AND media_name = %s
        """,
        (count, client_id, MEDIA_NAME),
        local=False,
    )
    logger.info("max_update_count を %d に保存しました (client_id=%d)", count, client_id)


def save_error_log(client_id: int, message: str) -> None:
    """error_logs にエラーを記録する（local=False）。"""
    try:
        execute_update(
            """
            INSERT INTO error_logs
                (client_id, error_type, error_message, occurred_at)
            VALUES (%s, %s, %s, %s)
            """,
            (client_id, "vanilla_error", message, datetime.now()),
            local=False,
        )
    except Exception as e:
        logger.error("エラーログのDB保存も失敗: %s", e)


# ---------------------------------------------------------------------------
# ブラウザ起動
# ---------------------------------------------------------------------------
def build_browser(p):
    """HEADLESS 環境変数に従いブラウザを起動し、(browser, page) を返す。"""
    headless = os.getenv("HEADLESS", "true").lower() != "false"
    if headless:
        browser = p.chromium.launch(
            headless=True,
            args=["--no-sandbox", "--disable-blink-features=AutomationControlled"],
        )
    else:
        browser = p.chromium.launch(
            headless=False,
            executable_path=r"C:\Program Files\Google\Chrome\Application\chrome.exe",
            slow_mo=500,
            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"
        ),
        locale="ja-JP",
        timezone_id="Asia/Tokyo",
    )
    page = context.new_page()
    return browser, page


# ---------------------------------------------------------------------------
# 更新回数取得本体
# ---------------------------------------------------------------------------
def get_update_count(client_id: int, settings: dict) -> int:
    """バニラにログインして削除ボタンの個数を取得して返す。"""
    login_id   = settings["login_id"]
    login_pass = settings["login_pass"]

    with sync_playwright() as p:
        browser, page = build_browser(p)
        try:
            # ① アクセス
            logger.info("バニラにアクセス: %s", VANILLA_URL)
            page.goto(VANILLA_URL, timeout=30_000, wait_until="domcontentloaded")
            page.wait_for_timeout(2000)

            # ② ログイン
            logger.info("ログイン処理")
            page.fill("input[name='username']", str(login_id))
            page.fill("input[name='password']", str(login_pass))
            page.click("input[type='submit']")
            page.wait_for_timeout(3000)

            # ③ 「店舗上位表示を設定する」ボタンをクリック
            logger.info("「店舗上位表示を設定する」ボタンをクリック")
            allup_selectors = [
                "#allupform img",
                "#allupform input[type='image']",
                "form#allupform button",
                "form#allupform input[type='submit']",
            ]
            clicked = False
            for sel in allup_selectors:
                el = page.locator(sel).first
                if el.count() > 0 and el.is_visible():
                    logger.info("上位表示ボタンをクリック: %s", sel)
                    el.click(force=True)
                    clicked = True
                    break
            if not clicked:
                raise RuntimeError("「店舗上位表示を設定する」ボタンが見つかりません")
            page.wait_for_timeout(3000)

            # ④ 各時間帯削除ボタンの個数を取得（最も件数が多いセレクタを採用）
            delete_btn_selectors = [
                "input[name='js-delete']",
                "button:has-text('削除')",
                "input[value='削除']",
                "input[type='submit'][value='削除']",
                "td input[type='submit']",
            ]
            best_sel = None
            count = 0
            for sel in delete_btn_selectors:
                c = page.locator(sel).count()
                logger.info("削除ボタン候補: %s → %d件", sel, c)
                if c > count:
                    count = c
                    best_sel = sel
            logger.info("採用セレクタ: %s | 削除ボタン個数（max_update_count）: %d", best_sel, count)
            return count

        finally:
            browser.close()


# ---------------------------------------------------------------------------
# エントリポイント
# ---------------------------------------------------------------------------
def main() -> None:
    parser = argparse.ArgumentParser(description="バニラ 最大更新回数取得")
    parser.add_argument("client_id", type=int, help="クライアントID")
    args = parser.parse_args()
    client_id = args.client_id

    logger.info("バニラ更新回数取得開始 | client_id=%d", client_id)

    # media_settings 取得
    try:
        settings = get_media_settings(client_id)
    except Exception as e:
        logger.error("media_settings 取得エラー: %s", e)
        save_error_log(client_id, f"media_settings取得失敗: {e}")
        sys.exit(1)

    if settings is None:
        logger.error("client_id=%d の media_settings(vanilla) が見つかりません", client_id)
        save_error_log(client_id, f"media_settingsが見つかりません (client_id={client_id})")
        sys.exit(1)

    if settings["is_active"] == 0:
        logger.info("is_active=0 のためスキップします (client_id=%d)", client_id)
        sys.exit(0)

    # 更新回数取得
    try:
        count = get_update_count(client_id, settings)
    except Exception as e:
        error_msg = f"更新回数取得失敗 (client_id={client_id}): {e}"
        logger.error(error_msg)
        save_error_log(client_id, error_msg)
        sys.exit(1)

    # max_update_count を保存
    try:
        save_max_update_count(client_id, count)
    except Exception as e:
        error_msg = f"max_update_count保存失敗 (client_id={client_id}): {e}"
        logger.error(error_msg)
        save_error_log(client_id, error_msg)
        sys.exit(1)

    logger.info("完了 | client_id=%d max_update_count=%d", client_id, count)


if __name__ == "__main__":
    main()
