import argparse
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 import crud
from app.database import SessionLocal
from app.models import Recording
from app.services import recall_service


def backfill_recordings_to_s3(force_all: bool = False, 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))
        if not force_all:
            query = query.filter(Recording.download_urls_refreshed_at.is_(None))

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

        recordings = query.all()
        print(f"[backfill][s3] total={len(recordings)} force_all={force_all}")

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

            try:
                recording_detail = recall_service.get_recording(recording.recall_recording_id)
                refreshed_recording = crud.upsert_recording_from_recall(
                    db,
                    recording.meeting_id,
                    recording_detail,
                    mark_links_refreshed=True,
                )
                if not refreshed_recording:
                    skipped += 1
                    print(
                        f"[backfill][s3] skipped recording_id={recording.id} "
                        f"meeting_id={recording.meeting_id} reason=no-recording-data"
                    )
                    continue

                updated += 1
                print(
                    f"[backfill][s3] updated recording_id={recording.id} "
                    f"meeting_id={recording.meeting_id} recall_recording_id={recording.recall_recording_id} "
                    f"audio={refreshed_recording.audio_download_url} video={refreshed_recording.video_download_url} "
                    f"refreshed_at={refreshed_recording.download_urls_refreshed_at}"
                )
            except requests.RequestException as exc:
                failed += 1
                print(
                    f"[backfill][s3] failed recording_id={recording.id} "
                    f"meeting_id={recording.meeting_id} recall_recording_id={recording.recall_recording_id} "
                    f"error={exc}"
                )

        print(f"[backfill][s3] done updated={updated} failed={failed} skipped={skipped}")
        return 0 if failed == 0 else 1
    finally:
        db.close()


def main() -> int:
    parser = argparse.ArgumentParser(
        description="Refresh recording media from Recall, upload audio/video to S3/Spaces, and mark refresh time."
    )
    parser.add_argument(
        "--force-all",
        action="store_true",
        help="Process all recordings with recall_recording_id, not only rows where download_urls_refreshed_at is null.",
    )
    parser.add_argument(
        "--limit",
        type=int,
        default=None,
        help="Limit the number of recordings processed.",
    )
    args = parser.parse_args()
    return backfill_recordings_to_s3(force_all=args.force_all, limit=args.limit)


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