from datetime import date, datetime
from enum import Enum
from typing import List, Optional, Union, Any
import uuid
from uuid import UUID

from pydantic import BaseModel, Field, field_serializer, ConfigDict


class EntryType(str, Enum):
    PERIOD = "period"
    OVULATION = "ovulation"
    SYMPTOMS = "symptoms"
    MEDICATION = "medication"
    MOOD = "mood"
    EXERCISE = "exercise"
    APPOINTMENT = "appointment"


# Мобильное приложение использует другие названия типов
class MobileEntryType(str, Enum):
    MENSTRUATION = "MENSTRUATION"
    OVULATION = "OVULATION"
    SPOTTING = "SPOTTING"
    DISCHARGE = "DISCHARGE"
    PAIN = "PAIN"
    MOOD = "MOOD"
    
    def to_server_type(self) -> EntryType:
        """Конвертировать тип из мобильного приложения в тип сервера"""
        mapping = {
            self.MENSTRUATION: EntryType.PERIOD,
            self.OVULATION: EntryType.OVULATION,
            self.SPOTTING: EntryType.SYMPTOMS,
            self.DISCHARGE: EntryType.SYMPTOMS,
            self.PAIN: EntryType.SYMPTOMS,
            self.MOOD: EntryType.MOOD,
        }
        return mapping.get(self, EntryType.SYMPTOMS)


class FlowIntensity(str, Enum):
    LIGHT = "light"
    MEDIUM = "medium"
    HEAVY = "heavy"
    SPOTTING = "spotting"
    
    @classmethod
    def from_int(cls, value: int) -> 'FlowIntensity':
        """Конвертировать числовое значение в enum"""
        if value <= 1:
            return cls.LIGHT
        elif value <= 3:
            return cls.MEDIUM
        else:
            return cls.HEAVY


class MobileMoodType(str, Enum):
    """Типы настроения из мобильного приложения"""
    HAPPY = "HAPPY"
    SAD = "SAD"
    NORMAL = "NORMAL"
    STRESSED = "STRESSED"
    ANXIOUS = "ANXIOUS"
    IRRITATED = "IRRITATED"


class MoodType(str, Enum):
    HAPPY = "happy"
    SAD = "sad"
    ANXIOUS = "anxious"
    IRRITATED = "irritated"
    ENERGETIC = "energetic"
    TIRED = "tired"
    
    @classmethod
    def from_mobile_mood(cls, mood_str: str) -> Optional['MoodType']:
        """Конвертировать строку настроения из мобильного приложения"""
        if not mood_str:
            return None
            
        # Преобразуем строку в enum или используем исходную строку, если не удалось
        try:
            mood_type = MobileMoodType(mood_str)
            if mood_type == MobileMoodType.NORMAL:
                return None
                
            mapping = {
                MobileMoodType.HAPPY: cls.HAPPY,
                MobileMoodType.SAD: cls.SAD,
                MobileMoodType.ANXIOUS: cls.ANXIOUS,
                MobileMoodType.IRRITATED: cls.IRRITATED,
                MobileMoodType.STRESSED: cls.ANXIOUS,
            }
            return mapping.get(mood_type)
        except ValueError:
            # Если строка не является допустимым MobileMoodType
            # Пробуем сопоставить с сервером напрямую
            mood_map = {
                "HAPPY": cls.HAPPY,
                "SAD": cls.SAD,
                "ANXIOUS": cls.ANXIOUS,
                "IRRITATED": cls.IRRITATED,
                "ENERGETIC": cls.ENERGETIC,
                "TIRED": cls.TIRED,
                "NORMAL": cls.HAPPY,  # NORMAL мапится на HAPPY
            }
            return mood_map.get(mood_str)


class CalendarEntryBase(BaseModel):
    entry_date: date
    entry_type: EntryType
    flow_intensity: Optional[FlowIntensity] = None
    period_symptoms: Optional[str] = Field(None, max_length=500)
    mood: Optional[MoodType] = None
    energy_level: Optional[int] = Field(None, ge=1, le=5)
    sleep_hours: Optional[int] = Field(None, ge=0, le=24)
    symptoms: Optional[str] = Field(None, max_length=1000)
    medications: Optional[str] = Field(None, max_length=500)
    notes: Optional[str] = Field(None, max_length=1000)


class MobileSymptom(str, Enum):
    """Симптомы, используемые в мобильном приложении"""
    CRAMPS = "CRAMPS"
    HEADACHE = "HEADACHE"
    BLOATING = "BLOATING"
    FATIGUE = "FATIGUE"
    NAUSEA = "NAUSEA"
    BREAST_TENDERNESS = "BREAST_TENDERNESS"
    ACNE = "ACNE"
    BACKACHE = "BACKACHE"


