"""
Entry point: `sora` CLI
  sora setup           — cau hinh profiles va mo Chrome de dang nhap
  sora setup --retry   — mo lai profile cu de dang nhap lai
  sora run             — chay tu dong tao video
  sora help            — hien thi huong dan
"""
from __future__ import annotations

import sys
import time
from math import ceil

import click

from .config import load_settings, save_settings, validate_settings
from .profile_manager import ensure_profile_exists
from .browser_launcher import launch_chrome_for_login, launch_chrome_for_automation, close_chrome
from .sora_bot import reset_page, create_video
from .api_client import get_pending_products, mark_product_done
from .telegram_notifier import (
    notify_product_done,
    notify_product_failed,
    notify_profile_done,
    notify_all_done,
)
from .run_tracker import record_product_done, record_product_failed
from .constants import PRODUCTS_PER_PROFILE, WAIT_BETWEEN_PRODUCTS_SEC, CDP_PORT_BASE, API_BASE_URL, SORA_URL

_LINE = "─" * 56
_BOLD = "=" * 56


# ===========================================================================
# CLI group
# ===========================================================================

def _ensure_playwright_browsers() -> None:
    """Cai Playwright Chromium tu dong neu chua co."""
    import subprocess
    from playwright.sync_api import sync_playwright
    try:
        with sync_playwright() as pw:
            pw.chromium.launch(headless=True).close()
    except Exception:
        click.echo("Cai dat Playwright browsers (chi can 1 lan)...")
        subprocess.run(
            [sys.executable, "-m", "playwright", "install", "chromium"],
            check=True,
        )


@click.group()
def main() -> None:
    """Sora Video Tool — Tu dong tao video Sora theo batch."""
    _ensure_playwright_browsers()


# ===========================================================================
# sora setup
# ===========================================================================

@main.command("setup")
@click.option("--retry", is_flag=True, help="Mo lai profile cu de dang nhap lai.")
def cmd_setup(retry: bool) -> None:
    """Cau hinh profiles, nhap thong tin, mo Chrome de dang nhap."""
    if retry:
        _setup_retry()
    else:
        _setup_full()


def _setup_full() -> None:
    click.echo(f"\n{_BOLD}")
    click.echo("  SORA VIDEO TOOL — THIET LAP")
    click.echo(_BOLD)

    settings = load_settings()

    # ── Profiles ──────────────────────────────────────────────────────────
    click.echo("\n[1/6] Cau hinh profiles")
    num = click.prompt(
        "  So luong profile",
        type=int,
        default=settings.get("num_profiles", 1),
    )

    profiles: list[dict] = []
    for i in range(1, num + 1):
        alias = click.prompt(
            f"  Ten alias cho profile {i} (Enter = mac dinh)",
            default=f"Tai khoan {i}",
        )
        profiles.append({"id": f"profile_{i}", "alias": alias})

    # ── Credentials ───────────────────────────────────────────────────────
    click.echo("\n[2/6] Thong tin tai khoan")
    username = click.prompt("  Username dsora", default=settings.get("username", ""))
    backend_key = click.prompt(
        "  Backend key", hide_input=True, default=settings.get("backend_key", "")
    )

    # ── Telegram (optional) ───────────────────────────────────────────────
    click.echo("\n[3/6] Telegram (tuy chon — nhan Enter de bo qua)")
    tele_token = click.prompt(
        "  Bot Token", default=settings.get("telegram_token", ""), show_default=False
    )
    tele_channel = click.prompt(
        "  Channel ID", default=settings.get("telegram_channel", ""), show_default=False
    )

    # ── Save ──────────────────────────────────────────────────────────────
    settings.update({
        "num_profiles": num,
        "profiles": profiles,
        "username": username,
        "backend_key": backend_key,
        "telegram_token": tele_token,
        "telegram_channel": tele_channel,
    })
    save_settings(settings)

    for p in profiles:
        ensure_profile_exists(p["id"])

    click.echo(f"\n{_LINE}")
    click.echo("  Cau hinh da luu.")
    click.echo(_LINE)
    click.echo("\nHuong dan sau khi Chrome mo:")
    click.echo("  1. Dang nhap Google trong moi cua so")
    click.echo("  2. Vao sora.com va dang nhap")
    click.echo("  3. Vao Settings: dat thoi gian 15s, chon 3 video")
    click.echo("  4. Dong tat ca cua so Chrome khi xong")
    click.echo(_LINE)

    if click.confirm("\nMo Chrome de dang nhap ngay bay gio?", default=True):
        _open_browsers_for_login(profiles)


