from datetime import timedelta
from typing import List

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from services.user_service.emergency_contact_model import EmergencyContact
from services.user_service.emergency_contact_schema import (
    EmergencyContactCreate,
    EmergencyContactResponse,
    EmergencyContactUpdate,
)
from services.user_service.models import User
from services.user_service.schemas import (
    Token,
    UserCreate,
    UserLogin,
    UserResponse,
    UserUpdate,
)
from shared.auth import (
    create_access_token,
    get_current_user_from_token,
    get_password_hash,
    verify_password,
)
from shared.config import settings
from shared.database import get_db

app = FastAPI(title="User Service", version="1.0.0")

# CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # В продакшене ограничить конкретными доменами
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


async def get_current_user(
    user_data: dict = Depends(get_current_user_from_token),
    db: AsyncSession = Depends(get_db),
):
    """Get current user from token via auth dependency."""
    # Get full user object from database
    result = await db.execute(select(User).filter(User.id == user_data["user_id"]))
    user = result.scalars().first()
    if user is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail="User not found"
        )
    return user


@app.get("/health")
async def health_check():
    """Health check endpoint"""
    return {"status": "healthy", "service": "user_service"}


@app.get("/users")
async def get_all_users(db: AsyncSession = Depends(get_db)):
    """Get all users (public endpoint for testing)"""
    result = await db.execute(select(User).limit(100))
    users = result.scalars().all()
    return [UserResponse.model_validate(user) for user in users] if users else []


@app.post("/api/v1/auth/register", response_model=UserResponse)
@app.post("/api/v1/users/register", response_model=UserResponse)
async def register_user(user_data: UserCreate, db: AsyncSession = Depends(get_db)):
    """Register a new user"""
    # Check if user already exists by email
    result = await db.execute(select(User).filter(User.email == user_data.email))
    if result.scalars().first():
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST, detail="Email already registered"
        )
    
    # Check if username provided and already exists
    if user_data.username:
        result = await db.execute(select(User).filter(User.username == user_data.username))
        if result.scalars().first():
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST, detail="Username already taken"
            )

    # Create new user
    try:
        hashed_password = get_password_hash(user_data.password)
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Password validation error: {str(e)}"
        )
    
    # Используем phone_number как запасной вариант для phone
    phone = user_data.phone or user_data.phone_number
        
    # Определяем username на основе email, если он не указан
    username = user_data.username
    if not username:
        username = user_data.email.split('@')[0]
    
    # Определяем first_name и last_name
    first_name = user_data.first_name
    last_name = user_data.last_name
    
    # Если есть full_name, разделяем его на first_name и last_name
    if user_data.full_name:
        parts = user_data.full_name.split(" ", 1)
        first_name = parts[0]
        last_name = parts[1] if len(parts) > 1 else ""
    
    db_user = User(
        username=username,
        email=user_data.email,
        phone=phone,
        password_hash=hashed_password,
        first_name=first_name or "",  # Устанавливаем пустую строку, если None
        last_name=last_name or "",    # Устанавливаем пустую строку, если None
        date_of_birth=user_data.date_of_birth,
        bio=user_data.bio,
    )

    db.add(db_user)
    await db.commit()
    await db.refresh(db_user)

    return UserResponse.model_validate(db_user)


@app.post("/api/v1/auth/login", response_model=Token)
async def login(user_credentials: UserLogin, db: AsyncSession = Depends(get_db)):
    """Authenticate user and return token"""
    print(f"Login attempt: email={user_credentials.email}, username={user_credentials.username}")
    
    # Проверка валидности входных данных
    if not user_credentials.email and not user_credentials.username:
        print("Error: Neither email nor username provided")
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            detail="Either email or username must be provided",
        )
    
    if not user_credentials.password:
        print("Error: Password not provided")
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            detail="Password is required",
        )
    
    # Определяем, по какому полю ищем пользователя
    user = None
    try:
        if user_credentials.email:
            print(f"Looking up user by email: {user_credentials.email}")
            result = await db.execute(select(User).filter(User.email == user_credentials.email))
            user = result.scalars().first()
        elif user_credentials.username:
            print(f"Looking up user by username: {user_credentials.username}")
            result = await db.execute(select(User).filter(User.username == user_credentials.username))
            user = result.scalars().first()
    except Exception as e:
        print(f"Database error during user lookup: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Database error during authentication",
        )
    
    # Проверяем наличие пользователя и правильность пароля
    if not user:
        print(f"User not found: email={user_credentials.email}, username={user_credentials.username}")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect email or password",
        )
    
    print(f"User found: id={user.id}, email={user.email}")
    
    # Проверка пароля
    try:
        password_valid = verify_password(user_credentials.password, str(user.password_hash))
        print(f"Password verification result: {password_valid}")
        if not password_valid:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Incorrect email or password",
            )
    except HTTPException:
        raise
    except Exception as e:
        # Если произошла ошибка при проверке пароля, то считаем, что пароль неверный
        print(f"Password verification error: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect email or password",
        )

    # Проверка активности аккаунта
    try:
        is_active = bool(user.is_active)
        print(f"User active status: {is_active}")
        if not is_active:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Account is inactive",
            )
    except Exception as e:
        # Если произошла ошибка при проверке активности, считаем аккаунт активным
        print(f"Error checking user active status: {str(e)}")
        pass

    print("Creating access token...")
    access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": str(user.id), "email": user.email},
        expires_delta=access_token_expires,
    )

    print("Login successful")
    return {"access_token": access_token, "token_type": "bearer"}