class CalendarEventCreate(BaseModel):
    """Модель создания события календаря из мобильного приложения"""
    date: date
    type: MobileEntryType
    flow_intensity: Optional[int] = Field(None, ge=1, le=5)
    mood: Optional[MobileMoodType] = None
    symptoms: Optional[List[MobileSymptom]] = None
    notes: Optional[str] = Field(None, max_length=1000)
    
    def to_server_format(self) -> 'CalendarEntryCreate':
        """Преобразовать в серверный формат"""
        symptoms_str = None
        if self.symptoms:
            symptoms_str = ", ".join([s.value for s in self.symptoms])
        
        flow = None
        if self.flow_intensity is not None:
            flow = FlowIntensity.from_int(self.flow_intensity)
            
        mood_val = None
        if self.mood:
            mood_val = MoodType.from_mobile_mood(self.mood)
        
        return CalendarEntryCreate(
            entry_date=self.date,
            entry_type=self.type.to_server_type(),
            flow_intensity=flow,
            mood=mood_val,
            symptoms=symptoms_str,
            notes=self.notes,
            period_symptoms=None,
            energy_level=None,
            sleep_hours=None,
            medications=None
        )


class CalendarEntryCreate(CalendarEntryBase):
    pass


class CalendarEntryResponse(BaseModel):
    id: int
    uuid: UUID  # Используем UUID из uuid модуля
    entry_date: date
    entry_type: str
    flow_intensity: Optional[str] = None
    period_symptoms: Optional[str] = None
    mood: Optional[str] = None
    energy_level: Optional[int] = None
    sleep_hours: Optional[int] = None
    symptoms: Optional[str] = None
    medications: Optional[str] = None
    notes: Optional[str] = None
    is_predicted: bool
    confidence_score: Optional[int] = None
    created_at: datetime
    updated_at: Optional[datetime] = None
    is_active: Optional[bool] = None
    user_id: Optional[int] = None

    model_config = ConfigDict(from_attributes=True)
    
    @field_serializer('uuid')
    def serialize_uuid(self, uuid_val: UUID) -> str:
        """Преобразование UUID в строку для JSON-сериализации"""
        return str(uuid_val)


# Модель ответа для мобильного приложения
class CalendarEvent(BaseModel):
    id: int
    uuid: UUID  # Используем тип UUID из модуля uuid
    date: date
    type: str
    flow_intensity: Optional[int] = None
    mood: Optional[str] = None
    symptoms: Optional[List[str]] = None
    notes: Optional[str] = None
    created_at: datetime
    
    model_config = ConfigDict(from_attributes=True)
    
    @classmethod
    def from_server_response(cls, entry: CalendarEntryResponse) -> 'CalendarEvent':
        """Преобразовать из серверной модели в модель для мобильного приложения"""
        # Преобразование flow_intensity из строки в число
        flow_int = None
        if entry.flow_intensity:
            if entry.flow_intensity == "light":
                flow_int = 1
            elif entry.flow_intensity == "medium":
                flow_int = 3
            elif entry.flow_intensity == "heavy":
                flow_int = 5
                
        # Преобразование symptoms из строки в список
        symptoms_list = None
        if entry.symptoms:
            symptoms_list = [s.strip() for s in entry.symptoms.split(",")]
            
        return cls(
            id=entry.id,
            uuid=entry.uuid,
            date=entry.entry_date,
            type=entry.entry_type.upper(),
            flow_intensity=flow_int,
            mood=entry.mood.upper() if entry.mood else None,
            symptoms=symptoms_list,
            notes=entry.notes,
            created_at=entry.created_at
        )


class CycleDataResponse(BaseModel):
    id: int
    cycle_start_date: date
    cycle_length: Optional[int]
    period_length: Optional[int]
    ovulation_date: Optional[date]


class CycleOverview(BaseModel):
    current_cycle_day: Optional[int]
    current_phase: str  # menstrual, follicular, ovulation, luteal
    next_period_date: Optional[date]
    days_until_period: Optional[int]
    cycle_regularity: str  # very_regular, regular, irregular, very_irregular
    avg_cycle_length: Optional[int]


class HealthInsightResponse(BaseModel):
    id: int
    insight_type: str
    title: str
    description: str
    recommendation: Optional[str]
    confidence_level: str
    created_at: datetime

    class Config:
        from_attributes = True