"""Command-line interface for video-thumbnail-creator."""

import json
import os
import sys
import tempfile

from .config import get_effective_config, get_value, list_config, set_value
from .embedded_image import detect_embedded_image, extract_embedded_image
from .sidecar_image import detect_sidecar_image
from .extractor import extract_frames
from .mosaic import create_mosaic
from .poster_template import get_style, list_styles
from .image_converter import is_image_file, prepare_image_source
from .utils import check_dependencies, get_video_properties
from .badges import detect_badges
from .cli_parser import _build_parser
from .cli_helpers import (
    EXIT_SUCCESS, EXIT_ERROR, EXIT_NO_SELECTION, EXIT_AI_FAILED,
    _resolve_output_path, _emit_result, _resolve_overlay_title, _resolve_category,
    _apply_postprocess, _generate_fanart_if_requested, _finalize_frame,
)
from .cli_modes import _run_manual, _run_auto, _run_suggest
from .cli_image_handlers import _run_with_embedded, _run_with_sidecar, _run_with_image


def _handle_styles_command() -> None:
    """Print all registered poster styles with their descriptions."""
    print("Available styles:\n")
    for s in list_styles():
        print(f"  {s['name']:<12} {s['description']}")


def _handle_config_command(args) -> None:
    """Dispatch config sub-commands."""
    if args.config_command == "set":
        try:
            set_value(args.key, args.value)
            print(f"Config '{args.key}' set to '{args.value}'.")
        except ValueError as exc:
            print(f"Error: {exc}", file=sys.stderr)
            sys.exit(EXIT_ERROR)
    elif args.config_command == "get":
        try:
            value = get_value(args.key)
        except ValueError as exc:
            print(f"Error: {exc}", file=sys.stderr)
            sys.exit(EXIT_ERROR)
        if value is None:
            print(f"Config key '{args.key}' is not set.", file=sys.stderr)
            sys.exit(EXIT_ERROR)
        print(value)
    elif args.config_command == "list":
        config = list_config()
        if not config:
            print("No configuration values set.")
        else:
            for section, values in sorted(config.items()):
                print(f"[{section}]")
                for key, val in sorted(values.items()):
                    print(f"  {key} = {val}")
    else:
        print("Usage: video-thumbnail-creator config <set|get|list>", file=sys.stderr)
        sys.exit(EXIT_ERROR)


def _handle_info_command(args) -> None:
    """Display embedded metadata from a poster image."""
    from .metadata import read_metadata

    if not os.path.isfile(args.image_path):
        print(f"Error: File not found: '{args.image_path}'", file=sys.stderr)
        sys.exit(EXIT_ERROR)

    metadata = read_metadata(args.image_path)
    if metadata is None:
        print("No video-thumbnail-creator metadata found in this image.", file=sys.stderr)
        sys.exit(EXIT_ERROR)

    if args.json:
        print(json.dumps(metadata, ensure_ascii=False, indent=2))
    else:
        print("Poster Metadata:")
        field_labels = {
            "vtc_version": "Version",
            "source": "Source",
            "frame_index": "Frame Index",
            "crop_position": "Crop Position",
            "format": "Format",
            "mode": "Mode",
            "input_file": "Input File",
            "overlay_title": "Overlay Title",
            "overlay_category": "Category",
            "overlay_category_logo": "Category Logo",
            "overlay_note": "Note",
            "ai_reasoning": "AI Reasoning",
            "poster_template": "Template",
            "created_at": "Created",
        }
        for key, label in field_labels.items():
            if key in metadata:
                value = metadata[key]
                # Truncate long AI reasoning for display
                if key == "ai_reasoning" and len(str(value)) > 100:
                    value = str(value)[:100] + "…"
                print(f"  {label:18s} {value}")


