"""
店名取得スクリプト

指定媒体の管理画面にログインして店舗名を取得し、
media_settings の shop_name カラムに保存する。

対応媒体:
  girlsheaven : manager.girlsheaven-job.net
  vanilla      : qzin.jp/entry/

Usage:
    python tools/get_shop_name.py <client_id> <media_name>

例:
    python tools/get_shop_name.py 1 girlsheaven
    python tools/get_shop_name.py 1 vanilla
"""

import argparse
import logging
import os
import random
import sys
from datetime import datetime
from pathlib import Path

from playwright.sync_api import Page, sync_playwright
from playwright_stealth import Stealth

sys.path.append(str(Path(__file__).resolve().parents[1]))
from config.database import execute_query, execute_update

GH_LOGIN_URL = "https://manager.girlsheaven-job.net/"
VANILLA_LOGIN_URL = "https://qzin.jp/entry/"
PAGE_TIMEOUT = 30_000

VIEWPORTS = [
    {"width": 1280, "height": 800},
    {"width": 1366, "height": 768},
    {"width": 1920, "height": 1080},
    {"width": 1440, "height": 900},
]

logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)


def get_media_settings(client_id: int, media_name: str) -> dict | None:
    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 save_shop_name(client_id: int, media_name: str, shop_name: str) -> None:
    rowcount = execute_update(
        "UPDATE media_settings SET shop_name = %s WHERE client_id = %s AND media_name = %s",
        (shop_name, client_id, media_name), local=False,
    )
    logger.info("shop_name更新完了: %d行 (value='%s', client_id=%d, media=%s)", rowcount, shop_name, client_id, media_name)


def save_error_log(client_id: int, media_name: str, message: str) -> None:
    try:
        execute_update(
            "INSERT INTO error_logs (client_id, media_name, error_type, error_message, occurred_at) VALUES (%s, %s, %s, %s, %s)",
            (client_id, media_name, "get_shop_name_error", message, datetime.now()), local=True,
        )
    except Exception as e:
        logger.error("エラーログのDB保存も失敗: %s", e)


def build_browser(p):
    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",
        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 get_shop_name_girlsheaven(page: Page, login_id: str, login_pass: str) -> str:
    logger.info("GH管理画面にアクセス: %s", GH_LOGIN_URL)
    page.goto(GH_LOGIN_URL, timeout=PAGE_TIMEOUT, wait_until="domcontentloaded")
    page.wait_for_timeout(random.randint(1000, 2000))
    page.fill("#loginId", login_id)
    page.fill("#loginPass", login_pass)
    page.click("#login_btn")
    page.wait_for_url("**/top/**", timeout=15_000)
    page.goto("https://manager.girlsheaven-job.net/top/", timeout=PAGE_TIMEOUT)
    page.wait_for_load_state("networkidle", timeout=15_000)
    text = None
    shop_name = None
    status_el = page.locator("#globalHeaderLoginStatus")
    if status_el.count() > 0:
        text = status_el.inner_text().strip()
        shop_name = text.split("様")[0].strip()
        logger.info("GH店名取得成功: %s", shop_name)
    else:
        body_text = page.inner_text("body")
        for line in body_text.split("\n"):
            if "様でログイン中" in line:
                shop_name = line.split("様")[0].strip()
                text = line
                logger.info("GH店名取得成功(方法2): %s", shop_name)
                break
    logger.info("取得テキスト全文: %s", text)
    logger.info("抽出した店名: %s", shop_name)
    if not shop_name:
        raise RuntimeError("店舗名を取得できませんでした")
    return shop_name


