"""
clawID command-line interface.

Commands:
  clawid embed   -i input.jpg  -o output.png  --uid user123  --platform hawky.ai
  clawid detect  -i output.png
  clawid serve   --store sqlite:///clawid.db  --port 8000
"""

import argparse
import json
import sys

from .core.embed import embed
from .core.detect import detect
from .video import embed_video, detect_video


def cmd_embed(args: argparse.Namespace) -> None:
    metadata = {}
    if args.uid:
        metadata["uid"] = args.uid
    if args.platform:
        metadata["platform"] = args.platform
    if args.asset_id:
        metadata["asset_id"] = args.asset_id
    if args.meta:
        try:
            metadata.update(json.loads(args.meta))
        except json.JSONDecodeError as exc:
            print(f"Error: --meta must be valid JSON — {exc}", file=sys.stderr)
            sys.exit(1)

    if not metadata:
        print(
            "Error: provide at least one of --uid, --platform, --asset-id, or --meta",
            file=sys.stderr,
        )
        sys.exit(1)

    try:
        final_meta = embed(
            source=args.input,
            output_path=args.output,
            metadata=metadata,
            mode=args.mode,
            algorithm=args.algorithm,
            opacity=args.opacity,
            font_size=args.font_size,
            position=args.position,
        )
    except Exception as exc:
        print(f"Error: {exc}", file=sys.stderr)
        sys.exit(1)

    print(f"Watermark embedded → {args.output}")
    print(f"clawid: {final_meta.get('clawid')}")

    # Optionally persist to store
    if args.store:
        try:
            from .storage import from_uri
            with from_uri(args.store) as store:
                store.save(final_meta["clawid"], final_meta)
            print(f"Saved to store: {args.store}")
        except Exception as exc:
            print(f"Warning: could not save to store — {exc}", file=sys.stderr)


def cmd_embed_video(args: argparse.Namespace) -> None:
    metadata = {}
    if args.uid:
        metadata["uid"] = args.uid
    if args.platform:
        metadata["platform"] = args.platform
    if args.asset_id:
        metadata["asset_id"] = args.asset_id
    if args.meta:
        try:
            metadata.update(json.loads(args.meta))
        except json.JSONDecodeError as exc:
            print(f"Error: --meta must be valid JSON — {exc}", file=sys.stderr)
            sys.exit(1)

    if not metadata:
        print(
            "Error: provide at least one of --uid, --platform, --asset-id, or --meta",
            file=sys.stderr,
        )
        sys.exit(1)

    try:
        final_meta = embed_video(
            source=args.input,
            output_path=args.output,
            metadata=metadata,
            frame_stride=args.frame_stride,
        )
    except Exception as exc:
        print(f"Error: {exc}", file=sys.stderr)
        sys.exit(1)

    print(f"Video watermarked → {args.output}")
    print(f"clawid: {final_meta.get('clawid')}")


def cmd_detect_video(args: argparse.Namespace) -> None:
    result = detect_video(args.input, algorithm=args.algorithm)
    if result is None:
        print("No clawID watermark detected in video.")
        sys.exit(1)

    print("clawID watermark detected:")
    print(json.dumps(result, indent=2))


def cmd_detect(args: argparse.Namespace) -> None:
    result = detect(args.input, algorithm=args.algorithm)
    if result is None:
        print("No clawID watermark detected.")
        sys.exit(1)

    print("clawID watermark detected:")
    print(json.dumps(result, indent=2))

    # Optionally enrich from store
    if args.store and result.get("clawid"):
        try:
            from .storage import from_uri
            with from_uri(args.store) as store:
                db_meta = store.get(result["clawid"])
            if db_meta:
                merged = {**result, **db_meta}
                print("\nEnriched from store:")
                print(json.dumps(merged, indent=2))
        except Exception as exc:
            print(f"Warning: could not query store — {exc}", file=sys.stderr)