def _setup_retry() -> None:
    settings = load_settings()
    profiles = settings.get("profiles", [])

    if not profiles:
        click.echo("Chua co profile nao. Chay `sora setup` truoc.", err=True)
        sys.exit(1)

    click.echo(f"\n{_LINE}")
    click.echo("  CHON PROFILE DE DANG NHAP LAI")
    click.echo(_LINE)
    for i, p in enumerate(profiles, 1):
        click.echo(f"  {i}. {p['alias']}  ({p['id']})")
    click.echo(_LINE)

    raw = click.prompt(
        "Nhap so thu tu (cach nhau bang dau phay, Enter = tat ca)",
        default="all",
    )

    if raw.strip().lower() == "all":
        selected = profiles
    else:
        nums = [x.strip() for x in raw.split(",") if x.strip().isdigit()]
        selected = [profiles[int(n) - 1] for n in nums if 0 < int(n) <= len(profiles)]

    if not selected:
        click.echo("Khong co profile nao duoc chon.")
        return

    _open_browsers_for_login(selected)


def _open_browsers_for_login(profiles: list[dict]) -> None:
    for p in profiles:
        path = ensure_profile_exists(p["id"])
        click.echo(f"  Mo Chrome: {p['alias']} ...")
        launch_chrome_for_login(path, url=SORA_URL)
        time.sleep(0.8)

    click.echo(f"\nDa mo {len(profiles)} cua so Chrome.")
    click.echo("Dang nhap xong thi dong cac cua so la xong.")


# ===========================================================================
# sora run
# ===========================================================================

