"""MCP tool implementation for SARIF export."""

import json
import sys
from pathlib import Path
from typing import Optional

from tools.export_sarif.generator import SarifGenerator
from tools.export_sarif.models import SarifExportError, SarifExportResponse
from tools.export_sarif.numbering import allocate_sarif_number
from tools.generate_report.file_operations import atomic_write_file
from tools.generate_report.models import AuditLens
from tools.workflow.state import WorkflowState, WorkflowStateManager


def create_optix_directory(project_root: Path) -> Path:
    """Create the .optix directory if it doesn't exist.

    Args:
        project_root: Project root directory path

    Returns:
        Path to the .optix directory

    Raises:
        PermissionError: If permission denied when creating directory
        OSError: If directory creation fails for other reasons
    """
    optix_dir = project_root / ".optix"

    try:
        optix_dir.mkdir(parents=True, exist_ok=True)
        return optix_dir
    except PermissionError as e:
        raise PermissionError(
            f"Failed to create .optix directory: Permission denied at {optix_dir}. "
            f"Please check directory permissions or run with appropriate privileges."
        ) from e
    except OSError as e:
        raise OSError(f"Failed to create .optix directory at {optix_dir}: {e}") from e


class ExportSarifTool:
    """MCP tool for exporting audit findings to SARIF 2.1.0 format."""

    def __init__(self) -> None:
        self._state_manager = WorkflowStateManager()

    @property
    def name(self) -> str:
        return "export_sarif"

    @property
    def description(self) -> str:
        return (
            "Export audit findings to SARIF 2.1.0 format for integration with "
            "GitHub Code Scanning, VS Code, and other security toolchains."
        )

    def execute(
        self,
        continuation_id: Optional[str] = None,
        output_path: Optional[str] = None,
    ) -> SarifExportResponse | SarifExportError:
        """Execute the SARIF export tool.

        Args:
            continuation_id: Optional UUID of specific workflow to use.
                If omitted, uses most recent workflow from WorkflowStateManager.
            output_path: Optional custom path for SARIF file.
                If omitted, creates numbered file in .optix/ directory.

        Returns:
            SarifExportResponse on success, SarifExportError on failure
        """
        try:
            state, lens, project_root = self._get_audit_context(continuation_id)

            if not state.is_finished:
                return SarifExportError(
                    error="Workflow must be completed (is_finished=true) before exporting SARIF",
                    error_type="WorkflowIncomplete",
                )

            generator = SarifGenerator(state, lens)
            sarif_data = generator.generate()

            if output_path:
                sarif_path = Path(output_path)
                sarif_path.parent.mkdir(parents=True, exist_ok=True)
            else:
                optix_dir = create_optix_directory(project_root)
                _, sarif_path = allocate_sarif_number(optix_dir, lens)

            sarif_content = json.dumps(sarif_data, indent=2)
            atomic_write_file(sarif_path, sarif_content)

            findings_count = len(sarif_data.get("runs", [{}])[0].get("results", []))
            rules_count = generator.get_rules_count()

            return SarifExportResponse(
                success=True,
                sarif_file_path=sarif_path,
                findings_count=findings_count,
                lens=lens,
                message=f"SARIF exported successfully to: {sarif_path}",
                rules_count=rules_count,
            )

        except ValueError as e:
            error_msg = str(e)
            if "Unknown tool name" in error_msg:
                return SarifExportError(
                    error=error_msg,
                    error_type="UnknownLens",
                )
            if "No completed audit" in error_msg or "No audit workflow" in error_msg:
                return SarifExportError(
                    error=error_msg,
                    error_type="NoAuditFound",
                )
            return SarifExportError(
                error=error_msg,
                error_type="GeneralError",
            )

        except PermissionError as e:
            return SarifExportError(
                error=str(e),
                error_type="PermissionDenied",
            )

        except RuntimeError as e:
            error_msg = str(e)
            if "retry attempts" in error_msg.lower():
                return SarifExportError(
                    error=error_msg,
                    error_type="RetryExhausted",
                )
            return SarifExportError(
                error=error_msg,
                error_type="GeneralError",
            )

        except OSError as e:
            return SarifExportError(
                error=f"File system error: {e}",
                error_type="FileSystemError",
            )

        except Exception as e:
            print(f"[ERROR] Unexpected error in export_sarif: {e}", file=sys.stderr)
            return SarifExportError(
                error=f"Unexpected error: {e}",
                error_type="GeneralError",
            )

    def _get_audit_context(
        self, continuation_id: Optional[str]
    ) -> tuple[WorkflowState, AuditLens, Path]:
        """Retrieve workflow state, audit lens and project root."""
        if continuation_id:
            state = self._state_manager.get(continuation_id)
            if state is None:
                raise ValueError(
                    f"No audit workflow found with continuation_id: {continuation_id}. "
                    "Please ensure you completed an audit workflow first."
                )
        else:
            state = self._get_most_recent_finished()
            if state is None:
                workflows = self._state_manager._workflows
                if not workflows:
                    raise ValueError(
                        "No completed audit found. Please run an audit "
                        "(security_audit, a11y_audit, principal_audit, or devops_audit) "
                        "before exporting SARIF"
                    )
                state = max(
                    workflows.values(),
                    key=lambda w: (w.updated_at, -w.created_at.timestamp()),
                )

        tool_name = state.tool_name
        lens = AuditLens.from_tool_name(tool_name)

        if state.project_root_path:
            project_root = Path(state.project_root_path)
        else:
            project_root = Path.cwd()

        return state, lens, project_root

    def _get_most_recent_finished(self) -> Optional[WorkflowState]:
        """Get the most recently finished workflow."""
        workflows = self._state_manager._workflows
        finished = [w for w in workflows.values() if w.is_finished]
        if not finished:
            return None
        return max(finished, key=lambda w: w.updated_at)
