"""에피소드 API 테스트."""

import io
import shutil

import pytest
from fastapi.testclient import TestClient
from fpdf import FPDF
from pathlib import Path

from app.core.config import settings
from app.core.database import Base, engine
from app.main import app
from tests._safety_guards import safe_drop_all, safe_rmtree


def make_test_pdf(text="Test screenplay content") -> bytes:
    pdf = FPDF()
    pdf.add_page()
    pdf.set_font("Helvetica", size=12)
    pdf.cell(200, 10, text=text)
    return pdf.output()


@pytest.fixture(autouse=True)
def _setup_db():
    Base.metadata.create_all(engine)
    with TestClient(app):
        pass
    yield
    safe_drop_all(engine, Base.metadata)
    proj_dir = Path(settings.projects_dir)
    if proj_dir.exists():
        safe_rmtree(proj_dir)


@pytest.fixture()
def client():
    with TestClient(app, raise_server_exceptions=False) as c:
        yield c


def _admin_login(client: TestClient):
    resp = client.post("/api/v1/auth/login", json={"username": "admin", "password": "admin123"})
    assert resp.status_code == 200


def _create_project(client: TestClient) -> str:
    _admin_login(client)
    resp = client.post("/api/v1/projects/", json={"name": "Episode Test Proj"})
    assert resp.status_code == 200
    return resp.json()["id"]


def test_upload_episode(client: TestClient):
    project_id = _create_project(client)
    pdf_bytes = make_test_pdf("INT. OFFICE - DAY")
    resp = client.post(
        f"/api/v1/projects/{project_id}/episodes/",
        data={"episode_number": "1", "title": "Pilot"},
        files={"file": ("pilot.pdf", io.BytesIO(pdf_bytes), "application/pdf")},
    )
    assert resp.status_code == 200
    data = resp.json()
    assert data["episode_number"] == 1
    assert data["title"] == "Pilot"
    assert data["source_filename"] == "pilot.pdf"
    assert data["status"] == "uploaded"
    assert data["page_count"] == 1
    assert "id" in data


def test_list_episodes(client: TestClient):
    project_id = _create_project(client)
    pdf_bytes = make_test_pdf("Scene 1")
    client.post(
        f"/api/v1/projects/{project_id}/episodes/",
        data={"episode_number": "1", "title": "First"},
        files={"file": ("ep1.pdf", io.BytesIO(pdf_bytes), "application/pdf")},
    )
    resp = client.get(f"/api/v1/projects/{project_id}/episodes/")
    assert resp.status_code == 200
    items = resp.json()
    assert len(items) == 1
    assert items[0]["title"] == "First"


def test_get_episode(client: TestClient):
    project_id = _create_project(client)
    pdf_bytes = make_test_pdf("Scene content")
    create_resp = client.post(
        f"/api/v1/projects/{project_id}/episodes/",
        data={"episode_number": "1", "title": "Get Me"},
        files={"file": ("ep.pdf", io.BytesIO(pdf_bytes), "application/pdf")},
    )
    assert create_resp.status_code == 200
    episode_id = create_resp.json()["id"]

    resp = client.get(f"/api/v1/projects/{project_id}/episodes/{episode_id}")
    assert resp.status_code == 200
    assert resp.json()["title"] == "Get Me"
    assert resp.json()["id"] == episode_id


def test_update_episode(client: TestClient):
    project_id = _create_project(client)
    pdf_bytes = make_test_pdf("Content")
    create_resp = client.post(
        f"/api/v1/projects/{project_id}/episodes/",
        data={"episode_number": "1", "title": "Old Title"},
        files={"file": ("ep.pdf", io.BytesIO(pdf_bytes), "application/pdf")},
    )
    assert create_resp.status_code == 200
    episode_id = create_resp.json()["id"]

    resp = client.patch(
        f"/api/v1/projects/{project_id}/episodes/{episode_id}",
        json={"title": "New Title"},
    )
    assert resp.status_code == 200
    assert resp.json()["title"] == "New Title"


def test_delete_episode(client: TestClient):
    project_id = _create_project(client)
    pdf_bytes = make_test_pdf("Delete me")
    create_resp = client.post(
        f"/api/v1/projects/{project_id}/episodes/",
        data={"episode_number": "1", "title": "Delete Me"},
        files={"file": ("ep.pdf", io.BytesIO(pdf_bytes), "application/pdf")},
    )
    assert create_resp.status_code == 200
    episode_id = create_resp.json()["id"]

    resp = client.delete(f"/api/v1/projects/{project_id}/episodes/{episode_id}")
    assert resp.status_code == 200
    assert resp.json()["ok"] is True

    # Verify it's gone
    resp = client.get(f"/api/v1/projects/{project_id}/episodes/{episode_id}")
    assert resp.status_code == 404


def test_duplicate_episode_number(client: TestClient):
    project_id = _create_project(client)
    pdf_bytes = make_test_pdf("Content")
    client.post(
        f"/api/v1/projects/{project_id}/episodes/",
        data={"episode_number": "1", "title": "First"},
        files={"file": ("ep1.pdf", io.BytesIO(pdf_bytes), "application/pdf")},
    )
    resp = client.post(
        f"/api/v1/projects/{project_id}/episodes/",
        data={"episode_number": "1", "title": "Duplicate"},
        files={"file": ("ep2.pdf", io.BytesIO(pdf_bytes), "application/pdf")},
    )
    assert resp.status_code == 400
    assert resp.json()["error"]["code"] == "episode.duplicate_number"


def test_episode_not_found(client: TestClient):
    project_id = _create_project(client)
    resp = client.get(f"/api/v1/projects/{project_id}/episodes/nonexistent-id")
    assert resp.status_code == 404
    assert resp.json()["error"]["code"] == "episode.not_found"
