"""Tests for the processing API router (job submission stub).

Tests cover:
- POST /api/processing/submit creates a valid pending job
- GET /api/processing/status/{job_id} returns job details
- GET /api/processing/status/{unknown} returns 404
- GET /api/processing/jobs returns all submitted jobs
- Validation of request fields
- Job eviction when MAX_JOBS reached
"""

from __future__ import annotations

import uuid

import pytest
from fastapi.testclient import TestClient

from sltk.api.main import app
from sltk.api.routers import processing as proc_mod

pytestmark = pytest.mark.api


# ---------------------------------------------------------------------------
# Fixtures
# ---------------------------------------------------------------------------


@pytest.fixture
def client():
    return TestClient(app)


@pytest.fixture(autouse=True)
def clear_jobs():
    """Reset the in-memory job store between tests."""
    proc_mod._jobs.clear()
    yield
    proc_mod._jobs.clear()


# ---------------------------------------------------------------------------
# Submit tests
# ---------------------------------------------------------------------------


class TestSubmitProcessing:
    def test_submit_returns_pending_job(self, client):
        resp = client.post(
            "/api/processing/submit",
            json={
                "video_paths": ["/tmp/a.mp4"],
                "type": "segments",
                "model": "SIGNREP",
            },
        )
        assert resp.status_code == 200
        data = resp.json()
        assert data["status"] == "pending"
        assert data["total_videos"] == 1
        assert data["processed_videos"] == 0
        assert data["type"] == "segments"
        assert data["model"] == "SIGNREP"
        # job_id should be a valid UUID
        uuid.UUID(data["job_id"])

    def test_submit_multiple_videos(self, client):
        resp = client.post(
            "/api/processing/submit",
            json={
                "video_paths": ["/a.mp4", "/b.mp4", "/c.mp4"],
                "type": "both",
                "model": "SIGNREP-BSLCP",
            },
        )
        assert resp.status_code == 200
        data = resp.json()
        assert data["total_videos"] == 3
        assert data["type"] == "both"
        assert data["model"] == "SIGNREP-BSLCP"

    def test_submit_requires_video_paths(self, client):
        resp = client.post(
            "/api/processing/submit",
            json={"video_paths": [], "type": "segments"},
        )
        assert resp.status_code == 422

    def test_submit_validates_type(self, client):
        resp = client.post(
            "/api/processing/submit",
            json={
                "video_paths": ["/tmp/a.mp4"],
                "type": "invalid",
            },
        )
        assert resp.status_code == 422


# ---------------------------------------------------------------------------
# Status tests
# ---------------------------------------------------------------------------


class TestProcessingStatus:
    def test_get_status_existing_job(self, client):
        submit = client.post(
            "/api/processing/submit",
            json={
                "video_paths": ["/tmp/v1.mp4", "/tmp/v2.mp4"],
                "type": "spots",
            },
        )
        job_id = submit.json()["job_id"]

        resp = client.get(f"/api/processing/status/{job_id}")
        assert resp.status_code == 200
        data = resp.json()
        assert data["job_id"] == job_id
        assert data["total_videos"] == 2
        assert data["type"] == "spots"

    def test_get_status_nonexistent_returns_404(self, client):
        resp = client.get("/api/processing/status/nonexistent-id")
        assert resp.status_code == 404

    def test_get_status_unknown_uuid_returns_404(self, client):
        fake_id = str(uuid.uuid4())
        resp = client.get(f"/api/processing/status/{fake_id}")
        assert resp.status_code == 404


# ---------------------------------------------------------------------------
# List jobs tests
# ---------------------------------------------------------------------------


class TestListProcessingJobs:
    def test_list_empty(self, client):
        resp = client.get("/api/processing/jobs")
        assert resp.status_code == 200
        data = resp.json()
        assert data["total"] == 0
        assert data["jobs"] == []

    def test_list_after_submits(self, client):
        for _ in range(3):
            client.post(
                "/api/processing/submit",
                json={
                    "video_paths": ["/tmp/x.mp4"],
                    "type": "segments",
                },
            )

        resp = client.get("/api/processing/jobs")
        assert resp.status_code == 200
        data = resp.json()
        assert data["total"] == 3
        assert len(data["jobs"]) == 3

    def test_list_ordered_by_creation(self, client):
        ids = []
        for i in range(3):
            r = client.post(
                "/api/processing/submit",
                json={
                    "video_paths": [f"/tmp/{i}.mp4"],
                    "type": "segments",
                },
            )
            ids.append(r.json()["job_id"])

        resp = client.get("/api/processing/jobs")
        data = resp.json()
        # Sorted reverse by created_at — most recent first
        returned_ids = [j["job_id"] for j in data["jobs"]]
        assert returned_ids == list(reversed(ids))


# ---------------------------------------------------------------------------
# Eviction tests
# ---------------------------------------------------------------------------


class TestJobEviction:
    def test_eviction_when_max_reached(self, client):
        """Oldest completed jobs are evicted when MAX_JOBS is reached."""
        # Pre-fill with MAX_JOBS completed jobs via internal store
        from sltk.api.models import ProcessingJobStatus

        for i in range(proc_mod.MAX_JOBS):
            jid = f"old-{i}"
            proc_mod._jobs[jid] = ProcessingJobStatus(
                job_id=jid,
                status="completed",
                created_at=f"2025-01-01T00:00:{i:02d}Z",
                total_videos=1,
            )

        assert len(proc_mod._jobs) == proc_mod.MAX_JOBS

        # Submit a new job — should trigger eviction
        resp = client.post(
            "/api/processing/submit",
            json={
                "video_paths": ["/tmp/new.mp4"],
                "type": "segments",
            },
        )
        assert resp.status_code == 200
        # Some completed jobs should have been evicted
        assert len(proc_mod._jobs) <= proc_mod.MAX_JOBS
