"""
Integration tests for the dashboard server that actually run builds.

These tests start a real HTTP server and run actual `ato build` commands.
They are slower than unit tests and should be run separately.

Usage:
    pytest test/test_dashboard_integration.py -v

Note: These tests require the quickstart example project to exist.
"""

import time
from pathlib import Path

import pytest
import requests

QUICKSTART_PROJECT = Path(__file__).parent.parent / "examples" / "quickstart"


@pytest.fixture
def quickstart_project() -> Path:
    """Return the path to the quickstart example project."""
    if not QUICKSTART_PROJECT.exists():
        pytest.skip("Quickstart project not found")
    return QUICKSTART_PROJECT


@pytest.fixture
def dashboard_server(tmp_path: Path, quickstart_project: Path):
    """Start a real dashboard server for integration testing."""
    from atopile.server.server import DashboardServer

    # Create server using the DashboardServer class directly
    # Don't specify port - let it find a free port automatically
    server = DashboardServer(
        workspace_paths=[quickstart_project.parent],
    )
    server.start()

    # Wait for server to be ready
    base_url = server.url
    max_wait = 10
    started = False
    for _ in range(max_wait * 10):
        try:
            resp = requests.get(f"{base_url}/api/projects", timeout=1)
            if resp.status_code == 200:
                started = True
                break
        except (requests.exceptions.ConnectionError, requests.exceptions.Timeout):
            pass
        time.sleep(0.1)

    if not started:
        server.shutdown()
        pytest.fail(f"Server did not start within {max_wait}s on {base_url}")

    yield base_url

    # Cleanup
    server.shutdown()


class TestRealBuilds:
    """Integration tests that run actual builds."""

    @pytest.mark.not_in_ci  # requires kicad-cli
    def test_build_quickstart_and_poll_status(
        self, dashboard_server: str, quickstart_project: Path
    ):
        """
        Start a build via API and poll until completion.

        This test:
        1. POSTs to /api/build to start a build
        2. Polls /api/build/{id}/status until completion
        3. Verifies the build succeeded
        """
        # Start the build
        response = requests.post(
            f"{dashboard_server}/api/build",
            json={
                "project_root": str(quickstart_project),
                "targets": ["default"],
                "frozen": False,
            },
            timeout=10,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["success"] is True
        assert len(data["buildTargets"]) > 0
        build_id = data["buildTargets"][0]["buildId"]
        print(f"Started build: {build_id}")

        # Poll for status
        max_wait = 120  # 2 minutes max
        poll_interval = 1.0
        elapsed = 0
        last_status = None

        while elapsed < max_wait:
            status_response = requests.get(
                f"{dashboard_server}/api/build/{build_id}/status",
                timeout=5,
            )
            assert status_response.status_code == 200
            status_data = status_response.json()

            print(f"  Status: {status_data['status']} (elapsed: {elapsed:.1f}s)")
            last_status = status_data

            if status_data["status"] in ["success", "failed"]:
                break

            time.sleep(poll_interval)
            elapsed += poll_interval

        # Verify final status
        assert last_status is not None
        assert last_status["status"] == "success", (
            f"Build failed: {last_status.get('error')}"
        )
        assert last_status.get("returnCode") == 0
        print(f"Build completed successfully in {elapsed:.1f}s")

    def test_build_appears_in_summary_while_building(
        self, dashboard_server: str, quickstart_project: Path
    ):
        """
        Build should appear in /api/summary while in progress.

        This verifies that the UI will see the build status during execution.
        """
        # Start the build
        response = requests.post(
            f"{dashboard_server}/api/build",
            json={
                "project_root": str(quickstart_project),
                "targets": ["default"],
                "frozen": False,
            },
            timeout=10,
        )
        data = response.json()
        build_id = data["buildTargets"][0]["buildId"]

        # Immediately check summary
        summary_response = requests.get(
            f"{dashboard_server}/api/summary",
            timeout=5,
        )
        assert summary_response.status_code == 200
        summary_data = summary_response.json()

        # Build should be in the summary (either in progress or completed)
        builds = summary_data.get("builds", [])
        found = any(
            b.get("buildId") == build_id
            or "quickstart" in b.get("displayName", "").lower()
            for b in builds
        )

        # If not found immediately, wait a bit and check again
        if not found:
            time.sleep(0.5)
            summary_response = requests.get(
                f"{dashboard_server}/api/summary",
                timeout=5,
            )
            summary_data = summary_response.json()
            builds = summary_data.get("builds", [])
            found = any(
                b.get("buildId") == build_id
                or "quickstart" in b.get("displayName", "").lower()
                for b in builds
            )

        # Wait for build to complete before exiting
        max_wait = 120
        elapsed = 0
        while elapsed < max_wait:
            status = requests.get(
                f"{dashboard_server}/api/build/{build_id}/status"
            ).json()
            if status["status"] in ["success", "failed"]:
                break
            time.sleep(1)
            elapsed += 1

        assert found, "Build was not visible in /api/summary"

    def test_project_discovery_via_api(
        self, dashboard_server: str, quickstart_project: Path
    ):
        """GET /api/projects should discover the quickstart project."""
        response = requests.get(
            f"{dashboard_server}/api/projects",
            timeout=5,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["total"] >= 1

        # Find quickstart
        quickstart = None
        for p in data["projects"]:
            if p["name"] == "quickstart":
                quickstart = p
                break

        assert quickstart is not None, "Quickstart not found in projects"
        assert quickstart["root"] == str(quickstart_project)
        assert len(quickstart["targets"]) >= 1
        assert any(t["name"] == "default" for t in quickstart["targets"])
