from __future__ import annotations

from collections.abc import Callable

from fastapi.testclient import TestClient


def _create_project(client: TestClient, name: str) -> int:
    response = client.post(
        "/projects",
        json={
            "name": name,
            "location": "Western Australia",
            "operation_type": "open_pit",
            "description": "Legacy calculations redirect test project",
        },
    )
    assert response.status_code == 201
    return response.json()["id"]


def _create_scenario(client: TestClient, project_id: int, name: str) -> int:
    response = client.post(
        f"/projects/{project_id}/scenarios",
        json={
            "name": name,
            "description": "Scenario for legacy calculations redirect tests",
            "status": "draft",
            "currency": "usd",
            "primary_resource": "diesel",
        },
    )
    assert response.status_code == 201
    return response.json()["id"]


def test_legacy_opex_redirects_to_scenario_route(
    client: TestClient,
    scenario_calculation_url: Callable[[str, int, int], str],
) -> None:
    project_id = _create_project(client, "Opex Legacy Redirect Project")
    scenario_id = _create_scenario(
        client, project_id, "Opex Legacy Redirect Scenario")

    response = client.get(
        f"/calculations/opex?project_id={project_id}&scenario_id={scenario_id}",
        follow_redirects=False,
    )

    assert response.status_code == 308
    assert response.headers["location"] == scenario_calculation_url(
        "calculations.scenario_opex_form",
        project_id,
        scenario_id,
    )

    post_response = client.post(
        f"/calculations/opex?project_id={project_id}&scenario_id={scenario_id}",
        data={},
        follow_redirects=False,
    )

    assert post_response.status_code == 308
    assert post_response.headers["location"] == scenario_calculation_url(
        "calculations.scenario_opex_submit",
        project_id,
        scenario_id,
    )


def test_legacy_capex_redirects_to_scenario_route(
    client: TestClient,
    scenario_calculation_url: Callable[[str, int, int], str],
) -> None:
    project_id = _create_project(client, "Capex Legacy Redirect Project")
    scenario_id = _create_scenario(
        client, project_id, "Capex Legacy Redirect Scenario")

    response = client.get(
        f"/calculations/capex?project_id={project_id}&scenario_id={scenario_id}",
        follow_redirects=False,
    )

    assert response.status_code == 308
    assert response.headers["location"] == scenario_calculation_url(
        "calculations.scenario_capex_form",
        project_id,
        scenario_id,
    )

    post_response = client.post(
        f"/calculations/capex?project_id={project_id}&scenario_id={scenario_id}",
        data={},
        follow_redirects=False,
    )

    assert post_response.status_code == 308
    assert post_response.headers["location"] == scenario_calculation_url(
        "calculations.scenario_capex_submit",
        project_id,
        scenario_id,
    )


def test_legacy_opex_redirects_to_project_scenarios_when_only_project(
    client: TestClient,
    app_url_for: Callable[..., str],
) -> None:
    project_id = _create_project(client, "Opex Legacy Project Only")

    response = client.get(
        f"/calculations/opex?project_id={project_id}",
        follow_redirects=False,
    )

    assert response.status_code == 303
    assert response.headers["location"] == app_url_for(
        "scenarios.project_scenario_list", project_id=project_id
    )


def test_legacy_capex_rejects_invalid_identifiers(client: TestClient) -> None:
    response = client.get(
        "/calculations/capex?project_id=abc&scenario_id=-10",
        follow_redirects=False,
    )

    assert response.status_code == 400
    assert "project_id" in response.json()["detail"].lower()


def test_legacy_opex_returns_not_found_for_missing_entities(client: TestClient) -> None:
    project_id = _create_project(client, "Opex Legacy Missing Scenario")

    response = client.get(
        f"/calculations/opex?project_id={project_id}&scenario_id=999999",
        follow_redirects=False,
    )

    assert response.status_code == 404
    assert response.json()["detail"] == "Scenario not found"
