"""Export scan results in various formats (JSON, SARIF, plain text)."""

from __future__ import annotations

import json
from pathlib import Path
from typing import List

from .. import __version__
from .runner import ScanResult


def _validate_output_path(output_path: str | Path) -> Path:
    """Validate that the output path is safe (no path traversal)."""
    p = Path(output_path).resolve()
    path_str = str(p)
    # Ensure the path doesn't escape to sensitive system directories
    # Include /private/* variants for macOS where /etc -> /private/etc
    sensitive_dirs = [
        "/etc", "/usr", "/bin", "/sbin", "/sys", "/proc",
        "/private/etc",
    ]
    for d in sensitive_dirs:
        if path_str.startswith(d + "/") or path_str == d:
            raise ValueError(f"Output path not allowed: {p}")
    # Ensure parent directory exists
    if not p.parent.exists():
        raise FileNotFoundError(f"Parent directory does not exist: {p.parent}")
    return p


def export_json(results: List[ScanResult], output_path: str | Path | None = None) -> str:
    """Export results as JSON. Optionally write to a file."""
    data = {
        "version": "1.0",
        "scans": [r.to_dict() for r in results],
    }
    text = json.dumps(data, indent=2)
    if output_path:
        _validate_output_path(output_path).write_text(text)
    return text


def export_text(results: List[ScanResult]) -> str:
    """Export results as human-readable plain text."""
    lines: List[str] = []

    for result in results:
        lines.append(f"Platform: {result.platform.value.upper()} ({result.project_type})")
        lines.append(f"Scan Time: {result.scan_time_seconds:.1f}s")
        lines.append(f"FAIL: {result.fail_count}  WARN: {result.warn_count}  INFO: {result.info_count}")
        lines.append("")

        for f in result.findings:
            lines.append(f"[{f.severity}] {f.rule_id} — {f.message}")
            lines.append(f"       Fix: {f.fix}")
            if f.reference:
                lines.append(f"       Ref: {f.reference}")
            lines.append("")

    return "\n".join(lines)


def export_sarif(results: List[ScanResult], output_path: str | Path | None = None) -> str:
    """Export results in SARIF 2.1 format for CI/CD integration."""
    rules = []
    sarif_results = []

    for result in results:
        for f in result.findings:
            rule_entry = {
                "id": f.rule_id,
                "shortDescription": {"text": f.message},
                "helpUri": f.reference if f.reference.startswith("http") else "",
                "properties": {"severity": f.severity},
            }
            rules.append(rule_entry)

            level_map = {"FAIL": "error", "WARN": "warning", "INFO": "note"}
            sarif_results.append({
                "ruleId": f.rule_id,
                "level": level_map.get(f.severity, "note"),
                "message": {"text": f"{f.message}\nFix: {f.fix}"},
            })

    sarif = {
        "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/sarif-2.1/schema/sarif-schema-2.1.0.json",
        "version": "2.1.0",
        "runs": [
            {
                "tool": {
                    "driver": {
                        "name": "Oncecheck",
                        "version": __version__,
                        "rules": rules,
                    }
                },
                "results": sarif_results,
            }
        ],
    }

    text = json.dumps(sarif, indent=2)
    if output_path:
        _validate_output_path(output_path).write_text(text)
    return text
