from __future__ import annotations

import csv
from io import BytesIO, StringIO
from zipfile import ZipFile

from fastapi.testclient import TestClient
from sqlalchemy.orm import Session

from models import Project, Scenario, ScenarioStatus
from services.unit_of_work import UnitOfWork


def _seed_projects(session: Session) -> None:
    project = Project(name="Alpha", operation_type="open_pit")
    project.updated_at = project.created_at
    session.add(project)
    session.commit()


def _seed_scenarios(session: Session, project: Project) -> Scenario:
    scenario = Scenario(
        name="Scenario A",
        project_id=project.id,
        status=ScenarioStatus.ACTIVE,
    )
    session.add(scenario)
    session.commit()
    session.refresh(scenario)
    return scenario


def test_projects_export_modal(client: TestClient) -> None:
    response = client.get("/exports/modal/projects")
    assert response.status_code == 200
    assert "Export Projects" in response.text


def test_scenarios_export_modal(client: TestClient) -> None:
    response = client.get("/exports/modal/scenarios")
    assert response.status_code == 200
    assert "Export Scenarios" in response.text


def test_project_export_csv(client: TestClient, unit_of_work_factory) -> None:
    with unit_of_work_factory() as uow:
        project = Project(name="CSV Project", operation_type="open_pit")
        uow.projects.create(project)

    response = client.post(
        "/exports/projects",
        json={"format": "csv"},
    )

    assert response.status_code == 200
    assert response.headers["Content-Type"].startswith("text/csv")
    assert "attachment; filename=" in response.headers["Content-Disposition"]

    content = response.content.decode("utf-8")
    reader = csv.reader(StringIO(content))
    rows = list(reader)
    assert rows[0][:3] == ["name", "location", "operation_type"]
    assert any(row[0] == "CSV Project" for row in rows[1:])


def test_project_export_excel(client: TestClient, unit_of_work_factory) -> None:
    with unit_of_work_factory() as uow:
        project = Project(name="XLSX Project", operation_type="open_pit")
        uow.projects.create(project)

    response = client.post(
        "/exports/projects",
        json={"format": "xlsx"},
    )

    assert response.status_code == 200
    assert response.headers["Content-Type"].startswith(
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    )

    with ZipFile(BytesIO(response.content)) as archive:
        assert "xl/workbook.xml" in archive.namelist()


def test_scenario_export_csv(client: TestClient, unit_of_work_factory) -> None:
    with unit_of_work_factory() as uow:
        project = Project(name="Scenario Project", operation_type="open_pit")
        uow.projects.create(project)
        scenario = Scenario(
            name="Scenario CSV",
            project_id=project.id,
            status=ScenarioStatus.ACTIVE,
        )
        uow.scenarios.create(scenario)

    response = client.post(
        "/exports/scenarios",
        json={"format": "csv"},
    )

    assert response.status_code == 200
    reader = csv.reader(StringIO(response.content.decode("utf-8")))
    rows = list(reader)
    assert rows[0][0] == "project_name"
    assert any(row[0] == "Scenario Project" for row in rows[1:])


def test_scenario_export_excel(client: TestClient, unit_of_work_factory) -> None:
    with unit_of_work_factory() as uow:
        project = Project(name="Scenario Excel", operation_type="open_pit")
        uow.projects.create(project)
        scenario = Scenario(
            name="Scenario XLSX",
            project_id=project.id,
            status=ScenarioStatus.ACTIVE,
        )
        uow.scenarios.create(scenario)

    response = client.post(
        "/exports/scenarios",
        json={"format": "xlsx"},
    )

    assert response.status_code == 200
    assert response.headers["Content-Type"].startswith(
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    )

    with ZipFile(BytesIO(response.content)) as archive:
        assert "xl/workbook.xml" in archive.namelist()
