"""
Artifact storage and retrieval for test results.
"""

import shutil
from pathlib import Path
from typing import Optional
from dataclasses import dataclass


@dataclass
class TestArtifact:
    """Test artifact (video, screenshot, trace, etc.)."""
    type: str  # "video", "screenshot", "trace", "log"
    filename: str
    path: str
    size: int
    mimetype: str
    url: str  # Streaming endpoint


class ArtifactStore:
    """Manage test artifacts."""

    def __init__(self, artifacts_dir: Path):
        self.artifacts_dir = artifacts_dir
        self.videos_dir = artifacts_dir / "videos"
        self.screenshots_dir = artifacts_dir / "screenshots"
        self.traces_dir = artifacts_dir / "traces"

        # Ensure directories exist
        self.videos_dir.mkdir(parents=True, exist_ok=True)
        self.screenshots_dir.mkdir(parents=True, exist_ok=True)
        self.traces_dir.mkdir(parents=True, exist_ok=True)

    def store_artifact(
        self,
        source_path: Path,
        run_id: str,
        artifact_type: str
    ) -> Optional[TestArtifact]:
        """
        Store an artifact and return its metadata.

        Args:
            source_path: Path to the source file
            run_id: Test run ID
            artifact_type: Type of artifact (video, screenshot, trace)

        Returns:
            TestArtifact metadata or None if storage fails
        """
        if not source_path.exists():
            return None

        # Determine destination directory
        if artifact_type == "video":
            dest_dir = self.videos_dir
            mimetype = "video/webm"
        elif artifact_type == "screenshot":
            dest_dir = self.screenshots_dir
            mimetype = "image/png"
        elif artifact_type == "trace":
            dest_dir = self.traces_dir
            mimetype = "application/zip"
        else:
            # Unknown type, store in root artifacts dir
            dest_dir = self.artifacts_dir
            mimetype = "application/octet-stream"

        # Create run-specific subdirectory
        run_dir = dest_dir / run_id
        run_dir.mkdir(parents=True, exist_ok=True)

        # Copy file
        dest_path = run_dir / source_path.name
        try:
            shutil.copy2(source_path, dest_path)
        except Exception:
            return None

        # Build streaming URL
        url = f"/tools/tester/api/artifact/{run_id}/{source_path.name}"

        return TestArtifact(
            type=artifact_type,
            filename=source_path.name,
            path=str(dest_path),
            size=dest_path.stat().st_size,
            mimetype=mimetype,
            url=url,
        )

    def get_artifact(self, run_id: str, filename: str) -> Optional[Path]:
        """
        Retrieve an artifact file.

        Args:
            run_id: Test run ID
            filename: Artifact filename

        Returns:
            Path to artifact file or None if not found
        """
        # Search in all artifact directories
        for artifact_dir in [self.videos_dir, self.screenshots_dir, self.traces_dir]:
            artifact_path = artifact_dir / run_id / filename
            if artifact_path.exists():
                return artifact_path

        # Check root artifacts dir
        artifact_path = self.artifacts_dir / run_id / filename
        if artifact_path.exists():
            return artifact_path

        return None

    def list_artifacts(self, run_id: str) -> list[TestArtifact]:
        """
        List all artifacts for a test run.

        Args:
            run_id: Test run ID

        Returns:
            List of TestArtifact metadata
        """
        artifacts = []

        # Search in all artifact directories
        type_mapping = {
            self.videos_dir: ("video", "video/webm"),
            self.screenshots_dir: ("screenshot", "image/png"),
            self.traces_dir: ("trace", "application/zip"),
        }

        for artifact_dir, (artifact_type, mimetype) in type_mapping.items():
            run_dir = artifact_dir / run_id
            if not run_dir.exists():
                continue

            for artifact_file in run_dir.iterdir():
                if artifact_file.is_file():
                    artifacts.append(TestArtifact(
                        type=artifact_type,
                        filename=artifact_file.name,
                        path=str(artifact_file),
                        size=artifact_file.stat().st_size,
                        mimetype=mimetype,
                        url=f"/tools/tester/api/artifact/{run_id}/{artifact_file.name}",
                    ))

        return artifacts

    def cleanup_old_artifacts(self, keep_recent: int = 10):
        """
        Clean up old artifact directories, keeping only the most recent runs.

        Args:
            keep_recent: Number of recent runs to keep
        """
        # Get all run directories sorted by modification time
        all_runs = []

        for artifact_dir in [self.videos_dir, self.screenshots_dir, self.traces_dir]:
            for run_dir in artifact_dir.iterdir():
                if run_dir.is_dir():
                    all_runs.append(run_dir)

        # Sort by modification time (newest first)
        all_runs.sort(key=lambda p: p.stat().st_mtime, reverse=True)

        # Keep only the most recent
        for old_run in all_runs[keep_recent:]:
            try:
                shutil.rmtree(old_run)
            except Exception:
                pass  # Ignore errors during cleanup
