from pathlib import Path

from fastapi.testclient import TestClient
from sqlmodel import Session

from app.core.config import get_settings
from app.db.session import init_db, reset_db_for_tests
from app.main import app
from app.models.core import VideoAsset, VideoStatus


def setup_test_db(tmp_path):
    settings = get_settings()
    settings.database_url = "sqlite://"
    settings.storage_root = tmp_path / "storage"
    engine = init_db(settings)
    reset_db_for_tests(engine)
    return settings, engine, TestClient(app)


def test_videos_api_starts_empty(tmp_path):
    _settings, _engine, client = setup_test_db(tmp_path)

    response = client.get("/api/videos")

    assert response.status_code == 200
    assert response.json()["items"] == []


def test_video_thumbnail_serves_existing_file(tmp_path):
    _settings, engine, client = setup_test_db(tmp_path)
    media = tmp_path / "media"
    media.mkdir()
    video_path = media / "video.mp4"
    video_path.write_bytes(b"not-real-video")
    thumb_path = media / "thumb.jpg"
    thumb_path.write_bytes(b"\xff\xd8\xff\xd9")
    with Session(engine) as session:
        video = VideoAsset(
            candidate_id="test_thumb_existing",
            package_id="package_thumb_existing",
            source="prepared_package",
            file_path=str(video_path),
            file_size=video_path.stat().st_size,
            checksum="thumb-existing-checksum",
            thumbnail_path=str(thumb_path),
            working_title="Existing thumbnail",
            status=VideoStatus.ready_for_review,
        )
        session.add(video)
        session.commit()
        session.refresh(video)
        video_id = video.id

    response = client.get(f"/api/videos/{video_id}/thumbnail")

    assert response.status_code == 200
    assert response.headers["content-type"].startswith("image/jpeg")
    assert response.headers["cache-control"] == "public, max-age=3600"
    assert response.content == b"\xff\xd8\xff\xd9"


def test_video_thumbnail_falls_back_to_svg_without_path_leak(tmp_path):
    _settings, engine, client = setup_test_db(tmp_path)
    missing_path = tmp_path / "private" / "missing.mp4"
    with Session(engine) as session:
        video = VideoAsset(
            candidate_id="test_thumb_fallback",
            package_id="package_thumb_fallback",
            source="prepared_package",
            file_path=str(missing_path),
            file_size=0,
            checksum="thumb-fallback-checksum",
            working_title="No Media Yet",
            status=VideoStatus.ready_for_review,
        )
        session.add(video)
        session.commit()
        session.refresh(video)
        video_id = video.id

    response = client.get(f"/api/videos/{video_id}/thumbnail")

    assert response.status_code == 200
    assert response.headers["content-type"].startswith("image/svg+xml")
    assert response.headers["cache-control"] == "public, max-age=600"
    assert "No Media Yet" in response.text
    assert str(missing_path) not in response.text


def test_video_preview_frame_uses_thumbnail_response(tmp_path):
    _settings, engine, client = setup_test_db(tmp_path)
    media = tmp_path / "media"
    media.mkdir()
    video_path = media / "video.mp4"
    video_path.write_bytes(b"not-real-video")
    thumb_path = media / "thumb.jpg"
    thumb_path.write_bytes(b"\xff\xd8\xff\xd9")
    with Session(engine) as session:
        video = VideoAsset(
            candidate_id="test_preview_alias",
            package_id="package_preview_alias",
            source="prepared_package",
            file_path=str(video_path),
            file_size=video_path.stat().st_size,
            checksum="preview-alias-checksum",
            thumbnail_path=str(thumb_path),
            working_title="Preview Alias",
            status=VideoStatus.ready_for_review,
        )
        session.add(video)
        session.commit()
        session.refresh(video)
        video_id = video.id

    response = client.get(f"/api/videos/{video_id}/preview-frame")

    assert response.status_code == 200
    assert response.headers["content-type"].startswith("image/jpeg")
    assert response.content == b"\xff\xd8\xff\xd9"
