"""Generic GRC normalized JSON exporter (Team+ tier).

Produces a universal GRC JSON format for import into any GRC platform.
"""

from __future__ import annotations

import hashlib
import json
from typing import TYPE_CHECKING

from complyform import __version__
from complyform.core.generators.evidence_export.base import (
    EvidenceExporter,
    ExportResult,
)

if TYPE_CHECKING:
    from pathlib import Path


class GrcJsonExporter(EvidenceExporter):
    """Export findings as normalized GRC JSON."""

    FORMAT_ID = "grc-json"
    TIER_FEATURE = "evidence_export_native"

    def export_to_file(
        self,
        findings: list[dict[str, object]],
        metadata: dict[str, object],
        output_dir: Path,
        project_label: str | None = None,
    ) -> ExportResult:
        output_dir.mkdir(parents=True, exist_ok=True)
        scan_id = str(metadata.get("scan_id", "unknown"))
        timestamp = str(metadata.get("timestamp", ""))
        cloud = str(metadata.get("cloud", ""))

        output_path = output_dir / f"complyform-grc-{scan_id}.json"
        instructions_path = output_dir / "grc-json-import-instructions.md"

        # Build findings list
        grc_findings: list[dict[str, object]] = []
        controls_map: dict[str, dict[str, object]] = {}

        for finding in findings:
            control_id = str(finding.get("control_id", ""))
            framework = str(finding.get("framework", ""))
            resource_address = str(finding.get("resource_address", ""))
            resource_hash = hashlib.sha256(resource_address.encode()).hexdigest()[:8]
            status = str(finding.get("status", "FAIL"))
            severity = str(finding.get("severity", "MEDIUM"))

            finding_id = f"cf-{framework}-{control_id}-{resource_hash}"

            grc_findings.append(
                {
                    "finding_id": finding_id,
                    "control_id": control_id,
                    "framework": framework,
                    "resource_address": resource_address,
                    "resource_type": str(finding.get("resource_type", "")),
                    "status": status,
                    "severity": severity,
                    "finding": str(finding.get("finding", "")),
                    "remediation": str(finding.get("remediation", "")),
                    "checkov_id": finding.get("checkov_id"),
                    "native_ids": finding.get("native_ids"),
                    "cross_mappings": finding.get("cross_mappings"),
                }
            )

            # Aggregate controls
            ctrl_key = f"{framework}:{control_id}"
            if ctrl_key not in controls_map:
                controls_map[ctrl_key] = {
                    "framework": framework,
                    "control_id": control_id,
                    "total_findings": 0,
                    "pass_count": 0,
                    "fail_count": 0,
                }
            entry = controls_map[ctrl_key]
            entry["total_findings"] = int(entry["total_findings"]) + 1  # type: ignore[call-overload]
            if status == "PASS":
                entry["pass_count"] = int(entry["pass_count"]) + 1  # type: ignore[call-overload]
            else:
                entry["fail_count"] = int(entry["fail_count"]) + 1  # type: ignore[call-overload]

        envelope = {
            "schema_version": 1,
            "tool": "complyform",
            "tool_version": __version__,
            "metadata": {
                "scan_id": scan_id,
                "timestamp": timestamp,
                "cloud": cloud,
                "project_label": project_label,
            },
            "summary": {
                "total_findings": len(grc_findings),
                "total_controls": len(controls_map),
                "frameworks": list({str(f.get("framework", "")) for f in findings}),
            },
            "findings": grc_findings,
            "controls_evaluated": list(controls_map.values()),
        }

        output_path.write_text(json.dumps(envelope, indent=2), encoding="utf-8")

        instructions = _GRC_INSTRUCTIONS.format(
            filename=output_path.name,
            finding_count=len(grc_findings),
            control_count=len(controls_map),
        )
        instructions_path.write_text(instructions, encoding="utf-8")

        return ExportResult(
            format=self.FORMAT_ID,
            output_files=[output_path, instructions_path],
            record_count=len(grc_findings),
        )


_GRC_INSTRUCTIONS = """\
# GRC JSON Import Instructions

## File: {filename}

Findings: {finding_count}
Controls: {control_count}

## Schema

The file follows ComplyForm GRC JSON schema v1.

## Import Steps

1. Parse the JSON file
2. Use `findings[]` for individual resource-level results
3. Use `controls_evaluated[]` for control-level aggregation
4. Match controls to your GRC platform's control framework

## Finding ID Format

`cf-{{framework}}-{{control_id}}-{{resource_hash_8}}`
"""