def cmd_serve(args: argparse.Namespace) -> None:
    try:
        import uvicorn
    except ImportError:
        print(
            "Error: uvicorn is required to run the server.\n"
            "Install it with:  pip install 'clawid[api]'",
            file=sys.stderr,
        )
        sys.exit(1)

    store = None
    if args.store:
        try:
            from .storage import from_uri
            store = from_uri(args.store)
            print(f"Store: {type(store).__name__} ({args.store})")
        except Exception as exc:
            print(f"Error: could not connect to store — {exc}", file=sys.stderr)
            sys.exit(1)

    from .api import create_app
    app = create_app(store=store)

    print(f"clawID API starting on http://{args.host}:{args.port}")
    print(f"Docs: http://{args.host}:{args.port}/docs")

    uvicorn.run(app, host=args.host, port=args.port, workers=args.workers)


def main() -> None:
    parser = argparse.ArgumentParser(
        prog="clawid",
        description="clawID — invisible & visible watermarking for AI-generated assets",
    )
    sub = parser.add_subparsers(dest="command", required=True)

    # ── embed ─────────────────────────────────────────────────────────────────
    ep = sub.add_parser("embed", help="Embed a watermark into an image")
    ep.add_argument("-i", "--input",   required=True, help="Input image path")
    ep.add_argument("-o", "--output",  required=True, help="Output image path")
    ep.add_argument("--uid",           help="Creator / user ID")
    ep.add_argument("--platform",      help="Platform name (e.g. hawky.ai)")
    ep.add_argument("--asset-id",      dest="asset_id", help="Asset / generation ID")
    ep.add_argument("--meta",          help="Extra metadata as a JSON string")
    ep.add_argument(
        "--mode",
        choices=["invisible", "visible", "both"],
        default="invisible",
    )
    ep.add_argument(
        "--algorithm",
        choices=["qim", "fm"],
        default="qim",
        help="qim=fast (PNG/JPEG), fm=resize-robust (survives ±35%% resize)",
    )
    ep.add_argument("--opacity",   type=float, default=0.6)
    ep.add_argument("--font-size", dest="font_size", type=int, default=20)
    ep.add_argument(
        "--position",
        choices=["top-left", "top-right", "bottom-left", "bottom-right", "center"],
        default="bottom-right",
    )
    ep.add_argument("--store", help="Store URI, e.g. sqlite:///clawid.db")

    # ── detect ────────────────────────────────────────────────────────────────
    dp = sub.add_parser("detect", help="Detect and extract a watermark from an image")
    dp.add_argument("-i", "--input", required=True, help="Image path to analyse")
    dp.add_argument("--store", help="Store URI to enrich result from DB")
    dp.add_argument(
        "--algorithm",
        choices=["auto", "qim", "fm"],
        default="auto",
        help="Detection algorithm (default: auto-tries both)",
    )

    # ── embed-video ───────────────────────────────────────────────────────────
    evp = sub.add_parser("embed-video", help="Embed a watermark into a video")
    evp.add_argument("-i", "--input",  required=True, help="Input video path")
    evp.add_argument("-o", "--output", required=True, help="Output video path")
    evp.add_argument("--uid",          help="Creator / user ID")
    evp.add_argument("--platform",     help="Platform name")
    evp.add_argument("--asset-id",     dest="asset_id", help="Asset ID")
    evp.add_argument("--meta",         help="Extra metadata as JSON")
    evp.add_argument(
        "--frame-stride",
        dest="frame_stride",
        type=int,
        default=5,
        help="Watermark every Nth frame (default 5)",
    )

    # ── detect-video ──────────────────────────────────────────────────────────
    dvp = sub.add_parser("detect-video", help="Detect a watermark in a video")
    dvp.add_argument("-i", "--input", required=True, help="Video path to analyse")
    dvp.add_argument(
        "--algorithm",
        choices=["auto", "qim", "fm"],
        default="auto",
    )

    # ── serve ─────────────────────────────────────────────────────────────────
    sp = sub.add_parser("serve", help="Start the clawID REST API server")
    sp.add_argument("--host",    default="0.0.0.0")
    sp.add_argument("--port",    type=int, default=8000)
    sp.add_argument("--workers", type=int, default=1)
    sp.add_argument("--store",   help="Store URI, e.g. postgresql://user:pass@host/db")

    args = parser.parse_args()
    {
        "embed":        cmd_embed,
        "detect":       cmd_detect,
        "embed-video":  cmd_embed_video,
        "detect-video": cmd_detect_video,
        "serve":        cmd_serve,
    }[args.command](args)


if __name__ == "__main__":
    main()
