"""Tests for Secureframe GRC evidence exporter."""

from __future__ import annotations

import json
from typing import TYPE_CHECKING
from unittest.mock import AsyncMock, patch

import httpx
import pytest

from complyform.core.generators.evidence_export.secureframe import (
    SECUREFRAME_REGION_URLS,
    SecureframeExporter,
)

if TYPE_CHECKING:
    from pathlib import Path


@pytest.fixture
def exporter() -> SecureframeExporter:
    return SecureframeExporter()


@pytest.fixture
def metadata() -> dict[str, object]:
    return {"scan_id": "abc12345", "timestamp": "2024-01-01T00:00:00Z", "cloud": "aws"}


@pytest.fixture
def sample_findings() -> list[dict[str, object]]:
    return [
        {
            "control_id": "CC6.1",
            "framework": "soc2",
            "resource_address": "aws_s3_bucket.example",
            "resource_type": "aws_s3_bucket",
            "status": "FAIL",
            "severity": "HIGH",
            "finding": "Bucket encryption not enabled",
            "remediation": "Enable SSE",
        },
        {
            "control_id": "CC7.2",
            "framework": "soc2",
            "resource_address": "aws_s3_bucket.logs",
            "resource_type": "aws_s3_bucket",
            "status": "PASS",
            "severity": "MEDIUM",
            "finding": "Logging enabled",
            "remediation": "",
        },
    ]


@pytest.fixture
def api_config() -> dict[str, object]:
    return {"api_key": "test-api-key", "api_secret": "test-secret", "region": "us"}


class TestSecureframeExporter:
    def test_export_to_file(
        self,
        exporter: SecureframeExporter,
        sample_findings: list[dict[str, object]],
        metadata: dict[str, object],
        tmp_path: Path,
    ) -> None:
        result = exporter.export_to_file(sample_findings, metadata, tmp_path)
        assert result.format == "secureframe"
        assert result.record_count == 2
        assert len(result.output_files) == 1

        data = json.loads(result.output_files[0].read_text())
        assert data["platform"] == "secureframe"
        assert data["test_count"] == 2
        assert len(data["tests"]) == 2
        assert data["tests"][0]["passing"] is False
        assert data["tests"][0]["evidence_type"] == "fail"
        assert data["tests"][1]["passing"] is True
        assert data["tests"][1]["evidence_type"] == "pass"

    @pytest.mark.asyncio
    async def test_push_to_api_success(
        self,
        exporter: SecureframeExporter,
        sample_findings: list[dict[str, object]],
        metadata: dict[str, object],
        api_config: dict[str, object],
        tmp_path: Path,
    ) -> None:
        upload_response = httpx.Response(
            200,
            json={"id": "test-1"},
            request=httpx.Request("POST", "https://app.secureframe.com/api/tests"),
        )

        with (
            patch(
                "complyform.core.generators.evidence_export.secureframe.grc_request",
                new_callable=AsyncMock,
                return_value=upload_response,
            ),
            patch(
                "complyform.core.generators.evidence_export.secureframe._default_output_dir",
                return_value=tmp_path,
            ),
        ):
            result = await exporter.push_to_api(sample_findings, metadata, api_config)
            assert result.api_push_status == "success"
            assert result.record_count == 2

    def test_push_to_api_region_urls(self) -> None:
        """Verify all region URLs are defined."""
        assert "us" in SECUREFRAME_REGION_URLS
        assert "uk" in SECUREFRAME_REGION_URLS
        assert "eu" in SECUREFRAME_REGION_URLS
        assert SECUREFRAME_REGION_URLS["us"] == "https://app.secureframe.com/api"
        assert SECUREFRAME_REGION_URLS["uk"] == "https://app-uk.secureframe.com/api"
        assert SECUREFRAME_REGION_URLS["eu"] == "https://app-eu.secureframe.com/api"

    @pytest.mark.asyncio
    async def test_push_to_api_uses_region(
        self,
        exporter: SecureframeExporter,
        sample_findings: list[dict[str, object]],
        metadata: dict[str, object],
        tmp_path: Path,
    ) -> None:
        """Verify EU region uses correct base URL."""
        eu_config: dict[str, object] = {
            "api_key": "key",
            "api_secret": "secret",
            "region": "eu",
        }

        upload_response = httpx.Response(
            200,
            json={"id": "test-1"},
            request=httpx.Request("POST", "https://app-eu.secureframe.com/api/tests"),
        )

        call_urls: list[str] = []

        async def capture_grc_request(
            _client: object, _method: str, url: str, **_kwargs: object
        ) -> httpx.Response:
            call_urls.append(url)
            return upload_response

        with (
            patch(
                "complyform.core.generators.evidence_export.secureframe.grc_request",
                side_effect=capture_grc_request,
            ),
            patch(
                "complyform.core.generators.evidence_export.secureframe._default_output_dir",
                return_value=tmp_path,
            ),
        ):
            result = await exporter.push_to_api(sample_findings, metadata, eu_config)
            assert result.api_push_details is not None
            assert result.api_push_details.get("region") == "eu"
            assert (
                result.api_push_details.get("base_url")
                == "https://app-eu.secureframe.com/api"
            )
            # All calls should use EU URL
            for url in call_urls:
                assert "app-eu.secureframe.com" in url

    def test_push_to_api_pass_vs_fail_evidence_type(
        self,
        exporter: SecureframeExporter,
        sample_findings: list[dict[str, object]],
        metadata: dict[str, object],
        tmp_path: Path,
    ) -> None:
        """Verify evidence_type reflects pass/fail status."""
        result = exporter.export_to_file(sample_findings, metadata, tmp_path)
        data = json.loads(result.output_files[0].read_text())
        fail_test = data["tests"][0]
        pass_test = data["tests"][1]
        assert fail_test["evidence_type"] == "fail"
        assert fail_test["passing"] is False
        assert pass_test["evidence_type"] == "pass"
        assert pass_test["passing"] is True
