from datetime import date
from enum import Enum
from typing import Optional, Dict, Any, List

from pydantic import BaseModel, Field

from .schemas import (
    EntryType, FlowIntensity, MoodType, CalendarEntryCreate, CalendarEntryResponse
)


class MobileFlowIntensity(int, Enum):
    """Flow intensity values used in the mobile app (1-5)"""
    SPOTTING = 1
    LIGHT = 2
    MEDIUM = 3
    HEAVY = 4
    VERY_HEAVY = 5
    
    @classmethod
    def to_server_intensity(cls, value: int) -> Optional[str]:
        """Convert mobile app intensity value to server format"""
        if value is None:
            return None
            
        mapping = {
            cls.SPOTTING.value: FlowIntensity.SPOTTING.value,
            cls.LIGHT.value: FlowIntensity.LIGHT.value,
            cls.MEDIUM.value: FlowIntensity.MEDIUM.value, 
            cls.HEAVY.value: FlowIntensity.HEAVY.value,
            cls.VERY_HEAVY.value: FlowIntensity.HEAVY.value,  # Server has no "very heavy"
        }
        return mapping.get(value)
    
    @classmethod
    def from_server_intensity(cls, value: Optional[str]) -> Optional[int]:
        """Convert server intensity value to mobile app format"""
        if value is None:
            return None
            
        mapping = {
            FlowIntensity.SPOTTING.value: cls.SPOTTING.value,
            FlowIntensity.LIGHT.value: cls.LIGHT.value,
            FlowIntensity.MEDIUM.value: cls.MEDIUM.value,
            FlowIntensity.HEAVY.value: cls.HEAVY.value,
        }
        return mapping.get(value)


class MobileMood(str, Enum):
    """Mood values used in the mobile app"""
    HAPPY = "HAPPY"
    SAD = "SAD" 
    NORMAL = "NORMAL"  # Added for mobile app support
    ANXIOUS = "ANXIOUS"
    IRRITATED = "IRRITATED"
    ENERGETIC = "ENERGETIC"
    TIRED = "TIRED"
    
    @classmethod
    def to_server_mood(cls, value: str) -> Optional[MoodType]:
        """Convert mobile app mood value to server format"""
        if value is None:
            return None
            
        mapping = {
            cls.HAPPY: MoodType.HAPPY,
            cls.SAD: MoodType.SAD,
            cls.NORMAL: MoodType.HAPPY,  # NORMAL maps to HAPPY
            cls.ANXIOUS: MoodType.ANXIOUS,
            cls.IRRITATED: MoodType.IRRITATED,  # Different spelling
            cls.ENERGETIC: MoodType.ENERGETIC,
            cls.TIRED: MoodType.TIRED,
        }
        return mapping.get(MobileMood(value))
    
    @classmethod
    def from_server_mood(cls, value: Optional[str]) -> Optional[str]:
        """Convert server mood value to mobile app format"""
        if value is None:
            return None
            
        # Convert string value to MoodType enum
        try:
            mood_type = MoodType(value)
        except ValueError:
            return None
            
        mapping = {
            MoodType.HAPPY: cls.HAPPY,
            MoodType.SAD: cls.SAD,
            MoodType.ANXIOUS: cls.ANXIOUS,
            MoodType.IRRITATED: cls.IRRITABLE,  # Different spelling
            MoodType.ENERGETIC: cls.ENERGETIC,
            MoodType.TIRED: cls.TIRED,
        }
        return mapping.get(mood_type)


class MobileAppCalendarEntryCreate(BaseModel):
    """Schema for creating calendar entries from mobile app"""
    entry_date: date
    entry_type: str  # Will be mapped to EntryType
    flow_intensity: Optional[int] = None  # 1-5 scale
    symptoms: Optional[str] = None
    mood: Optional[str] = None  # Mobile mood enum as string
    notes: Optional[str] = None


class MobileAppCalendarEntryResponse(BaseModel):
    """Schema for calendar entry responses to mobile app"""
    id: int
    user_id: int
    entry_date: date
    entry_type: str
    flow_intensity: Optional[int] = None
    symptoms: Optional[str] = None
    mood: Optional[str] = None
    notes: Optional[str] = None
    created_at: date
    updated_at: date


