
from fastapi import Depends, APIRouter, HTTPException, Depends, Request
from sqlalchemy.orm import Session
from app.db import models
from app.core.security import get_current_user
from app.api import schemas
from sqlalchemy import or_, and_, exists
from sqlalchemy.exc import IntegrityError
from app.websocket import connection_manager

# бд


def get_db():
    db = models.SessionLocal()
    try:
        yield db
    finally:
        db.close()


usersRouter = APIRouter(
    prefix="/users",
    tags=[],
)

# Пример защищенного роута


@usersRouter.get("/me")
async def read_users_me(current_user: models.User = Depends(get_current_user)):
    return {
        "id": current_user.id,
        "username": current_user.username,
        "first_name": current_user.first_name,
        "last_name": current_user.last_name,
        "phone": current_user.phone,
        "email": getattr(current_user, "email", None),
        "about": current_user.about,
        "public_key": current_user.public_key,
        "encrypted_private_key": current_user.encrypted_private_key,
        "avatar_file_id": current_user.avatar_file_id,
        "totp_enabled": bool(current_user.totp_secret != None),
    }


@usersRouter.put("/me")
async def update_users_me(
    data: schemas.UpdateMe,
    current_user: models.User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    user_to_update = db.merge(current_user)

    if data.username is not None:
        user_to_update.username = data.username
    if data.first_name is not None:
        user_to_update.first_name = data.first_name
    if data.last_name is not None:
        user_to_update.last_name = data.last_name
    if data.phone is not None:
        user_to_update.phone = data.phone or None
    if data.email is not None:
        user_to_update.email = data.email or None
    if data.about is not None:
        user_to_update.about = data.about or None

    try:
        db.commit()
    except IntegrityError:
        db.rollback()
        raise HTTPException(
            status_code=400, detail="phone/email already in use")

    db.refresh(user_to_update)
    await connection_manager.manager.broadcast({'type': 'user_updated', 'user_id': current_user.id})
    return {
        "status": "ok",
        "user": {
            "id": user_to_update.id,
            "username": user_to_update.username,
            "first_name": user_to_update.first_name,
            "last_name": user_to_update.last_name,
            "phone": user_to_update.phone,
            "email": getattr(user_to_update, "email", None),
            "about": user_to_update.about,
        },
    }


@usersRouter.put("/me/encryption-key")
async def update_encrypted_private_key(
    data: schemas.UpdateEncryptedPrivateKey,
    current_user: models.User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    user_to_update = db.merge(current_user)
    user_to_update.encrypted_private_key = data.encrypted_private_key

    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(
            status_code=500, detail="Не удалось сохранить ключ шифрования")

    db.refresh(user_to_update)
    await connection_manager.manager.broadcast({'type': 'user_updated', 'user_id': current_user.id})
    return {"status": "ok"}


@usersRouter.put("/me/password")
async def change_password(
    data: schemas.ChangePassword,
    current_user: models.User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    from app.core.security import verify_password, get_password_hash

    if not verify_password(data.current_password, current_user.hashed_password):
        raise HTTPException(status_code=400, detail="Неверный текущий пароль")

    user_to_update = db.merge(current_user)
    user_to_update.hashed_password = get_password_hash(data.new_password)

    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(
            status_code=500, detail="Не удалось изменить пароль")

    db.refresh(user_to_update)
    return {"status": "ok"}


@usersRouter.put("/me/privacy")
async def update_privacy_settings(
    data: schemas.UpdatePrivacySettings,
    current_user: models.User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    user_to_update = db.merge(current_user)

    if data.show_email is not None:
        user_to_update.show_email = 1 if data.show_email else 0
    if data.show_phone is not None:
        user_to_update.show_phone = 1 if data.show_phone else 0
    if data.show_avatar is not None:
        user_to_update.show_avatar = 1 if data.show_avatar else 0
    if data.show_about is not None:
        user_to_update.show_about = 1 if data.show_about else 0
    if data.show_username is not None:
        user_to_update.show_username = 1 if data.show_username else 0
    if data.show_last_online is not None:
        user_to_update.show_last_online = 1 if data.show_last_online else 0
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(
            status_code=500, detail="Не удалось сохранить настройки конфиденциальности")

    db.refresh(user_to_update)
    await connection_manager.manager.broadcast({'type': 'user_updated', 'user_id': current_user.id})
    return {"status": "ok"}


@usersRouter.get("/me/privacy")
async def get_privacy_settings(current_user: models.User = Depends(get_current_user)):
    """
    Получить настройки конфиденциальности текущего пользователя.
    """
    return {
        "show_email": bool(current_user.show_email),
        "show_phone": bool(current_user.show_phone),
        "show_avatar": bool(current_user.show_avatar),
        "show_about": bool(current_user.show_about),
        "show_username": bool(current_user.show_username),
        "show_last_online": bool(current_user.show_last_online),
    }


@usersRouter.get("/all")
async def read_users_all(current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)):
    users = db.query(models.User).all()
    return [{"id": user.id, "username": user.username, "name": f"{user.first_name} {user.last_name or ''}".strip(), "public_key": user.public_key} for user in users]


@usersRouter.get("/chats")
async def read_users_chats(
    request: Request,
    current_user: models.User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    """
    Список контактов для экрана чатов: последний месседж + время + непрочитанные.

    last_message возвращается в том виде, как хранится в БД (зашифрованный content).
    Клиент должен расшифровать превью локально.
    """

    users = (
        db.query(models.User)
        .filter(models.User.id != current_user.id)
        .filter(exists().where(
            or_(
                and_(models.Message.sender_id == current_user.id,
                     models.Message.receiver_id == models.User.id),
                and_(models.Message.sender_id == models.User.id,
                     models.Message.receiver_id == current_user.id)
            )
        ))
        .all()
    )

    result = []
    for user in users:
        last_msg = (
            db.query(models.Message)
            .filter(
                or_(
                    and_(
                        models.Message.sender_id == current_user.id,
                        models.Message.receiver_id == user.id,
                    ),
                    and_(
                        models.Message.sender_id == user.id,
                        models.Message.receiver_id == current_user.id,
                    ),
                )
            )
            .order_by(models.Message.timestamp.desc())
            .first()
        )

        unread_count = (
            db.query(models.Message)
            .filter(
                models.Message.sender_id == user.id,
                models.Message.receiver_id == current_user.id,
                models.Message.read_at.is_(None),
            )
            .count()
        )

        result.append(
            {
                "id": user.id,
                "username": user.username,
                "name": f"{user.first_name} {user.last_name or ''}".strip(),
                "public_key": user.public_key,
                "avatar_file_id": user.avatar_file_id,
                "avatar_url": str(request.url_for("get_file", file_id=user.avatar_file_id)) if user.show_avatar and user.avatar_file_id else None,
                "last_message": last_msg.content if last_msg else None,
                "last_message_time": (last_msg.timestamp.isoformat() if last_msg and last_msg.timestamp else None),
                "unread_count": unread_count,
            }
        )

    result.sort(key=lambda x: x['last_message_time'] or '', reverse=True)
    return result


@usersRouter.get("/{user_id}", response_model=schemas.UserProfile)
def get_user_by_id(
    user_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """
    Получить информацию о пользователе с учетом настроек конфиденциальности.
    """
    user = db.query(models.User).filter(models.User.id == user_id).first()

    if not user:
        raise HTTPException(status_code=404, detail="Пользователь не найден")

    # Возвращаем информацию с учетом настроек конфиденциальности
    profile_data = {
        "id": user.id,
        "public_key": user.public_key,
    }

    profile_data["first_name"] = user.first_name
    profile_data["last_name"] = user.last_name

    # Проверяем настройки конфиденциальности
    if user.show_username:
        profile_data["username"] = user.username

    if user.show_avatar:
        profile_data["avatar_url"] = str(request.url_for(
            "get_file", file_id=user.avatar_file_id)) if user.avatar_file_id else None

    profile_data["show_avatar"] = bool(user.show_avatar)

    profile_data["totp_enabled"] = bool(user.totp_secret)

    if user.show_about:
        profile_data["about"] = user.about

    if user.show_phone:
        profile_data["phone"] = user.phone

    if user.show_email:
        profile_data["email"] = user.email

    if str(user.id) in connection_manager.manager.active_connections:
        profile_data["online"] = True
    else:
        profile_data["online"] = False
    if user.show_last_online:
        profile_data["last_online"] = user.last_online.isoformat(
        ) if user.last_online else None

    return profile_data


@usersRouter.put("/me/avatar")
async def update_user_avatar(
    data: dict,
    current_user: models.User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    user_to_update = db.merge(current_user)
    avatar_file_id = data.get("avatar_file_id")
    if avatar_file_id:
        user_to_update.avatar_file_id = avatar_file_id
        db.commit()
        print(
            f"Пользователь {user_to_update.id} обновил аватар: {avatar_file_id}")
    else:
        raise HTTPException(
            status_code=400, detail="avatar_file_id is required")
    await connection_manager.manager.broadcast({'type': 'user_updated', 'user_id': current_user.id})
    return {"message": "Avatar updated"}
