from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Any


@dataclass
class ResolvedSource:
    """Represents a resolved source for an asset."""
    source_type: str  # "huggingface", "civitai", "direct_url", etc.
    repo: str  # Repository ID or URL
    file: str  # Filename within the repository
    download_url: str | None = None  # Direct download URL if available
    sha256: str | None = None  # SHA-256 hash if available
    file_size_bytes: int | None = None  # File size in bytes if available


@dataclass
class ResolutionResult:
    """Represents the result of attempting to resolve an asset."""
    input_name: str
    resolved_name: str
    source: ResolvedSource | None
    confidence: str
    error: str | None = None
    asset_type: str = "other"

class BaseSource(ABC):
    """Abstract base class for asset resolution sources."""
    
    @property
    @abstractmethod
    def name(self) -> str:
        """Returns the name of this source (e.g., 'huggingface', 'civitai')."""
        pass
    
    @abstractmethod
    def search(self, filename: str, asset_type: str) -> list[ResolutionResult]:
        """
        Search for an asset by filename and type.
        
        Args:
            filename: The asset filename to search for
            asset_type: The type of asset (e.g., 'checkpoints', 'loras')
            
        Returns:
            List of ResolutionResult objects, sorted by confidence (highest first)
        """
        pass
    
    @abstractmethod
    def is_available(self, config: dict[str, Any]) -> bool:
        """
        Check if this source is available/configured.
        
        Args:
            config: Configuration dictionary
            
        Returns:
            True if the source can be used, False otherwise
        """
        pass
