from __future__ import annotations

import os
from dataclasses import dataclass
from enum import Enum
from pathlib import Path
from typing import Iterable, List, Optional


class SafetyRating(str, Enum):
    GREEN = "GREEN"
    YELLOW = "YELLOW"
    ORANGE = "ORANGE"
    RED = "RED"


@dataclass
class CleanupCandidate:
    category: str
    path: str
    size: int
    reason: str
    confidence: int
    safety_rating: SafetyRating
    recommended_action: str = "review"


class CleanupEngine:
    """Scan common disposable locations and classify safe cleanup candidates."""

    def __init__(self, base_paths: Optional[Iterable[str]] = None):
        self.base_paths = [str(Path(p)) for p in (base_paths or self._default_paths())]

    @staticmethod
    def _default_paths() -> List[str]:
        candidates = []
        env_vars = ["TEMP", "TMP", "LOCALAPPDATA"]
        for name in env_vars:
            value = os.environ.get(name)
            if value:
                candidates.append(value)
        candidates.extend([r"C:\Windows\Temp", r"C:\Temp"])
        return candidates

    def scan_candidates(self) -> List[CleanupCandidate]:
        findings: List[CleanupCandidate] = []
        seen = set()

        for root in self.base_paths:
            path = Path(root)
            if not path.exists():
                continue
            for child in path.rglob("*"):
                if not child.is_file():
                    continue
                if str(child) in seen:
                    continue
                seen.add(str(child))

                size = child.stat().st_size
                category = self._classify_candidate(child)
                if category is None:
                    continue
                reasons = self._reason_for(child, category)
                confidence = self._confidence(category, size)
                safety = self._safety_rating(category, confidence)
                findings.append(
                    CleanupCandidate(
                        category=category,
                        path=str(child),
                        size=size,
                        reason=reasons,
                        confidence=confidence,
                        safety_rating=safety,
                        recommended_action="delete" if safety == SafetyRating.GREEN else "review",
                    )
                )

        return findings

    @staticmethod
    def _classify_candidate(path: Path) -> Optional[str]:
        name = path.name.lower()
        if name.endswith(".tmp") or name.endswith(".temp"):
            return "temporary_file"
        if "cache" in name.lower() or "cache" in str(path.parent).lower():
            return "application_cache"
        if name.endswith(".log"):
            return "stale_log"
        if "crash" in name.lower() or "dump" in name.lower():
            return "crash_dump"
        return None

    @staticmethod
    def _reason_for(path: Path, category: str) -> str:
        if category == "temporary_file":
            return "Temporary file created for short-lived application state"
        if category == "application_cache":
            return "Cached data exceeded a disposable cleanup threshold"
        if category == "stale_log":
            return "Log file likely no longer needed for live operations"
        if category == "crash_dump":
            return "Crash dump from previous application failure"
        return f"Candidate flagged by {path.name} classification"

    @staticmethod
    def _confidence(category: str, size: int) -> int:
        if category == "temporary_file":
            return 86
        if category == "application_cache":
            return 74
        if category == "stale_log":
            return 70
        if category == "crash_dump":
            return 82
        return 50

    @staticmethod
    def _safety_rating(category: str, confidence: int) -> SafetyRating:
        if category in {"temporary_file", "stale_log", "crash_dump"}:
            return SafetyRating.GREEN
        if category == "application_cache":
            return SafetyRating.YELLOW
        return SafetyRating.ORANGE
