"""File-based report storage implementation."""

from pathlib import Path
from typing import Dict, Any, List, Optional
from loguru import logger

from .base import ReportStorage
from ..config.paths import get_research_outputs_directory


class FileReportStorage(ReportStorage):
    """Store reports as files on disk."""

    def __init__(self, base_dir: Optional[Path] = None):
        """Initialize file storage.

        Args:
            base_dir: Base directory for storing reports.
                     If None, uses default research outputs directory.
        """
        self.base_dir = base_dir or get_research_outputs_directory()
        self.base_dir.mkdir(parents=True, exist_ok=True)

    def _get_report_path(self, research_id: str) -> Path:
        """Get the file path for a report."""
        candidate = (self.base_dir / f"{research_id}.md").resolve()
        if not candidate.is_relative_to(self.base_dir.resolve()):
            raise ValueError(
                f"Path traversal attempt with research_id: {research_id!r}"
            )
        return candidate

    def _get_metadata_path(self, research_id: str) -> Path:
        """Get the file path for report metadata."""
        candidate = (self.base_dir / f"{research_id}_metadata.json").resolve()
        if not candidate.is_relative_to(self.base_dir.resolve()):
            raise ValueError(
                f"Path traversal attempt with research_id: {research_id!r}"
            )
        return candidate

    def save_report(
        self,
        research_id: str,
        content: str,
        metadata: Optional[Dict[str, Any]] = None,
        username: Optional[str] = None,
    ) -> bool:
        """Save report to file."""
        try:
            from ..security.file_write_verifier import (
                write_file_verified,
                write_json_verified,
            )

            report_path = self._get_report_path(research_id)

            # Save content
            write_file_verified(
                report_path,
                content,
                "report.enable_file_backup",
                context="file storage backup",
            )

            # Save metadata if provided
            if metadata:
                metadata_path = self._get_metadata_path(research_id)
                write_json_verified(
                    metadata_path,
                    metadata,
                    "report.enable_file_backup",
                    context="file storage metadata",
                )

            logger.info(
                f"Saved report for research {research_id} to {report_path}"
            )
            return True

        except Exception:
            logger.exception("Error saving report to file")
            return False

    def get_report(
        self, research_id: str, username: Optional[str] = None
    ) -> Optional[str]:
        """Get report from file."""
        try:
            report_path = self._get_report_path(research_id)

            if not report_path.exists():
                return None

            with open(report_path, "r", encoding="utf-8") as f:
                return f.read()

        except Exception:
            logger.exception("Error reading report from file")
            return None

    def get_report_with_metadata(
        self, research_id: str, username: Optional[str] = None
    ) -> Optional[Dict[str, Any]]:
        """Get report with metadata from files."""
        try:
            content = self.get_report(research_id)
            if not content:
                return None

            result = {"content": content, "metadata": {}}

            # Try to load metadata
            metadata_path = self._get_metadata_path(research_id)
            if metadata_path.exists():
                import json

                with open(metadata_path, "r", encoding="utf-8") as f:
                    result["metadata"] = json.load(f)

            return result

        except Exception:
            logger.exception("Error getting report with metadata")
            return None

    def list_reports(
        self, username: Optional[str] = None
    ) -> List[Dict[str, Any]]:
        """List reports from file system."""
        try:
            from datetime import datetime, timezone

            reports = []
            for report_path in self.base_dir.glob("*.md"):
                research_id = report_path.stem
                metadata = self._load_metadata(research_id)
                reports.append(
                    {
                        "id": research_id,
                        "query": metadata.get("query") if metadata else None,
                        "mode": metadata.get("mode", "unknown")
                        if metadata
                        else "unknown",
                        "created_at": datetime.fromtimestamp(
                            report_path.stat().st_mtime, tz=timezone.utc
                        ).isoformat(),
                        "completed_at": metadata.get("completed_at")
                        if metadata
                        else None,
                    }
                )
            return reports
        except Exception:
            logger.exception("Error listing reports from file system")
            return []

    def _load_metadata(self, research_id: str) -> Optional[Dict[str, Any]]:
        """Load metadata JSON for a report if it exists."""
        try:
            metadata_path = self._get_metadata_path(research_id)
            if metadata_path.exists():
                import json

                with open(metadata_path, "r", encoding="utf-8") as f:
                    return json.load(f)
        except Exception:
            logger.debug(f"Failed to load metadata for {research_id}")
        return None

    def delete_report(
        self, research_id: str, username: Optional[str] = None
    ) -> bool:
        """Delete report files."""
        try:
            report_path = self._get_report_path(research_id)
            metadata_path = self._get_metadata_path(research_id)

            deleted = False

            if report_path.exists():
                report_path.unlink()
                deleted = True

            if metadata_path.exists():
                metadata_path.unlink()

            return deleted

        except Exception:
            logger.exception("Error deleting report files")
            return False

    def report_exists(
        self, research_id: str, username: Optional[str] = None
    ) -> bool:
        """Check if report file exists."""
        return self._get_report_path(research_id).exists()