@app.get("/api/v1/profile", response_model=UserResponse)
@app.get("/api/v1/users/me", response_model=UserResponse)
async def get_profile(current_user: User = Depends(get_current_user)):
    """Get current user profile"""
    return UserResponse.model_validate(current_user)


@app.put("/api/v1/profile", response_model=UserResponse)
@app.put("/api/v1/users/me", response_model=UserResponse)
@app.patch("/api/v1/users/me", response_model=UserResponse)
async def update_profile(
    user_update: UserUpdate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Update user profile"""
    update_data = user_update.model_dump(exclude_unset=True)

    for field, value in update_data.items():
        setattr(current_user, field, value)

    await db.commit()
    await db.refresh(current_user)

    return UserResponse.model_validate(current_user)


# Маршруты для экстренных контактов
@app.get("/api/v1/users/me/emergency-contacts", response_model=List[EmergencyContactResponse])
async def get_emergency_contacts(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Получение списка экстренных контактов пользователя"""
    result = await db.execute(
        select(EmergencyContact).filter(EmergencyContact.user_id == current_user.id)
    )
    contacts = result.scalars().all()
    return contacts


@app.post("/api/v1/users/me/emergency-contacts", response_model=EmergencyContactResponse)
async def create_emergency_contact(
    contact_data: EmergencyContactCreate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Создание нового экстренного контакта"""
    # Преобразуем 'relationship' из схемы в 'relation_type' для модели
    contact_dict = contact_data.model_dump()
    relationship_value = contact_dict.pop('relationship', None)
    
    contact = EmergencyContact(
        **contact_dict,
        relation_type=relationship_value,
        user_id=current_user.id
    )
    
    db.add(contact)
    await db.commit()
    await db.refresh(contact)
    return contact


@app.get(
    "/api/v1/users/me/emergency-contacts/{contact_id}",
    response_model=EmergencyContactResponse,
)
async def get_emergency_contact(
    contact_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Получение информации об экстренном контакте"""
    result = await db.execute(
        select(EmergencyContact).filter(
            EmergencyContact.id == contact_id, EmergencyContact.user_id == current_user.id
        )
    )
    contact = result.scalars().first()
    if contact is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail="Contact not found"
        )
    return contact


@app.patch(
    "/api/v1/users/me/emergency-contacts/{contact_id}",
    response_model=EmergencyContactResponse,
)
async def update_emergency_contact(
    contact_id: int,
    contact_data: EmergencyContactUpdate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Обновление информации об экстренном контакте"""
    result = await db.execute(
        select(EmergencyContact).filter(
            EmergencyContact.id == contact_id, EmergencyContact.user_id == current_user.id
        )
    )
    contact = result.scalars().first()
    if contact is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail="Contact not found"
        )

    update_data = contact_data.model_dump(exclude_unset=True)
    
    # Преобразуем 'relationship' из схемы в 'relation_type' для модели
    if 'relationship' in update_data:
        update_data['relation_type'] = update_data.pop('relationship')
        
    for field, value in update_data.items():
        setattr(contact, field, value)

    await db.commit()
    await db.refresh(contact)
    return contact


@app.delete(
    "/api/v1/users/me/emergency-contacts/{contact_id}",
    status_code=status.HTTP_204_NO_CONTENT,
)
async def delete_emergency_contact(
    contact_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Удаление экстренного контакта"""
    result = await db.execute(
        select(EmergencyContact).filter(
            EmergencyContact.id == contact_id, EmergencyContact.user_id == current_user.id
        )
    )
    contact = result.scalars().first()
    if contact is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail="Contact not found"
        )

    await db.delete(contact)
    await db.commit()
    return None


@app.get("/api/v1/users/dashboard", tags=["Dashboard"])
async def get_user_dashboard(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Get user dashboard data"""
    try:
        # Get emergency contacts count
        emergency_contacts_result = await db.execute(
            select(EmergencyContact).filter(
                EmergencyContact.user_id == current_user.id,
                EmergencyContact.is_active == True
            )
        )
        emergency_contacts = emergency_contacts_result.scalars().all()
        
        dashboard_data = {
            "user": {
                "id": current_user.id,
                "uuid": str(current_user.uuid),
                "email": current_user.email,
                "username": current_user.username,
                "first_name": current_user.first_name,
                "last_name": current_user.last_name,
                "avatar_url": current_user.avatar_url
            },
            "emergency_contacts_count": len(emergency_contacts),
            "settings": {
                "location_sharing_enabled": current_user.location_sharing_enabled,
                "emergency_notifications_enabled": current_user.emergency_notifications_enabled,
                "push_notifications_enabled": current_user.push_notifications_enabled
            },
            "verification_status": {
                "email_verified": current_user.email_verified,
                "phone_verified": current_user.phone_verified
            },
            "account_status": {
                "is_active": current_user.is_active,
                "created_at": str(current_user.created_at) if hasattr(current_user, 'created_at') else None
            }
        }
        
        return dashboard_data
        
    except Exception as e:
        print(f"Dashboard error: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to load dashboard data"
        )


@app.get("/api/v1/health")
async def health_check_v1():
    """Health check endpoint with API version"""
    return {"status": "healthy", "service": "user-service"}


@app.get("/health")
async def health_check():
    """Health check endpoint"""
    return {"status": "healthy", "service": "user-service"}


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=8001)
