"""
Служба календаря для приложения женской безопасности.
Предоставляет API для работы с записями календаря здоровья.

Поддерживаются следующие форматы запросов:
1. Стандартный формат: /api/v1/calendar/entries
2. Мобильный формат: /api/v1/calendar/entry
3. Запросы без префикса /calendar: /api/v1/entries и /api/v1/entry
"""

from fastapi import FastAPI, Depends, HTTPException, Header, Body, Query, Path
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
import json
from typing import List, Optional, Dict, Any, Union
from datetime import date, datetime, timedelta
from pydantic import BaseModel, Field
from enum import Enum
import os
import sys
import uuid
import logging
from typing import Dict, List, Optional
import time
import asyncio

# Добавляем путь к общим модулям
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../')))

# Импортируем общие модули
from shared.auth import get_current_user
from shared.database import get_db
from shared.config import settings
from services.calendar_service.models import CalendarEntryInDB, EntryType, FlowIntensity, MoodType

# Схемы данных для календарных записей
class CalendarEntryBase(BaseModel):
    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[float] = None
    symptoms: Optional[str] = None
    medications: Optional[str] = None
    notes: Optional[str] = None

class CalendarEntryCreate(CalendarEntryBase):
    pass

class CalendarEntryResponse(CalendarEntryBase):
    id: int
    created_at: datetime
    updated_at: Optional[datetime] = None
    user_id: int
    
    class Config:
        orm_mode = True

# Мобильные типы записей и данных
class MobileEntryType(str, Enum):
    MENSTRUATION = "MENSTRUATION"
    OVULATION = "OVULATION"
    SPOTTING = "SPOTTING"
    DISCHARGE = "DISCHARGE"
    PAIN = "PAIN"
    MOOD = "MOOD"

class MobileMood(str, Enum):
    HAPPY = "HAPPY"
    SAD = "SAD" 
    ANXIOUS = "ANXIOUS"
    IRRITABLE = "IRRITABLE"
    ENERGETIC = "ENERGETIC"
    TIRED = "TIRED"
    NORMAL = "NORMAL"

class MobileSymptom(str, Enum):
    CRAMPS = "CRAMPS"
    HEADACHE = "HEADACHE"
    BLOATING = "BLOATING"
    FATIGUE = "FATIGUE"
    NAUSEA = "NAUSEA"
    BREAST_TENDERNESS = "BREAST_TENDERNESS"
    ACNE = "ACNE"
    BACKACHE = "BACKACHE"

# Схемы для мобильного API
class MobileCalendarEntry(BaseModel):
    date: date
    type: MobileEntryType
    flow_intensity: Optional[int] = None  # 1-5 scale
    mood: Optional[MobileMood] = None
    symptoms: Optional[List[str]] = None
    notes: Optional[str] = None

# Инициализация приложения
app = FastAPI(title="Calendar Service API", 
              description="API для работы с календарём здоровья",
              version="1.0.0")

# CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Настройка логирования
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Конвертеры форматов
def mobile_to_standard_entry(mobile_entry: MobileCalendarEntry) -> CalendarEntryCreate:
    """Конвертирует запись из мобильного формата в стандартный"""
    
    # Отображение типов записей
    entry_type_mapping = {
        MobileEntryType.MENSTRUATION: "period",
        MobileEntryType.OVULATION: "ovulation",
        MobileEntryType.SPOTTING: "spotting",
        MobileEntryType.DISCHARGE: "discharge",
        MobileEntryType.PAIN: "pain",
        MobileEntryType.MOOD: "mood"
    }
    
    # Отображение интенсивности потока
    flow_intensity_mapping = {
        1: "very_light",
        2: "light",
        3: "medium",
        4: "heavy",
        5: "very_heavy"
    }
    
    # Отображение настроения
    mood_mapping = {
        MobileMood.HAPPY: "happy",
        MobileMood.SAD: "sad",
        MobileMood.ANXIOUS: "anxious",
        MobileMood.IRRITABLE: "irritable",
        MobileMood.ENERGETIC: "energetic",
        MobileMood.TIRED: "tired",
        MobileMood.NORMAL: "normal"
    }
    
    # Сопоставляем симптомы
    symptoms_str = ""
    if mobile_entry.symptoms:
        symptoms_str = ", ".join(symptom.lower() for symptom in mobile_entry.symptoms)
    
    # Определяем тип записи
    entry_type = entry_type_mapping.get(mobile_entry.type, "other")
    
    # Преобразуем интенсивность потока
    flow_intensity = None
    if mobile_entry.flow_intensity and mobile_entry.type == MobileEntryType.MENSTRUATION:
        flow_intensity = flow_intensity_mapping.get(mobile_entry.flow_intensity)
    
    # Преобразуем настроение
    mood = None
    if mobile_entry.mood:
        mood = mood_mapping.get(mobile_entry.mood)
    
    # Создаем стандартную запись
    standard_entry = CalendarEntryCreate(
        entry_date=mobile_entry.date,
        entry_type=entry_type,
        flow_intensity=flow_intensity,
        period_symptoms="" if entry_type != "period" else symptoms_str,
        mood=mood,
        symptoms=symptoms_str if entry_type != "period" else "",
        notes=mobile_entry.notes,
        energy_level=None,
        sleep_hours=None,
        medications=""
    )
    
    return standard_entry

def standard_to_mobile_entry(entry: CalendarEntryResponse) -> Dict[str, Any]:
    """Конвертирует запись из стандартного формата в мобильный"""
    
    # Обратное отображение типов записей
    entry_type_mapping = {
        "period": MobileEntryType.MENSTRUATION,
        "ovulation": MobileEntryType.OVULATION,
        "spotting": MobileEntryType.SPOTTING,
        "discharge": MobileEntryType.DISCHARGE,
        "pain": MobileEntryType.PAIN,
        "mood": MobileEntryType.MOOD
    }
    
    # Обратное отображение интенсивности потока
    flow_intensity_mapping = {
        "very_light": 1,
        "light": 2,
        "medium": 3,
        "heavy": 4,
        "very_heavy": 5
    }
    
    # Обратное отображение настроения
    mood_mapping = {
        "happy": MobileMood.HAPPY,
        "sad": MobileMood.SAD,
        "anxious": MobileMood.ANXIOUS,
        "irritable": MobileMood.IRRITABLE,
        "energetic": MobileMood.ENERGETIC,
        "tired": MobileMood.TIRED,
        "normal": MobileMood.NORMAL
    }
    
    # Определяем тип записи
    mobile_type = entry_type_mapping.get(entry.entry_type, MobileEntryType.MOOD)
    
    # Интенсивность потока
    flow_intensity = None
    if entry.flow_intensity:
        flow_intensity = flow_intensity_mapping.get(entry.flow_intensity)
    
    # Настроение
    mood = None
    if entry.mood:
        mood = mood_mapping.get(entry.mood, MobileMood.NORMAL)
    
    # Симптомы
    symptoms = []
    if entry.entry_type == "period" and entry.period_symptoms:
        symptoms = [s.strip().upper() for s in entry.period_symptoms.split(',') if s.strip()]
    elif entry.symptoms:
        symptoms = [s.strip().upper() for s in entry.symptoms.split(',') if s.strip()]
    
    # Создаем мобильную запись
    mobile_entry = {
        "id": entry.id,
        "date": entry.entry_date.isoformat(),
        "type": mobile_type,
        "flow_intensity": flow_intensity,
        "mood": mood,
        "symptoms": symptoms,
        "notes": entry.notes,
        "created_at": entry.created_at.isoformat(),
        "updated_at": entry.updated_at.isoformat() if entry.updated_at else None
    }
    
    return mobile_entry

# Эндпоинт для проверки здоровья сервиса
@app.get("/health")
def health_check():
    return {"status": "ok", "service": "calendar"}

