"""Integration tests for the Flight API endpoints."""

import json

import pytest
from httpx import ASGITransport, AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine

from gps_denied.app import app
from gps_denied.db.engine import get_session
from gps_denied.db.models import Base


@pytest.fixture
async def override_get_session():
    """Create an in-memory SQLite db for API tests."""
    engine = create_async_engine("sqlite+aiosqlite://", echo=False)
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)
    async_session = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)

    async def _get_session():
        async with async_session() as session:
            yield session

    app.dependency_overrides[get_session] = _get_session
    yield
    app.dependency_overrides.clear()
    await engine.dispose()


@pytest.fixture
async def client(override_get_session) -> AsyncClient:
    async with AsyncClient(
        transport=ASGITransport(app=app), base_url="http://test"
    ) as ac:
        yield ac


# ── Payload Fixtures ──────────────────────────────────────────────────────

FLIGHT_PAYLOAD = {
    "name": "Integration_Test_Flight",
    "description": "API Test",
    "start_gps": {"lat": 48.1, "lon": 37.2},
    "rough_waypoints": [{"lat": 48.11, "lon": 37.21}],
    "geofences": {"polygons": []},
    "camera_params": {
        "focal_length": 25.0,
        "sensor_width": 23.5,
        "sensor_height": 15.6,
        "resolution_width": 6252,
        "resolution_height": 4168
    },
    "altitude": 500.0
}


@pytest.mark.asyncio
async def test_create_flight(client: AsyncClient):
    resp = await client.post("/flights", json=FLIGHT_PAYLOAD)
    assert resp.status_code == 201
    data = resp.json()
    assert "flight_id" in data
    assert data["status"] == "prefetching"


@pytest.mark.asyncio
async def test_get_flight_details(client: AsyncClient):
    # 1. Create flight
    resp1 = await client.post("/flights", json=FLIGHT_PAYLOAD)
    fid = resp1.json()["flight_id"]

    # 2. Get flight
    resp2 = await client.get(f"/flights/{fid}")
    assert resp2.status_code == 200
    data = resp2.json()
    assert data["flight_id"] == fid
    assert data["name"] == "Integration_Test_Flight"
    assert len(data["waypoints"]) == 1


@pytest.mark.asyncio
async def test_upload_image_batch(client: AsyncClient):
    # 1. Create flight
    resp1 = await client.post("/flights", json=FLIGHT_PAYLOAD)
    fid = resp1.json()["flight_id"]

    # 2. Upload Batch
    meta = {
        "start_sequence": 1,
        "end_sequence": 10,
        "batch_number": 1
    }
    files = [("images", ("test1.jpg", b"dummy", "image/jpeg")) for _ in range(10)]

    resp2 = await client.post(
        f"/flights/{fid}/images/batch",
        data={"metadata": json.dumps(meta)},
        files=files
    )
    assert resp2.status_code == 202
    data = resp2.json()
    assert data["accepted"] is True
    assert data["next_expected"] == 11


@pytest.mark.asyncio
async def test_user_fix(client: AsyncClient):
    # 1. Create flight
    resp1 = await client.post("/flights", json=FLIGHT_PAYLOAD)
    fid = resp1.json()["flight_id"]

    # 2. Submit fix
    fix_data = {
        "frame_id": 5,
        "uav_pixel": [1024.0, 768.0],
        "satellite_gps": {"lat": 48.11, "lon": 37.22}
    }
    resp2 = await client.post(f"/flights/{fid}/user-fix", json=fix_data)
    assert resp2.status_code == 200
    data = resp2.json()
    assert data["processing_resumed"] is True

@pytest.mark.asyncio
async def test_flight_status(client: AsyncClient):
    # 1. Create
    resp1 = await client.post("/flights", json=FLIGHT_PAYLOAD)
    fid = resp1.json()["flight_id"]

    # 2. Status
    resp2 = await client.get(f"/flights/{fid}/status")
    assert resp2.status_code == 200
    assert resp2.json()["status"] == "created"  # The initial state from DB


