#!/usr/bin/env python3
"""
karaoke.py — Караоке-генератор v0.1 (MVP)

Принимает аудиофайл (и опционально текст), генерирует видео с
синхронизированным текстом.

Пример:
    python karaoke.py --audio song.mp3
    python karaoke.py --audio song.mp3 --text lyrics.lrc
    python karaoke.py --audio song.mp3 --text lyrics.txt --output my_video.mp4
"""

import argparse
import os
import sys
from pathlib import Path
from dotenv import load_dotenv

# Загружаем ~/.openclaw/.env
load_dotenv(os.path.expanduser("~/.openclaw/.env"))

# Путь к директории проекта
PROJECT_DIR = Path(__file__).parent

# Добавляем в path для импорта модулей
sys.path.insert(0, str(PROJECT_DIR))

from transcribe import transcribe
from nlp import analyze
from video_bg import get_bg_video
from render import render_with_bg, render
from video_bg import FFMPEG


def get_audio_duration(audio_path: str) -> float:
    """Длительность аудио через ffprobe."""
    import subprocess
    FFPROBE = os.environ.get("FFPROBE_BIN",
                              os.path.expanduser("~/bin/ffmpeg-7.0.2-amd64-static/ffprobe"))
    cmd = [
        FFPROBE, "-v", "quiet", "-show_entries", "format=duration",
        "-of", "csv=p=0", audio_path
    ]
    out = subprocess.check_output(cmd, text=True).strip()
    return float(out)


def main():
    parser = argparse.ArgumentParser(
        description="Караоке-генератор: аудио → видео с текстом",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Примеры:
  python karaoke.py --audio song.mp3
  python karaoke.py --audio song.mp3 --text lyrics.lrc
  python karaoke.py --audio song.mp3 --text lyrics.srt --output out.mp4
  python karaoke.py --audio song.mp3 --whisper-model small
        """
    )
    parser.add_argument("--audio", required=True, help="Путь к аудиофайлу (mp3, wav, ogg, m4a)")
    parser.add_argument("--text", default=None, help="Путь к файлу с текстом (lrc, srt, txt)")
    parser.add_argument("--output", default="output.mp4", help="Путь к выходному видео")
    parser.add_argument("--whisper-model", default="base",
                        choices=["tiny", "base", "small", "medium", "large"],
                        help="Размер Whisper-модели (по умолчанию: base)")
    parser.add_argument("--model", default=None,
                        choices=["tiny", "base", "small", "medium", "large"],
                        help="Алиас для --whisper-model (удобнее для .txt)")
    parser.add_argument("--device", default="cpu", choices=["cpu", "cuda"],
                        help="Устройство для Whisper (по умолчанию: cpu)")
    parser.add_argument("--language", default=None,
                        help="Код языка (напр. ru, en) для Whisper (None = авто)")
    parser.add_argument("--no-api", action="store_true",
                        help="Не использовать OpenAI API, только локальный faster-whisper")

    args = parser.parse_args()

    # --model алиас для --whisper-model
    model_size = args.model if args.model else args.whisper_model

    # Валидация
    audio_path = os.path.abspath(args.audio)
    if not os.path.isfile(audio_path):
        print(f"❌ Аудиофайл не найден: {audio_path}")
        sys.exit(1)

    output_path = os.path.abspath(args.output)
    output_dir = os.path.dirname(output_path)
    if not output_dir:
        output_dir = "."

    tmp_dir = os.path.join(output_dir, ".karaoke_tmp")
    os.makedirs(tmp_dir, exist_ok=True)

    print("=" * 60)
    print("🎤 Караоке-генератор v0.1")
    print("=" * 60)

    # --- Шаг 1: Транскрипция ---
    print("\n📝 Шаг 1: Транскрипция…")
    if args.text:
        ext = Path(args.text).suffix.lower()
        print(f"   Используем готовый текст: {args.text} ({ext})")
        segments = transcribe(audio_path, text_path=args.text,
                              model_size=model_size,
                              device=args.device, language=args.language,
                              use_api=not args.no_api)
    else:
        segments = transcribe(audio_path, model_size=model_size,
                              device=args.device, language=args.language,
                              use_api=not args.no_api)

    if not segments:
        print("❌ Не удалось получить сегменты текста!")
        sys.exit(1)

    print(f"   Получено {len(segments)} сегментов.")
    full_text = " ".join(s["text"] for s in segments)

    audio_duration = get_audio_duration(audio_path)
    print(f"   Длительность аудио: {audio_duration:.1f}s")

    # --- Шаг 2: NLP-анализ ---
    print("\n🧠 Шаг 2: NLP-анализ текста…")
    nlp_result = analyze(full_text)
    mood = nlp_result.get("mood", "neutral")
    scenes = nlp_result.get("scenes", ["abstract"])
    search_query = scenes[0] if scenes else "abstract"
    print(f"   Настроение: {mood}")
    print(f"   Сцена для фона: {search_query}")

    # --- Шаг 3: Видео-фон ---
    print(f"\n🎬 Шаг 3: Подбор видео-фона…")
    bg_video = get_bg_video(search_query, audio_duration, tmp_dir)
    print(f"   Видео-фон: {bg_video}")

    # --- Шаг 4: Рендер ---
    print(f"\n🎞️ Шаг 4: Рендер видео…")
    is_black_bg = (bg_video.split("/")[-1] == "background.mp4"
                   and get_bg_video.__doc__)

    # Проверяем, чёрный фон или реальный видео
    # Проще: всегда пытаемся render_with_bg — он сам упадёт на fallback
    try:
        render_with_bg(segments, audio_path, bg_video, output_path)
    except Exception as e:
        print(f"[karaoke] Render с фоном не удался: {e}")
        print("[karaoke] Пробуем fallback…")
        render(segments, audio_path, bg_video, output_path)

    # Финал
    print("\n" + "=" * 60)
    if os.path.isfile(output_path):
        size_mb = os.path.getsize(output_path) / (1024 * 1024)
        print(f"✅ Готово: {output_path} ({size_mb:.1f} MB)")
    else:
        print("❌ Ошибка: выходной файл не создан!")
        sys.exit(1)
    print("=" * 60)

    # Чистим tmp
    try:
        import shutil
        shutil.rmtree(tmp_dir)
    except Exception:
        pass


if __name__ == "__main__":
    main()
