import os
import shutil
import subprocess
from importlib import metadata as importlib_metadata
from importlib import util as importlib_util
from video_thumbnail_creator import ThumbnailSession
import video_thumbnail_creator
from video_thumbnail_creator.poster_template import get_style
from .config import CONFIG

_FRAME_SELECTION_HINT = (
    "IMPORTANT: Prefer frames WITHOUT text overlays, advertising slogans, watermarks, "
    "or branding displayed at the bottom or edges of the image. If clean frames are "
    "available, choose those instead. Only select a frame with such text or branding "
    "if it is the central subject of the video (e.g., a documentary where the company "
    "logo itself is the main focus)."
)


def _build_suggest_frame_description(description: str) -> str:
    """Prepend an image-selection hint to the video description for the AI."""
    if description:
        return f"{_FRAME_SELECTION_HINT}\n\n{description}"
    return _FRAME_SELECTION_HINT


_GERMAN_MONTHS = [
    "Januar", "Februar", "März", "April", "Mai", "Juni",
    "Juli", "August", "September", "Oktober", "November", "Dezember",
]

_POSTER_STYLE_NAME = "internet"


def _get_thumbnail_creator_runtime_info():
    """Return version and import-path details for the loaded thumbnail library."""
    runtime_info = {
        "distribution": "video-thumbnail-creator",
        "version": None,
        "module_path": None,
        "distribution_root": None,
    }

    try:
        runtime_info["version"] = importlib_metadata.version(runtime_info["distribution"])
    except importlib_metadata.PackageNotFoundError:
        pass
    except Exception:
        pass

    module_path = getattr(video_thumbnail_creator, "__file__", None)
    if module_path:
        runtime_info["module_path"] = os.path.abspath(module_path)
    else:
        try:
            spec = importlib_util.find_spec("video_thumbnail_creator")
            if spec and spec.origin:
                runtime_info["module_path"] = os.path.abspath(spec.origin)
        except Exception:
            pass

    try:
        distribution = importlib_metadata.distribution(runtime_info["distribution"])
        distribution_root = distribution.locate_file("")
        if distribution_root:
            runtime_info["distribution_root"] = os.path.abspath(str(distribution_root))
    except importlib_metadata.PackageNotFoundError:
        pass
    except Exception:
        pass

    return runtime_info


def _print_thumbnail_creator_runtime_info():
    """Print the exact runtime source of video-thumbnail-creator for diagnostics."""
    runtime_info = _get_thumbnail_creator_runtime_info()
    version_text = runtime_info["version"] or "unbekannt"
    module_text = runtime_info["module_path"] or "unbekannt"

    print(f"   🔎 video-thumbnail-creator Runtime: v{version_text}")
    print(f"   🎨 Poster-Stil: {_POSTER_STYLE_NAME} (explizit gesetzt)")
    print(f"   📦 Modulpfad: {module_text}")

    if runtime_info["distribution_root"]:
        print(f"   📁 Distribution-Root: {runtime_info['distribution_root']}")


def _format_upload_date(raw_date):
    """Format upload date from YYYYMMDD to German long format.

    Args:
        raw_date: Date string in YYYYMMDD format (e.g., "20221208")

    Returns:
        Formatted date string in German (e.g., "8. Dezember 2022") or empty string
    """
    if not raw_date or len(raw_date) < 8:
        return ""
    try:
        year = raw_date[:4]
        month = int(raw_date[4:6])
        day = int(raw_date[6:8])
        if not (1 <= month <= 12):
            return ""
        return f"{day}. {_GERMAN_MONTHS[month - 1]} {year}"
    except (IndexError, TypeError, ValueError):
        return ""