def convert_mobile_app_format_to_server(mobile_entry: MobileAppCalendarEntryCreate) -> CalendarEntryCreate:
    """Convert mobile app format to server format"""
    # Map entry type
    try:
        entry_type = EntryType(mobile_entry.entry_type.lower())
    except ValueError:
        # Handle case where entry type doesn't match directly
        if mobile_entry.entry_type == "MENSTRUATION":
            entry_type = EntryType.PERIOD
        elif mobile_entry.entry_type == "SPOTTING":
            entry_type = EntryType.PERIOD
        else:
            # Default to symptoms if no direct mapping
            entry_type = EntryType.SYMPTOMS
            
    # Map flow intensity (1-5 scale to text values)
    flow_intensity_str = None
    if mobile_entry.flow_intensity is not None:
        flow_intensity_str = MobileFlowIntensity.to_server_intensity(mobile_entry.flow_intensity)
        
    # Map mood
    mood_str = None
    if mobile_entry.mood is not None:
        try:
            mobile_mood = MobileMood(mobile_entry.mood)
            mood_type = MobileMood.to_server_mood(mobile_entry.mood)
            if mood_type:
                mood_str = mood_type.value
        except ValueError:
            # If mood doesn't match any enum value, leave it as None
            pass
            
    return CalendarEntryCreate(
        entry_date=mobile_entry.entry_date,
        entry_type=entry_type,
        flow_intensity=flow_intensity_str,
        symptoms=mobile_entry.symptoms or "",
        mood=mood_str,
        notes=mobile_entry.notes or "",
        # Default values for server required fields that mobile app doesn't provide
        period_symptoms="",
        energy_level=0,
        sleep_hours=0,
        medications="",
    )


def convert_server_response_to_mobile_app(
    server_response: CalendarEntryResponse
) -> MobileAppCalendarEntryResponse:
    """Convert server response to mobile app format"""
    # Map flow intensity back to 1-5 scale
    flow_intensity = None
    if server_response.flow_intensity is not None:
        flow_intensity = MobileFlowIntensity.from_server_intensity(server_response.flow_intensity)
        
    # Map mood back to mobile format
    mood = None
    if server_response.mood is not None:
        mood = MobileMood.from_server_mood(server_response.mood)
        
    # Upper case the entry type
    entry_type = server_response.entry_type.upper() if server_response.entry_type else ""
        
    return MobileAppCalendarEntryResponse(
        id=server_response.id,
        user_id=getattr(server_response, "user_id", 0),  # Handle if field doesn't exist
        entry_date=server_response.entry_date,
        entry_type=entry_type,
        flow_intensity=flow_intensity,
        symptoms=server_response.symptoms,
        mood=mood,
        notes=server_response.notes,
        created_at=getattr(server_response, "created_at", date.today()),
        updated_at=getattr(server_response, "created_at", date.today()),  # Fallback to created_at
    )


def convert_mobile_entry_type(mobile_type: str) -> str:
    """Конвертирует тип записи из мобильного формата в формат API"""
    mapping = {
        "MENSTRUATION": "period",
        "OVULATION": "ovulation",
        "FERTILE": "fertile_window",
        "OTHER": "other"
    }
    return mapping.get(mobile_type, "other")


def convert_mobile_flow_intensity(intensity: int) -> str:
    """Конвертирует интенсивность потока из мобильного формата в формат API"""
    if intensity is None:
        return None

    mapping = {
        1: "very_light",
        2: "light",
        3: "medium",
        4: "heavy",
        5: "very_heavy"
    }
    return mapping.get(intensity, "medium")


def convert_mobile_mood(mood: str) -> str:
    """Конвертирует настроение из мобильного формата в формат API"""
    if mood is None:
        return None

    mapping = {
        "HAPPY": "happy",
        "SAD": "sad",
        "NORMAL": "happy",  # NORMAL мапится на happy
        "ANXIOUS": "anxious",
        "IRRITATED": "irritated",
        "ENERGETIC": "energetic",
        "TIRED": "tired"
    }
    return mapping.get(mood, "happy")


def convert_mobile_symptoms(symptoms: List[str]) -> str:
    """Конвертирует список симптомов из мобильного формата в строку для API"""
    if not symptoms:
        return ""

    # Преобразуем все симптомы в нижний регистр и соединяем запятыми
    return ",".join([symptom.lower() for symptom in symptoms])


def mobile_to_api_format(mobile_data: Dict[str, Any]) -> Dict[str, Any]:
    """Конвертирует данные из мобильного формата в формат API"""
    api_data = {
        "entry_date": mobile_data.get("date"),
        "entry_type": convert_mobile_entry_type(mobile_data.get("type")),
        "flow_intensity": convert_mobile_flow_intensity(mobile_data.get("flow_intensity")),
        "mood": convert_mobile_mood(mobile_data.get("mood")),
        "symptoms": convert_mobile_symptoms(mobile_data.get("symptoms")),
        "notes": mobile_data.get("notes", "")
    }

    # Удаляем None значения
    return {k: v for k, v in api_data.items() if v is not None}