# API для работы с календарем
# 1. Стандартный эндпоинт для получения записей календаря
@app.get("/api/v1/calendar/entries", response_model=List[CalendarEntryResponse])
async def get_calendar_entries(
    skip: int = 0,
    limit: int = 100,
    current_user: dict = Depends(get_current_user),
    db = Depends(get_db)
):
    """Получение списка записей календаря"""
    entries = db.query(CalendarEntryInDB).filter(
        CalendarEntryInDB.user_id == current_user["id"]
    ).offset(skip).limit(limit).all()
    
    return entries

# 2. Стандартный эндпоинт для создания записи календаря
@app.post("/api/v1/calendar/entries", response_model=CalendarEntryResponse, status_code=201)
async def create_calendar_entry(
    entry: CalendarEntryCreate,
    current_user: dict = Depends(get_current_user),
    db = Depends(get_db)
):
    """Создание новой записи в календаре"""
    db_entry = CalendarEntryInDB(**entry.dict(), user_id=current_user["id"])
    db.add(db_entry)
    db.commit()
    db.refresh(db_entry)
    return db_entry

# 3. Поддержка legacy эндпоинта /api/v1/entries (без префикса /calendar)
@app.get("/api/v1/entries", response_model=List[CalendarEntryResponse])
async def get_entries_legacy(
    skip: int = 0,
    limit: int = 100,
    current_user: dict = Depends(get_current_user),
    db = Depends(get_db)
):
    """Legacy эндпоинт для получения записей календаря"""
    return await get_calendar_entries(skip, limit, current_user, db)

@app.post("/api/v1/entries", response_model=CalendarEntryResponse, status_code=201)
async def create_entry_legacy(
    entry: CalendarEntryCreate,
    current_user: dict = Depends(get_current_user),
    db = Depends(get_db)
):
    """Legacy эндпоинт для создания записи в календаре"""
    return await create_calendar_entry(entry, current_user, db)

# 4. Поддержка эндпоинта /api/v1/entry (ед. число, без префикса /calendar)
@app.post("/api/v1/entry", response_model=CalendarEntryResponse, status_code=201)
async def create_entry_singular(
    entry: CalendarEntryCreate,
    current_user: dict = Depends(get_current_user),
    db = Depends(get_db)
):
    """Эндпоинт для создания записи в календаре (ед. число)"""
    return await create_calendar_entry(entry, current_user, db)

# 5. Поддержка мобильного API с эндпоинтом /api/v1/calendar/entry
@app.post("/api/v1/calendar/entry", status_code=201)
async def create_mobile_calendar_entry(
    entry: MobileCalendarEntry,
    current_user: dict = Depends(get_current_user),
    db = Depends(get_db)
):
    """Создание записи в календаре из мобильного приложения"""
    # Преобразуем мобильную запись в стандартную
    standard_entry = mobile_to_standard_entry(entry)
    
    # Создаем запись в БД
    db_entry = CalendarEntryInDB(**standard_entry.dict(), user_id=current_user["id"])
    db.add(db_entry)
    db.commit()
    db.refresh(db_entry)
    
    # Преобразуем ответ обратно в мобильный формат
    mobile_response = standard_to_mobile_entry(db_entry)
    
    return mobile_response

@app.get("/api/v1/calendar/entry/{entry_id}", status_code=200)
async def get_mobile_calendar_entry(
    entry_id: int,
    current_user: dict = Depends(get_current_user),
    db = Depends(get_db)
):
    """Получение записи календаря в мобильном формате"""
    db_entry = db.query(CalendarEntryInDB).filter(
        CalendarEntryInDB.id == entry_id,
        CalendarEntryInDB.user_id == current_user["id"]
    ).first()
    
    if not db_entry:
        raise HTTPException(status_code=404, detail="Запись не найдена")
    
    # Преобразуем ответ в мобильный формат
    mobile_response = standard_to_mobile_entry(db_entry)
    
    return mobile_response

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8004)