def handle_poster_selection(job_dir, meta, auto_mode=False, curated_title=None):
    """Select and create a 2:3 poster image with overlays using video-thumbnail-creator.

    Creates a poster in 2:3 format (1080x1620) with:
    - Title overlay (curated title if provided, otherwise raw video title)
    - Category overlay (from YouTube channel name)
    - Note overlay (formatted upload date in German)

    The poster is saved as poster.jpg and later embedded as artwork in the M4V file.

    Args:
        job_dir: Path to the job directory containing the original video
        meta: Video metadata dictionary (from original.info.json)
        auto_mode: If True, AI selects the best frame and crop position automatically
        curated_title: Optional curated title from AI analysis; falls back to meta title
    """
    video_src = None
    for f in os.listdir(job_dir):
        if f.startswith("original.") and f.endswith((".mkv", ".mp4", ".webm")):
            video_src = os.path.join(job_dir, f)
            break

    if not video_src:
        print("   ⚠️  Kein Video gefunden für Poster-Erstellung.")
        return

    target_poster = os.path.join(job_dir, "poster.jpg")

    # Determine overlay values from metadata
    overlay_title = curated_title or meta.get("title", "")
    overlay_category = meta.get("channel") or meta.get("uploader") or ""
    overlay_note = _format_upload_date(meta.get("upload_date", ""))

    print(f"\n🖼️  Erstelle Poster (2:3)...")
    if overlay_title:
        print(f"   📝 Titel: {overlay_title}")
    if overlay_category:
        print(f"   📂 Kategorie: {overlay_category}")
    if overlay_note:
        print(f"   📅 Datum: {overlay_note}")
    _print_thumbnail_creator_runtime_info()

    try:
        with ThumbnailSession(
            video_src,
            ffmpeg=CONFIG.get('ffmpeg', 'ffmpeg'),
            ffprobe=CONFIG.get('ffprobe', 'ffprobe'),
        ) as session:

            if auto_mode:
                print("   🤖 Auto-Modus: K.I. wählt automatisch das beste Bild...")
                try:
                    suggestion = session.suggest_frame(
                        title=meta.get('title', ''),
                        description=_build_suggest_frame_description(meta.get('description', '')),
                    )
                    session.select_frame(suggestion["frame_index"])
                    reasoning = suggestion.get("reasoning", "Keine Begründung verfügbar")
                    print(f"   ✅ K.I. Auswahl: Bild {suggestion['frame_index']}")
                    print(f"   💡 Begründung: {reasoning}")
                except Exception as e:
                    print(f"   ⚠️  K.I.-Auswahl fehlgeschlagen: {e}")
                    print("   ⚠️  Kein Titelbild wird eingebettet.")
                    return

                # Auto crop position via AI
                try:
                    crop_suggestion = session.suggest_crop()
                    crop_position = crop_suggestion.get("crop_position", "center")
                    print(f"   🎯 Crop-Position: {crop_position}")
                except Exception:
                    crop_position = "center"

            else:
                # Manual mode: Open mosaic and let user choose
                subprocess.run(["open", session.mosaic_path])

                print("\n   Auswahloptionen:")
                print("   • Eingabe 0-19: Manuell ein Bild wählen")
                print("   • [ENTER]: Kein Titelbild (Mediencenter findet eigenes)")
                print("   • [a] oder [ai]: K.I. wählt automatisch das beste Bild")
                choice = input("\n   Deine Wahl: ").strip().lower()

                if choice in ('a', 'ai'):
                    try:
                        suggestion = session.suggest_frame(
                            title=meta.get('title', ''),
                            description=_build_suggest_frame_description(meta.get('description', '')),
                        )
                        ai_index = suggestion["frame_index"]
                        reasoning = suggestion.get("reasoning", "Keine Begründung verfügbar")

                        print(f"\n   🤖 K.I. Empfehlung: Bild {ai_index}")
                        print(f"   💡 Begründung: {reasoning}")

                        confirm = input("\n   K.I. Auswahl übernehmen? [ENTER]=Ja, [n]=Manuelle Wahl: ").strip().lower()
                        if confirm == 'n':
                            choice = input("\n   Wähle Bild (0-19) oder [ENTER] für kein Titelbild: ").strip()
                            if choice.isdigit() and 0 <= int(choice) <= 19:
                                session.select_frame(int(choice))
                            else:
                                print("   ℹ️  Kein Titelbild eingebettet. Mediencenter wird eigenes Bild finden.")
                                _close_preview()
                                return
                        else:
                            session.select_frame(ai_index)
                    except Exception as e:
                        print(f"   ⚠️  K.I.-Auswahl fehlgeschlagen: {e}")
                        choice = input("   Wähle Bild (0-19) oder [ENTER] für kein Titelbild: ").strip()
                        if choice.isdigit() and 0 <= int(choice) <= 19:
                            session.select_frame(int(choice))
                        else:
                            print("   ℹ️  Kein Titelbild eingebettet.")
                            _close_preview()
                            return

                elif choice.isdigit() and 0 <= int(choice) <= 19:
                    session.select_frame(int(choice))
                    print(f"   ✅ Bild {choice} ausgewählt.")

                else:
                    print("   ℹ️  Kein Titelbild eingebettet. Mediencenter wird eigenes Bild finden.")
                    _close_preview()
                    return

                _close_preview()

                # Manual crop position selection
                print("\n   🎯 Crop-Position für Poster (1:1 Ausschnitt):")
                print("   1. left")
                print("   2. center-left")
                print("   3. center (Standard)")
                print("   4. center-right")
                print("   5. right")
                print("   [a] K.I. wählt automatisch")
                crop_choice = input("   Auswahl [ENTER=center]: ").strip().lower()

                crop_map = {
                    "1": "left", "2": "center-left", "3": "center",
                    "4": "center-right", "5": "right",
                    "left": "left", "center-left": "center-left",
                    "center": "center", "center-right": "center-right",
                    "right": "right",
                }

                if crop_choice in ('a', 'ai'):
                    try:
                        crop_suggestion = session.suggest_crop()
                        crop_position = crop_suggestion.get("crop_position", "center")
                        print(f"   🤖 K.I. Crop-Position: {crop_position}")
                    except Exception:
                        crop_position = "center"
                elif crop_choice in crop_map:
                    crop_position = crop_map[crop_choice]
                else:
                    crop_position = "center"

                print(f"   ✅ Crop-Position: {crop_position}")

            # Compose the final poster (2:3 format with overlays)
            fanart_enabled = CONFIG.get('fanart_enabled', False)
            result = session.compose(
                format="poster",
                output_path=target_poster,
                crop_position=crop_position,
                template=get_style(_POSTER_STYLE_NAME),
                overlay_title=overlay_title or None,
                overlay_category=overlay_category or None,
                overlay_note=overlay_note or None,
                fanart=fanart_enabled,
            )
            print(f"   ✅ Poster (2:3) gespeichert: {result.poster_path}")

            # Copy fanart to a well-known location in the job directory
            if fanart_enabled and result.fanart_path:
                target_fanart = os.path.join(job_dir, "fanart.jpg")
                shutil.copy2(result.fanart_path, target_fanart)
                print(f"   ✅ Fanart (16:9) gespeichert: {target_fanart}")

    except Exception as e:
        print(f"   ⚠️  Fehler bei der Poster-Erstellung: {e}")
        print("   ℹ️  Kein Titelbild wird eingebettet.")


def _close_preview():
    """Close macOS Preview app after mosaic selection."""
    try:
        subprocess.run(
            ["osascript", "-e", 'tell application "Preview" to quit'],
            capture_output=True, timeout=2
        )
    except (subprocess.SubprocessError, subprocess.TimeoutExpired, FileNotFoundError, OSError):
        pass
