import argparse
import json
import sys
from pathlib import Path

import requests

PROJECT_ROOT = Path(__file__).resolve().parents[1]
if str(PROJECT_ROOT) not in sys.path:
    sys.path.insert(0, str(PROJECT_ROOT))

from app.database import SessionLocal
from app.models import Recording
from app.services import recall_service


def _extract_audio_from_payload(recording_payload: str | None) -> str | None:
    if not recording_payload:
        return None

    try:
        payload = json.loads(recording_payload)
    except json.JSONDecodeError:
        return None

    shortcuts = payload.get("media_shortcuts") or {}
    audio_mixed = shortcuts.get("audio_mixed") or {}
    return (audio_mixed.get("data") or {}).get("download_url")


def backfill_audio_download_urls(limit: int | None = None) -> int:
    db = SessionLocal()
    updated = 0
    failed = 0
    skipped = 0

    try:
        query = db.query(Recording).filter(Recording.recall_recording_id.isnot(None))

        query = query.order_by(Recording.id.asc())
        if limit:
            query = query.limit(limit)

        recordings = query.all()
        print(f"[backfill][audio] total={len(recordings)} mode=refresh-all")

        for recording in recordings:
            if not recording.meeting_id:
                skipped += 1
                print(f"[backfill][audio] skipped recording_id={recording.id} reason=no-meeting-id")
                continue

            audio_download_url = None
            video_download_url = None
            source = None

            try:
                recording_detail = recall_service.get_recording(recording.recall_recording_id)
                shortcuts = recording_detail.get("media_shortcuts") or {}
                video_mixed = shortcuts.get("video_mixed") or {}
                audio_mixed = shortcuts.get("audio_mixed") or {}
                video_download_url = (video_mixed.get("data") or {}).get("download_url")
                audio_download_url = (audio_mixed.get("data") or {}).get("download_url")
                source = "recall"
            except requests.RequestException as exc:
                print(
                    f"[backfill][audio] recall refresh failed recording_id={recording.id} "
                    f"meeting_id={recording.meeting_id} recall_recording_id={recording.recall_recording_id} error={exc}"
                )

            if (not audio_download_url or not video_download_url) and recording.recording_payload:
                try:
                    payload = json.loads(recording.recording_payload)
                    shortcuts = payload.get("media_shortcuts") or {}
                    video_mixed = shortcuts.get("video_mixed") or {}
                    audio_mixed = shortcuts.get("audio_mixed") or {}
                    video_download_url = (video_mixed.get("data") or {}).get("download_url")
                    audio_download_url = audio_download_url or (audio_mixed.get("data") or {}).get("download_url")
                except json.JSONDecodeError:
                    pass

            if not audio_download_url and not video_download_url:
                skipped += 1
                print(
                    f"[backfill][audio] skipped recording_id={recording.id} "
                    f"meeting_id={recording.meeting_id} reason=no-audio-or-video-url"
                )
                continue

            if audio_download_url:
                recording.audio_download_url = audio_download_url
            if video_download_url:
                recording.video_download_url = video_download_url
            db.commit()
            updated += 1
            print(
                f"[backfill][audio] updated recording_id={recording.id} "
                f"meeting_id={recording.meeting_id} source={source} "
                f"audio_set={bool(audio_download_url)} video_set={bool(video_download_url)}"
            )

        print(f"[backfill][audio] done updated={updated} failed={failed} skipped={skipped}")
        return 0 if failed == 0 else 1
    except Exception as exc:
        db.rollback()
        failed += 1
        print(f"[backfill][audio] fatal error={exc}")
        return 1
    finally:
        db.close()


def main() -> int:
    parser = argparse.ArgumentParser(description="Backfill audio_download_url for existing recordings.")
    parser.add_argument(
        "--limit",
        type=int,
        default=None,
        help="Limit the number of recordings processed.",
    )
    args = parser.parse_args()
    return backfill_audio_download_urls(limit=args.limit)


if __name__ == "__main__":
    raise SystemExit(main())