@main.command("run")
def cmd_run() -> None:
    """Chay tu dong tao video cho tat ca profiles."""
    settings = load_settings()

    try:
        validate_settings(settings)
    except ValueError as e:
        click.echo(f"Loi cau hinh: {e}", err=True)
        sys.exit(1)

    profiles = settings["profiles"]

    click.echo(f"\n{_BOLD}")
    click.echo("  SORA VIDEO TOOL — BAT DAU CHAY")
    click.echo(_BOLD)
    click.echo(f"  Username  : {settings['username']}")
    click.echo(f"  Profiles  : {len(profiles)}")
    click.echo(f"  Max SP    : {len(profiles) * PRODUCTS_PER_PROFILE}")
    click.echo(_BOLD)

    # ── Fetch products ────────────────────────────────────────────────────
    click.echo("\nDang lay danh sach san pham tu API ...")
    try:
        products = get_pending_products(settings["username"])
    except RuntimeError as e:
        click.echo(f"Loi: {e}", err=True)
        sys.exit(1)

    if not products:
        click.echo("Khong co san pham nao can xu ly. Ket thuc.")
        return

    click.echo(f"San pham can xu ly: {len(products)}")

    # ── Warn & trim ───────────────────────────────────────────────────────
    needed = ceil(len(products) / PRODUCTS_PER_PROFILE)
    if needed < len(profiles):
        click.echo(
            f"\n[CANH BAO] Chi can {needed}/{len(profiles)} profile "
            f"cho {len(products)} san pham."
        )
        profiles = profiles[:needed]
    elif needed > len(profiles):
        max_sp = len(profiles) * PRODUCTS_PER_PROFILE
        click.echo(
            f"\n[CANH BAO] Chi xu ly duoc {max_sp}/{len(products)} san pham "
            f"(gioi han {len(profiles)} profiles)."
        )
        products = products[:max_sp]

    # ── Batch by profile ──────────────────────────────────────────────────
    batches = [
        products[i: i + PRODUCTS_PER_PROFILE]
        for i in range(0, len(products), PRODUCTS_PER_PROFILE)
    ]

    total_done = 0
    total_failed = 0

    for idx, (profile, batch) in enumerate(zip(profiles, batches)):
        profile_id = profile["id"]
        alias = profile.get("alias", profile_id)
        debug_port = CDP_PORT_BASE + idx

        click.echo(f"\n{_LINE}")
        click.echo(f"  Profile {idx + 1}/{len(profiles)}: {alias}")
        click.echo(f"  San pham: {len(batch)}")
        click.echo(_LINE)

        profile_path = ensure_profile_exists(profile_id)
        proc = pw = None
        p_done = 0
        p_failed = 0

        try:
            proc, pw, browser, context, page = launch_chrome_for_automation(
                profile_path, debug_port
            )

            for prod_idx, product in enumerate(batch):
                pname = product["product_name"]
                pid = product["id"]
                _img = product.get("product_image") or product.get("image_url")
                image_src = f"{API_BASE_URL.rstrip('/')}/{_img.lstrip('/')}" if _img else None
                click.echo(f"  Anh: {image_src or '(dung anh mac dinh)'}")

                click.echo(f"\n  [{prod_idx + 1}/{len(batch)}] {pname}")

                try:
                    create_video(page, product["prompt_content"], image_src)
                    mark_product_done(pid, settings["backend_key"])

                    p_done += 1
                    total_done += 1
                    record_product_done(profile_id, pid)

                    click.echo(f"  OK  {pname}")
                    notify_product_done(settings, alias, pname)

                except Exception as e:
                    p_failed += 1
                    total_failed += 1
                    record_product_failed(profile_id)

                    click.echo(f"  LOI  {pname}: {e}")
                    notify_product_failed(settings, alias, pname, str(e))

                # Cho gen xong roi F5 truoc san pham tiep theo
                if prod_idx < len(batch) - 1:
                    mins = WAIT_BETWEEN_PRODUCTS_SEC // 60
                    click.echo(f"\n  Cho {mins} phut de gen video ...")
                    time.sleep(WAIT_BETWEEN_PRODUCTS_SEC)
                    click.echo("  F5 trang cho san pham tiep theo ...")
                    reset_page(page)

        except Exception as e:
            click.echo(f"\n  LOI NGHIEM TRONG ({alias}): {e}")
            remaining = len(batch) - p_done - p_failed  # type: ignore[possibly-undefined]
            total_failed += remaining

        finally:
            if pw:
                try:
                    pw.stop()
                except Exception:
                    pass
            if proc:
                close_chrome(proc)
                click.echo(f"\n  Da dong Chrome: {alias}")

        click.echo(f"\n  {alias}: OK {p_done} | LOI {p_failed}")  # type: ignore[possibly-undefined]
        notify_profile_done(settings, alias, p_done, p_failed)  # type: ignore[possibly-undefined]

    # ── Summary ───────────────────────────────────────────────────────────
    click.echo(f"\n{_BOLD}")
    click.echo("  HOAN TAT")
    click.echo(_BOLD)
    click.echo(f"  Thanh cong : {total_done}")
    click.echo(f"  Loi        : {total_failed}")
    click.echo(f"  Tong       : {total_done + total_failed}")
    click.echo(_BOLD)

    notify_all_done(settings, total_done, total_failed)


# ===========================================================================
# sora help
# ===========================================================================

@main.command("open")
@click.argument("alias")
def cmd_open(alias: str) -> None:
    """Mo Chrome cho mot profile theo alias. Vi du: dsg open datly030102"""
    settings = load_settings()
    profiles = settings.get("profiles", [])

    match = next(
        (p for p in profiles if p.get("alias", "").lower() == alias.lower()),
        None,
    )

    if match is None:
        available = ", ".join(p.get("alias", p["id"]) for p in profiles) or "(chua co profile nao)"
        click.echo(f"Khong tim thay profile '{alias}'.")
        click.echo(f"Cac profile hien co: {available}")
        sys.exit(1)

    profile_path = ensure_profile_exists(match["id"])
    click.echo(f"Mo Chrome: {match['alias']} ({match['id']}) ...")
    proc = launch_chrome_for_login(profile_path, url=SORA_URL)
    click.echo("Dong cua so Chrome khi xong.")
    proc.wait()


# ===========================================================================
# dsg help
# ===========================================================================

@main.command("help")
@click.pass_context
def cmd_help(ctx: click.Context) -> None:
    """Hien thi danh sach lenh."""
    click.echo(ctx.parent.get_help())  # type: ignore[union-attr]
