"""Tests for batch export command — Phase 20c."""

from __future__ import annotations

import json
from typing import TYPE_CHECKING, Any

import pytest

from complyform.core.batch.executor import run_batch_operation
from complyform.core.batch.manifest import BatchManifest, BatchProject

if TYPE_CHECKING:
    from pathlib import Path


def _make_manifest(n: int = 3) -> BatchManifest:
    projects = [
        BatchProject(
            label=f"proj-{i}",
            cloud="aws",
            state=f"/tmp/state-{i}.tfstate",
        )
        for i in range(n)
    ]
    return BatchManifest(projects=projects)


def _file_only_fn(
    proj: BatchProject,
) -> dict[str, Any]:
    return {
        "status": "success",
        "format": "scc-json",
        "record_count": 10,
        "output_files": [f"/tmp/{proj.label}/export.json"],
        "file_only": True,
    }


def _partial_fail_fn(
    proj: BatchProject,
) -> dict[str, Any]:
    if proj.label == "proj-2":
        msg = "export format unsupported"
        raise ValueError(msg)
    return {
        "status": "success",
        "format": "grc-json",
        "record_count": 5,
    }


class TestBatchExportFileOnly:
    def test_batch_export_file_only(self, tmp_path: Path) -> None:
        """Global --file-only applies to all projects."""
        manifest = _make_manifest(3)
        result = run_batch_operation(manifest, "export", _file_only_fn, tmp_path)

        assert result.total == 3
        assert result.succeeded == 3
        assert result.failed == 0
        for entry in result.results:
            assert entry["status"] == "success"
            assert entry["file_only"] is True


class TestBatchExportPartialFailure:
    def test_batch_export_partial_failure(self, tmp_path: Path) -> None:
        """1 of 3 fails — others still complete."""
        manifest = _make_manifest(3)
        result = run_batch_operation(manifest, "export", _partial_fail_fn, tmp_path)

        assert result.total == 3
        assert result.succeeded == 2
        assert result.failed == 1
        assert result.results[2]["status"] == "failed"
        assert "unsupported" in result.results[2]["error"]


class TestBatchExportTierGate:
    def test_batch_export_tier_gate(self) -> None:
        """evidence_export_batch required — Pro rejected."""
        from complyform.core.auth.tier_enforcement import (
            TierInfo,
            check_feature,
        )
        from complyform.core.errors import FeatureNotAvailableError

        tier_info = TierInfo(
            tier="pro",
            assess_frameworks=[],
            remediate_frameworks=[],
            features=["evidence_export"],
            scan_sources=[],
            project_limit=None,
            batch_limit=None,
            discover_limit=None,
            expires_at=None,
        )
        with pytest.raises(FeatureNotAvailableError):
            check_feature("evidence_export_batch", tier_info)


class TestBatchExportSummaryJson:
    def test_batch_export_summary_json(self, tmp_path: Path) -> None:
        """Summary JSON follows schema_version 1 / D.4.12."""
        manifest = _make_manifest(2)
        run_batch_operation(manifest, "export", _file_only_fn, tmp_path)

        summary_path = tmp_path / "batch-export-summary.json"
        assert summary_path.exists()

        data = json.loads(summary_path.read_text(encoding="utf-8"))
        assert data["schema_version"] == 1
        assert data["operation"] == "export"
        assert data["total"] == 2
        assert data["succeeded"] == 2
        assert data["failed"] == 0
        assert len(data["results"]) == 2
        assert "timestamp" in data