def main() -> None:
    parser = _build_parser()
    args = parser.parse_args()

    if args.command is None:
        parser.print_help()
        sys.exit(EXIT_ERROR)

    if args.command == "styles":
        _handle_styles_command()
        sys.exit(EXIT_SUCCESS)

    if args.command == "config":
        _handle_config_command(args)
        sys.exit(EXIT_SUCCESS)

    if args.command == "info":
        _handle_info_command(args)
        sys.exit(EXIT_SUCCESS)

    # ── extract command ───────────────────────────────────────────────────────

    # Validate input file
    if not os.path.isfile(args.input_path):
        print(f"Error: Input file not found: '{args.input_path}'", file=sys.stderr)
        sys.exit(EXIT_ERROR)

    # Detect input type
    input_is_image = is_image_file(args.input_path)

    # Resolve effective values: CLI args > config file > built-in defaults
    effective = get_effective_config()

    mode = args.mode or effective["defaults"]["mode"]
    output_name_suffix = args.output_name_suffix or effective["defaults"]["output_name_suffix"]
    fmt = args.format or effective["defaults"]["format"]
    claude_api_key = (
        os.environ.get("CLAUDE_API_KEY", "")
        or effective.get("claude", {}).get("api_key", "")
    )
    claude_model = effective["claude"]["model"]
    ffmpeg_bin = effective["tools"]["ffmpeg"]
    ffprobe_bin = effective["tools"]["ffprobe"]

    # Store resolved values back into args for downstream helpers
    args.mode = mode
    args.output_name_suffix = output_name_suffix
    args.format = fmt
    args.claude_api_key = claude_api_key
    args.claude_model = claude_model
    args.ffmpeg_bin = ffmpeg_bin
    args.ffprobe_bin = ffprobe_bin

    if not input_is_image:
        check_dependencies(ffmpeg=ffmpeg_bin, ffprobe=ffprobe_bin)

    # Load poster design template from named style
    try:
        args.template = get_style(args.style)
    except ValueError as exc:
        print(f"Error: {exc}", file=sys.stderr)
        sys.exit(EXIT_ERROR)

    embedded_image_mode = args.embedded_image or effective["defaults"]["embedded_image"]
    args.embedded_image = embedded_image_mode

    with tempfile.TemporaryDirectory(prefix="vtc_") as tmpdir:
        if input_is_image:
            # ── Image input flow ──────────────────────────────────────────────
            args.detected_badges = []  # No badge detection for image input
            prepared_path = os.path.join(tmpdir, "prepared_source.jpg")
            try:
                source_image = prepare_image_source(args.input_path, prepared_path)
            except Exception as exc:
                print(f"   Error preparing image: {exc}", file=sys.stderr)
                sys.exit(EXIT_ERROR)
            exit_code = _run_with_image(args, source_image, tmpdir)
        else:
            # ── Video input flow ──────────────────────────────────────────────
            # Detect video properties and badges (unless --no-badges)
            badges_enabled = (
                not getattr(args, "no_badges", False)
                and args.template.get("badges", {}).get("enabled", True)
            )
            fanart_requested = getattr(args, "fanart", False)
            if badges_enabled or fanart_requested:
                video_props = get_video_properties(args.input_path, ffprobe=ffprobe_bin)
                args.video_properties = video_props
                if badges_enabled:
                    args.detected_badges = detect_badges(video_props)
                    if args.detected_badges:
                        print(
                            f"   🏷️  Erkannte Badges: {', '.join(b.upper() for b in args.detected_badges)}",
                            file=sys.stderr,
                        )
                else:
                    args.detected_badges = []
            else:
                args.detected_badges = []

            # ── Embedded image handling ───────────────────────────────────────
            source_image_video: str | None = None

            if embedded_image_mode != "ignore":
                print("   📎 Prüfe auf eingebettetes Titelbild…", file=sys.stderr)
                has_embedded = detect_embedded_image(args.input_path, ffprobe=ffprobe_bin)

                if has_embedded:
                    print("   📎 Eingebettetes Titelbild gefunden!", file=sys.stderr)
                    use_embedded = False

                    if embedded_image_mode == "prefer":
                        use_embedded = True
                    elif embedded_image_mode == "ask":
                        # In non-interactive (auto) mode treat ask like prefer
                        if args.mode == "auto":
                            use_embedded = True
                        else:
                            try:
                                answer = input(
                                    "   Eingebettetes Titelbild gefunden. Verwenden? [J/n]: "
                                ).strip().lower()
                            except (EOFError, KeyboardInterrupt):
                                answer = "j"
                            use_embedded = answer in ("", "j", "y", "ja", "yes")

                    if use_embedded:
                        print("   📎 Eingebettetes Titelbild wird verwendet.", file=sys.stderr)
                        embedded_path = os.path.join(tmpdir, "embedded.jpg")
                        try:
                            source_image_video = extract_embedded_image(
                                args.input_path, embedded_path,
                                ffmpeg=ffmpeg_bin, ffprobe=ffprobe_bin,
                            )
                        except Exception as exc:
                            print(f"   Error extracting embedded image: {exc}", file=sys.stderr)
                            sys.exit(EXIT_ERROR)
                    else:
                        print("   📎 Eingebettetes Titelbild wird ignoriert.", file=sys.stderr)
                else:
                    print(
                        "   📎 Kein eingebettetes Titelbild gefunden. "
                        "Fahre mit Frame-Extraktion fort.",
                        file=sys.stderr,
                    )

            if source_image_video is not None:
                # Use the embedded image as the high-res source; skip mosaic
                exit_code = _run_with_embedded(args, source_image_video, tmpdir)
            else:
                # ── Sidecar image handling ────────────────────────────────────
                if embedded_image_mode != "ignore":
                    sidecar_path = detect_sidecar_image(args.input_path)
                    if sidecar_path:
                        print(
                            f"   📁 Sidecar-Titelbild gefunden: {os.path.basename(sidecar_path)}",
                            file=sys.stderr,
                        )
                        use_sidecar = False

                        if embedded_image_mode == "prefer":
                            use_sidecar = True
                        elif embedded_image_mode == "ask":
                            if args.mode == "auto":
                                use_sidecar = True
                            else:
                                try:
                                    answer = input(
                                        f"   Sidecar-Titelbild gefunden ({os.path.basename(sidecar_path)}). "
                                        "Verwenden? [J/n]: "
                                    ).strip().lower()
                                except (EOFError, KeyboardInterrupt):
                                    answer = "j"
                                use_sidecar = answer in ("", "j", "y", "ja", "yes")

                        if use_sidecar:
                            print("   📁 Sidecar-Titelbild wird verwendet.", file=sys.stderr)
                            prepared_path = os.path.join(tmpdir, "sidecar_prepared.jpg")
                            try:
                                source_image_video = prepare_image_source(sidecar_path, prepared_path)
                            except Exception as exc:
                                print(f"   Error preparing sidecar image: {exc}", file=sys.stderr)
                                sys.exit(EXIT_ERROR)
                        else:
                            print("   📁 Sidecar-Titelbild wird ignoriert.", file=sys.stderr)

                if source_image_video is not None:
                    # Use the sidecar image as the high-res source; skip mosaic
                    exit_code = _run_with_sidecar(args, source_image_video, tmpdir)
                else:
                    # ── Normal mosaic flow ────────────────────────────────────
                    print("   📽️  Extrahiere Frames…", file=sys.stderr)

                    frames_dir = os.path.join(tmpdir, "frames")
                    os.makedirs(frames_dir)

                    try:
                        frame_paths = extract_frames(
                            args.input_path, frames_dir, ffmpeg=ffmpeg_bin, ffprobe=ffprobe_bin
                        )
                    except Exception as exc:
                        print(f"Error during frame extraction: {exc}", file=sys.stderr)
                        sys.exit(EXIT_ERROR)

                    mosaic_path = os.path.join(tmpdir, "mosaic.jpg")
                    try:
                        create_mosaic(frame_paths, mosaic_path)
                    except Exception as exc:
                        print(f"Error creating mosaic: {exc}", file=sys.stderr)
                        sys.exit(EXIT_ERROR)

                    if args.mode == "manual":
                        exit_code = _run_manual(args, frame_paths, mosaic_path, tmpdir)
                    elif args.mode == "auto":
                        exit_code = _run_auto(args, frame_paths, mosaic_path, tmpdir)
                    else:  # suggest
                        exit_code = _run_suggest(args, frame_paths, mosaic_path, tmpdir)

    sys.exit(exit_code)


if __name__ == "__main__":
    main()
