from typing import List, Optional
from datetime import date
from cvs_manager.models import ExperienceType, LanguageProficiency
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import and_, or_
from ..repositories import CandidateRepository
from ..models import Candidate
from ..schemas import CandidateFlat
from .dto import CandidateFilterDTO

class FilterService:
    def __init__(self, session: AsyncSession):
        self.candidate_repo = CandidateRepository(session)

    async def filter_candidates(self, filters: CandidateFilterDTO) -> List[CandidateFlat]:
        """
        Filters candidates based on the provided criteria.
        Converts high-level DTO filters to database queries.
        """
        # Convert DTO filters to repository-compatible format
        repo_filters = self._build_repository_filters(filters)
        
        # Define which relationships to load based on filters
        relationships = self._get_required_relationships(filters)
        
        return await self.candidate_repo.get_all(
            filters=repo_filters,
            relationships=relationships
        )

    def _build_repository_filters(self, filters: CandidateFilterDTO) -> dict:
        """Converts DTO filters to SQLAlchemy-compatible filters"""
        repo_filters = {}
        
        # Age range (assuming birth_date field exists)
        if filters.age_range:
            min_age, max_age = filters.age_range
            repo_filters.update({
                "birth_date__lte": date.today().replace(year=date.today().year - min_age),
                "birth_date__gte": date.today().replace(year=date.today().year - max_age)
            })
        
        # Creation date
        if filters.created_at:
            repo_filters["created_at"] = filters.created_at
        
        # Rating
        if filters.rating:
            repo_filters["rating__gte"] = filters.rating
        
        # Languages (requires relationship filtering)
        if filters.languages:
            repo_filters["languages__name__in"] = filters.languages
        
        # Skills (search in experiences)
        if filters.skills:
            repo_filters["experiences__key_skills__contains"] = filters.skills
        
        # Experience type
        if filters.experience:
            repo_filters["experiences__type"] = filters.experience
        
        # Employment type
        if filters.employment:
            repo_filters["employment"] = filters.employment
            
        return repo_filters

    def _get_required_relationships(self, filters: CandidateFilterDTO) -> List[str]:
        """Determines which relationships to eager load based on filters"""
        relationships = []
        
        if filters.languages or any(f for f in filters.dict() if f.startswith('languages_')):
            relationships.append("languages")
            
        if filters.skills or filters.experience:
            relationships.append("experiences")
            
        return relationships

    async def get_filter_options(self) -> dict:
        """Returns available filter options for UI"""
        return {
            "experience_types": [e.value for e in ExperienceType],
            "employment_types": ["Full-time", "Part-time", "Contract", "Internship"],
            "language_proficiencies": [lp.value for lp in LanguageProficiency]
        } from typing import List, Optional
from pydantic import BaseModel, Field, validator
from datetime import date

class CandidateFilterDTO(BaseModel):
    age_range: Optional[List[int]] = Field(None, description="Age range as [min, max], e.g. [25, 40]")
    created_at: Optional[date] = Field(None, description="Filter candidates created on this date")
    rating: Optional[int] = Field(None, ge=1, le=5, description="Minimum rating between 1 and 5")
    languages: Optional[List[str]] = Field(None, description="Programming languages like Python, Java, etc.")
    skills: Optional[List[str]] = Field(None, description="Skills like Django, React, etc.")
    experience: Optional[str] = Field(None, description="Experience type: Internship, Full-time, etc.")
    employment: Optional[str] = Field(None, description="Employment type: Full-time, Part-time, etc.")

    @validator("age_range")
    def validate_age_range(cls, v):
        if v:
            if len(v) != 2:
                raise ValueError("age_range must contain exactly two integers: [min_age, max_age]")
            if not all(0 <= age <= 100 for age in v):
                raise ValueError("Each age must be between 0 and 100")
        return v
async def get_all(
        self, 
        filters: Optional[Dict[str, Any]] = None,
        relationships: Optional[List[str]] = None
    ) -> List[CandidateFlat]:
        """The ONLY get_all implementation needed across all repos"""
        return [
            CandidateFlat.model_validate(candidate)
            async for candidate in self._all_with_filters(
                filters=filters,
                relationships=relationships
            )
        ]   is this correct ?