import pyautogui
import pygetwindow as gw

from common.config_loader import loadOcrConfig
from common.project_paths import RUNTIME_DIR

SCREENSHOT_PATH = RUNTIME_DIR / "latest_screenshot.png"
OCR_SCREENSHOT_PATH = RUNTIME_DIR / "latest_ocr.png"

EXCLUDED_WINDOW_KEYWORDS = [
    "Google Chrome",
    "Microsoft Edge",
    "Mozilla Firefox",
    "Visual Studio Code",
    "PowerShell",
    "Windows Terminal",
    "ChatGPT",
]


def log(level, message):
    from datetime import datetime

    now = datetime.now().strftime("%H:%M:%S")
    print(f"[{level}] {now} {message}", flush=True)


def findVrchatWindow():
    windows = gw.getAllWindows()
    candidates = []

    for window in windows:
        title = window.title or ""
        normalized = title.strip().lower()
        if not normalized:
            continue
        if any(keyword.lower() in normalized for keyword in EXCLUDED_WINDOW_KEYWORDS):
            continue

        if normalized == "vrchat":
            candidates.append((0, window))
            continue
        if normalized.startswith("vrchat "):
            candidates.append((1, window))
            continue
        if normalized.startswith("vrchat"):
            candidates.append((2, window))

    if not candidates:
        visible_titles = []
        for window in windows:
            title = (window.title or "").strip()
            if title:
                visible_titles.append(title)

        log("ERROR", "VRChatウィンドウが見つかりません")
        log("CHECK", "現在検出できるウィンドウ")
        for title in visible_titles[:30]:
            print(title, flush=True)

        raise RuntimeError("VRChatウィンドウが見つかりません")

    candidates = sorted(
        candidates,
        key=lambda item: (item[0], -(item[1].width * item[1].height)),
    )
    window = candidates[0][1]

    if window.width <= 0 or window.height <= 0:
        raise RuntimeError("VRChatウィンドウサイズが不正です")

    return window


def getVrchatRegion():
    window = findVrchatWindow()

    try:
        if window.isMinimized:
            window.restore()
    except Exception:
        pass

    left = int(window.left)
    top = int(window.top)
    width = int(window.width)
    height = int(window.height)

    if width <= 0 or height <= 0:
        raise RuntimeError("VRChatウィンドウ範囲が不正です")

    log("INFO", f"VRChat window title={window.title}")
    log("INFO", f"VRChat region left={left} top={top} width={width} height={height}")
    return left, top, width, height


def clampRatio(value):
    return max(0.0, min(1.0, value))


def getOcrRegion():
    left, top, width, height = getVrchatRegion()
    config = loadOcrConfig()

    # Default to the lower central area. It is much faster than OCRing the
    # whole VRChat window and usually contains chat/subtitle text.
    crop_left = clampRatio(config["crop_left"])
    crop_top = clampRatio(config["crop_top"])
    crop_right = clampRatio(config["crop_right"])
    crop_bottom = clampRatio(config["crop_bottom"])

    if crop_right <= crop_left:
        crop_left = 0.0
        crop_right = 1.0

    if crop_bottom <= crop_top:
        crop_top = 0.0
        crop_bottom = 1.0

    region_left = left + int(width * crop_left)
    region_top = top + int(height * crop_top)
    region_width = max(1, int(width * (crop_right - crop_left)))
    region_height = max(1, int(height * (crop_bottom - crop_top)))

    log(
        "INFO",
        f"OCR crop left={region_left} top={region_top} width={region_width} height={region_height}",
    )
    return region_left, region_top, region_width, region_height


def captureRegionTo(image_path, region):
    image_path.parent.mkdir(parents=True, exist_ok=True)

    left, top, width, height = region

    image = pyautogui.screenshot(region=(left, top, width, height))
    image.save(image_path)

    log("ACTION", f"captureVrchatWindow saved={image_path}")
    return image_path


def captureVrchatWindowTo(image_path):
    return captureRegionTo(
        image_path,
        getVrchatRegion(),
    )


def captureVrchatWindow():
    return captureVrchatWindowTo(SCREENSHOT_PATH)


def captureOcrRegion():
    return captureRegionTo(
        OCR_SCREENSHOT_PATH,
        getOcrRegion(),
    )


def captureScreen():
    return captureVrchatWindow()


def takeScreenshot():
    return captureVrchatWindow()
