"""HistoryManager for persisting audit results to disk."""

import json
import logging
from datetime import datetime
from pathlib import Path
from typing import Any

from tools.workflow.state import WorkflowState

logger = logging.getLogger(__name__)

LENS_MAPPING = {
    "security_audit": "security",
    "a11y_audit": "a11y",
    "devops_audit": "devops",
    "principal_audit": "principal",
}


class HistoryManager:
    """Manager for saving audit snapshots to .optix/history/ directory."""

    VERSION = "1.0"

    def __init__(self, base_dir: Path) -> None:
        """Initialize the HistoryManager.

        Args:
            base_dir: Base directory for history storage (typically .optix/history/)
        """
        self.base_dir = Path(base_dir)

    def save_audit(self, state: WorkflowState) -> Path:
        """Save completed audit to history directory.

        Creates: .optix/history/YYYY-MM-DD_HH-MM-SS_<lens>/audit.json

        Args:
            state: The completed WorkflowState to persist

        Returns:
            Path to the created directory
        """
        snapshot = self._state_to_snapshot(state)
        timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
        lens = LENS_MAPPING.get(state.tool_name, state.tool_name)
        dir_name = f"{timestamp}_{lens}"
        audit_dir = self.base_dir / dir_name

        try:
            audit_dir.mkdir(parents=True, exist_ok=True)
            audit_file = audit_dir / "audit.json"
            with open(audit_file, "w", encoding="utf-8") as f:
                json.dump(snapshot, f, indent=2, default=str)
            logger.info(f"Saved audit history to {audit_file}")

            self._regenerate_history_viewer()

            return audit_dir
        except OSError as e:
            logger.error(f"Failed to save audit history: {e}")
            raise

    def _regenerate_history_viewer(self) -> None:
        """Regenerate history_viewer.html with latest audit data."""
        try:
            from tools.history.reader import HistoryReader
            from tools.view_history.html_generator import HistoryHtmlGenerator

            reader = HistoryReader(self.base_dir)
            summaries = reader.list_audits()

            audits = []
            for summary in summaries:
                full_audit = reader.get_audit(summary.dir_name)
                audits.append(full_audit if full_audit else summary.to_dict())

            optix_dir = self.base_dir.parent
            project_name = optix_dir.parent.name

            generator = HistoryHtmlGenerator(project_name, audits)
            html_path = optix_dir / "history_viewer.html"
            html_path.write_text(generator.generate(), encoding="utf-8")
            logger.debug(f"Regenerated history viewer at {html_path}")
        except Exception as e:
            logger.warning(f"Failed to regenerate history viewer: {e}")

    def _state_to_snapshot(self, state: WorkflowState) -> dict[str, Any]:
        """Convert WorkflowState to JSON-serializable snapshot.

        Args:
            state: The WorkflowState to convert

        Returns:
            Dictionary suitable for JSON serialization
        """
        consolidated = state.consolidated
        by_severity = {"critical": 0, "high": 0, "medium": 0, "low": 0, "info": 0}
        findings_list = []
        files_checked = []
        total_findings = 0

        if consolidated:
            if hasattr(consolidated, "get_findings_by_severity"):
                severity_data = consolidated.get_findings_by_severity()
                for severity, items in severity_data.items():
                    if isinstance(items, list):
                        by_severity[severity] = len(items)
            if hasattr(consolidated, "issues_found"):
                total_findings = len(consolidated.issues_found)
                findings_list = self._format_findings(consolidated.issues_found)
            if hasattr(consolidated, "files_checked"):
                files_checked = list(consolidated.files_checked)

        duration_seconds = None
        if state.step_history:
            first_step = state.step_history[0]
            last_step = state.step_history[-1]
            if hasattr(first_step, "timestamp") and hasattr(last_step, "timestamp"):
                duration = last_step.timestamp - first_step.timestamp
                duration_seconds = int(duration.total_seconds())

        project_name = None
        if state.project_root_path:
            project_name = Path(state.project_root_path).name

        lens = LENS_MAPPING.get(state.tool_name, state.tool_name)

        return {
            "version": self.VERSION,
            "timestamp": datetime.now().isoformat(),
            "lens": lens,
            "continuation_id": state.continuation_id,
            "project": {
                "name": project_name,
                "root_path": state.project_root_path,
            },
            "summary": {
                "total_findings": total_findings,
                "by_severity": by_severity,
                "files_examined": len(files_checked),
                "steps_completed": len(state.step_history),
                "duration_seconds": duration_seconds,
            },
            "findings": findings_list,
            "step_history": self._format_step_history(state.step_history),
            "files_checked": files_checked,
            "confidence": (
                state.get_latest_confidence().value
                if hasattr(state, "get_latest_confidence")
                else "exploring"
            ),
        }

    def _format_findings(self, issues: list[dict[str, Any]]) -> list[dict[str, Any]]:
        """Format findings for the snapshot.

        Args:
            issues: List of issue dictionaries

        Returns:
            Formatted list of findings
        """
        formatted = []
        for issue in issues:
            finding = {
                "id": issue.get("finding_id", ""),
                "severity": issue.get("severity", "info"),
                "category": issue.get("category", ""),
                "description": issue.get("description", ""),
                "affected_files": issue.get("affected_files", []),
                "remediation": issue.get("remediation", ""),
            }
            formatted.append(finding)
        return formatted

    def _format_step_history(self, steps: list) -> list[dict[str, Any]]:
        """Format step history for the snapshot.

        Args:
            steps: List of StepHistory objects

        Returns:
            Formatted list of step records
        """
        formatted = []
        for step in steps:
            record = {
                "step_number": step.step_number,
                "name": step.step_content,
                "files_examined": step.files_checked,
                "findings_count": 0,
                "timestamp": (
                    step.timestamp.isoformat()
                    if hasattr(step, "timestamp") and step.timestamp
                    else None
                ),
            }
            formatted.append(record)
        return formatted
