#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
offline_bg.cli — 命令行入口。

    # 加工：从视频取摄像头帧做画像，把一批背景加工入库
    python -m offline_bg.cli build --frames assets/talking.mp4 \
        --bg assets/gen/bg_match_left.png --user u1 --root bg_library

    # 查看某用户的背景库
    python -m offline_bg.cli list --user u1 --root bg_library

    # 按当前摄像头光照挑一张
    python -m offline_bg.cli pick --frames assets/talking.mp4 --user u1 --root bg_library
"""
import argparse
import glob
import json
import os
import sys

import cv2

from .config import OfflineBGConfig
from .library import BackgroundLibrary
from .lighting import frames_from_video, profile_camera
from .pipeline import BackgroundPreprocessor


def _frames(args):
    if os.path.isdir(args.frames):
        fs = sorted(glob.glob(os.path.join(args.frames, "*")))
        ims = [cv2.imread(f) for f in fs[:args.n_frames]]
        ims = [i for i in ims if i is not None]
        if not ims:
            sys.exit(f"目录里没有可读图片: {args.frames}")
        return ims
    return frames_from_video(args.frames, args.n_frames)


def _cfg(args) -> OfflineBGConfig:
    c = OfflineBGConfig()
    if getattr(args, "root", None):
        c.library_root = args.root
    if getattr(args, "front_strategy", None):
        c.front_strategy = args.front_strategy
    if getattr(args, "target_size", None):
        w, h = args.target_size.lower().split("x")
        c.target_size = (int(w), int(h))
    if getattr(args, "max_attempts", None):
        c.max_attempts = args.max_attempts
    return c


def cmd_build(args):
    cfg = _cfg(args)
    frames = _frames(args)
    profile = profile_camera(frames, cfg=cfg)
    print("① 摄像头画像:", json.dumps(profile.to_dict(), ensure_ascii=False), flush=True)

    paths = []
    for pat in args.bg:
        paths += sorted(glob.glob(pat)) if any(ch in pat for ch in "*?[") else \
            ([os.path.join(pat, f) for f in sorted(os.listdir(pat))] if os.path.isdir(pat) else [pat])
    bgs, names = [], []
    for p in paths:
        im = cv2.imread(p)
        if im is None:
            print(f"⚠️ 读不出，跳过: {p}")
            continue
        bgs.append(im); names.append(os.path.splitext(os.path.basename(p))[0])
    if not bgs:
        sys.exit("没有可用背景图")

    prep = BackgroundPreprocessor(cfg)
    recs = prep.process_batch(bgs, profile, user_id=args.user, names=names,
                              relight=not args.no_relight)
    if args.json:
        with open(args.json, "w", encoding="utf-8") as f:
            json.dump({"profile": profile.to_dict(), "records": recs}, f,
                      ensure_ascii=False, indent=2)
        print("记录已写:", args.json)
    ok = sum(1 for r in recs if r.get("validated"))
    print(f"完成 {len(recs)} 张，方向校验通过 {ok} 张")


def cmd_list(args):
    lib = BackgroundLibrary(args.root)
    for i in lib.list(args.user, cls=args.cls):
        print(f"{i['bg_id']}  {i['cls']:<6} validated={str(i['validated']):<5} "
              f"Δ={i.get('signed_delta')}  {i['name']}  → {i['final']}")


def cmd_pick(args):
    cfg = _cfg(args)
    profile = profile_camera(_frames(args), cfg=cfg)
    e = BackgroundLibrary(args.root).pick(args.user, profile)
    print("当前光照:", json.dumps(profile.to_dict(), ensure_ascii=False))
    print("选中:", json.dumps(e, ensure_ascii=False) if e else "（库里没有背景）")


def main(argv=None):
    ap = argparse.ArgumentParser("offline_bg")
    sub = ap.add_subparsers(dest="cmd", required=True)

    def common(p):
        p.add_argument("--user", default="default")
        p.add_argument("--root", default="bg_library")
        p.add_argument("--frames", required=True, help="摄像头帧来源：视频文件或图片目录（须连续帧）")
        p.add_argument("--n-frames", type=int, default=9)
        p.add_argument("--front-strategy", choices=["skip", "radial"])

    b = sub.add_parser("build", help="加工背景入库")
    common(b)
    b.add_argument("--bg", nargs="+", required=True, help="背景图路径 / 目录 / 通配符")
    b.add_argument("--no-relight", action="store_true", help="只做画质匹配，不跑 IC-Light")
    b.add_argument("--target-size", help="成片尺寸 WxH，默认跟随摄像头帧")
    b.add_argument("--max-attempts", type=int)
    b.add_argument("--json", help="把完整记录写到这个文件")
    b.set_defaults(func=cmd_build)

    l = sub.add_parser("list", help="列出背景库")
    l.add_argument("--user", default="default")
    l.add_argument("--root", default="bg_library")
    l.add_argument("--cls", choices=["left", "right", "top", "bottom", "front"])
    l.set_defaults(func=cmd_list)

    p = sub.add_parser("pick", help="按当前摄像头光照挑背景")
    common(p)
    p.set_defaults(func=cmd_pick)

    a = ap.parse_args(argv)
    a.func(a)


if __name__ == "__main__":
    main()