def get_shop_name_vanilla(page: Page, login_id: str, login_pass: str) -> str:
    import re
    logger.info("バニラ管理画面にアクセス: %s", VANILLA_LOGIN_URL)
    page.goto(VANILLA_LOGIN_URL, timeout=PAGE_TIMEOUT, wait_until="domcontentloaded")
    page.wait_for_timeout(random.randint(1000, 2000))
    id_field = None
    for sel in ["input[name='login_id']", "input[type='text']"]:
        el = page.locator(sel).first
        if el.count() > 0 and el.is_visible():
            id_field = el
            break
    if id_field is None:
        raise RuntimeError("ログインIDフィールドが見つかりません")
    pass_field = None
    for sel in ["input[name='login_pass']", "input[type='password']"]:
        el = page.locator(sel).first
        if el.count() > 0 and el.is_visible():
            pass_field = el
            break
    if pass_field is None:
        raise RuntimeError("パスワードフィールドが見つかりません")
    id_field.fill(login_id)
    page.wait_for_timeout(random.randint(300, 600))
    pass_field.fill(login_pass)
    page.wait_for_timeout(random.randint(300, 600))
    login_btn = None
    for sel in ["input[type='submit']", "button:has-text('ログイン')"]:
        el = page.locator(sel).first
        if el.count() > 0 and el.is_visible():
            login_btn = el
            break
    if login_btn is None:
        raise RuntimeError("ログインボタンが見つかりません")
    login_btn.click()
    page.wait_for_timeout(random.randint(3000, 4000))
    shop_name = None
    text = None
    content = page.content()
    match = re.search(r'([^\n<>]+?)　様　ログインありがとうございます', content)
    if match:
        shop_name = match.group(1).strip()
        text = match.group(0)
        logger.info("方法1で店名取得: %s", shop_name)
    else:
        body_text = page.inner_text('body')
        for line in body_text.split('\n'):
            if '様' in line and 'ログインありがとうございます' in line:
                text = line
                shop_name = line.split('様')[0].strip()
                logger.info("方法2で店名取得: %s", shop_name)
                break
    logger.info("取得テキスト全文: %s", text)
    logger.info("抽出した店名: %s", shop_name)
    if not shop_name:
        raise RuntimeError("バニラ店舗名を取得できませんでした")
    return shop_name


def main() -> None:
    parser = argparse.ArgumentParser(description="店名取得スクリプト")
    parser.add_argument("client_id", type=int, help="クライアントID")
    parser.add_argument("media_name", type=str, choices=["girlsheaven", "vanilla"], help="媒体名")
    args = parser.parse_args()
    client_id = args.client_id
    media_name = args.media_name
    logger.info("店名取得開始 | client_id=%d media=%s", client_id, media_name)
    try:
        settings = get_media_settings(client_id, media_name)
    except Exception as e:
        logger.error("media_settings 取得エラー: %s", e)
        save_error_log(client_id, media_name, f"media_settings取得失敗: {e}")
        sys.exit(1)
    if settings is None:
        logger.error("client_id=%d media=%s の media_settings が見つかりません", client_id, media_name)
        save_error_log(client_id, media_name, f"media_settingsが見つかりません (client_id={client_id})")
        sys.exit(1)
    try:
        with sync_playwright() as p:
            browser, page = build_browser(p)
            try:
                if media_name == "girlsheaven":
                    shop_name = get_shop_name_girlsheaven(page, settings["login_id"], settings["login_pass"])
                else:
                    shop_name = get_shop_name_vanilla(page, settings["login_id"], settings["login_pass"])
            finally:
                browser.close()
    except Exception as e:
        error_msg = f"店名取得失敗 (client_id={client_id}, media={media_name}): {e}"
        logger.error(error_msg)
        save_error_log(client_id, media_name, error_msg)
        sys.exit(1)
    if not shop_name:
        error_msg = f"取得した店名が空です (client_id={client_id}, media={media_name})"
        logger.error(error_msg)
        save_error_log(client_id, media_name, error_msg)
        sys.exit(1)
    try:
        save_shop_name(client_id, media_name, shop_name)
    except Exception as e:
        error_msg = f"shop_name保存失敗 (client_id={client_id}, media={media_name}): {e}"
        logger.error(error_msg)
        save_error_log(client_id, media_name, error_msg)
        sys.exit(1)
    logger.info("完了 | client_id=%d media=%s shop_name='%s'", client_id, media_name, shop_name)


if __name__ == "__main__":
    main()
