from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel
import logging
from typing import List, Optional
from dbmodel import User, UserToken
import datetime
from ..dependencies import get_db

logger = logging.getLogger("sampacs")

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

class UserCreate(BaseModel):
    login: str
    password: str
    last_name: str
    first_name: str
    patr_name: str
    is_admin: bool = False

class UserResponse(BaseModel):
    id: int
    login: str
    last_name: str
    first_name: str
    patr_name: str
    is_admin: bool

    class Config:
        exclude_none = True

class UserUpdate(BaseModel):
    id: int
    password: Optional[str] = None
    last_name: Optional[str] = None
    first_name: Optional[str] = None
    patr_name: Optional[str] = None
    is_admin: Optional[bool] = None

@router.get("", response_model=List[UserResponse])
async def get_users(db: None = Depends(get_db)):
    users = User.select().where(~User.deleted).order_by(User.login)
    return [
        UserResponse(
            id=user.id,
            login=user.login,
            last_name=user.last_name,
            first_name=user.first_name,
            patr_name=user.patr_name,
            is_admin=user.is_admin
        )
        for user in users
    ]

@router.get("/{user_id}", response_model=UserResponse)
async def get_user(user_id: int, db: None = Depends(get_db)):
    user = User.get_or_none((User.id == user_id) & (~User.deleted))
    if not user:
        raise HTTPException(status_code=404, detail="User not found")

    return UserResponse(
        id=user.id,
        login=user.login,
        last_name=user.last_name,
        first_name=user.first_name,
        patr_name=user.patr_name,
        is_admin=user.is_admin
    )

@router.post("", response_model=UserResponse)
async def create_user(user_data: UserCreate, db: None = Depends(get_db)):
    existing_user = User.get_or_none((User.login == user_data.login) & (~User.deleted))
    if existing_user:
        raise HTTPException(status_code=400, detail="User with this login already exists")

    user = User(
        login=user_data.login,
        last_name=user_data.last_name,
        first_name=user_data.first_name,
        patr_name=user_data.patr_name,
        is_admin=user_data.is_admin
    )
    user.set_password(user_data.password)
    user.save()

    return UserResponse(
        id=user.id,  # pyright: ignore
        login=user.login,  # pyright: ignore
        last_name=user.last_name,  # pyright: ignore
        first_name=user.first_name,  # pyright: ignore
        patr_name=user.patr_name,  # pyright: ignore
        is_admin=user.is_admin  # pyright: ignore
    )

@router.put("/{user_id}", response_model=UserResponse)
async def update_user(user_id: int, user_data: UserUpdate, db: None = Depends(get_db)):
    user = User.get_or_none((User.id == user_id) & (~User.deleted))
    if not user:
        raise HTTPException(status_code=404, detail="User not found")

    if user_data.last_name is not None:
        user.last_name = user_data.last_name
    if user_data.first_name is not None:
        user.first_name = user_data.first_name
    if user_data.patr_name is not None:
        user.patr_name = user_data.patr_name
    if user_data.is_admin is not None:
        user.is_admin = user_data.is_admin
    if user_data.password is not None:
        user.set_password(user_data.password)
    
    user.save()

    return UserResponse(
        id=user.id,  # pyright: ignore
        login=user.login,  # pyright: ignore
        last_name=user.last_name,  # pyright: ignore
        first_name=user.first_name,  # pyright: ignore
        patr_name=user.patr_name,  # pyright: ignore
        is_admin=user.is_admin  # pyright: ignore
    )

@router.delete("/{user_id}")
async def delete_user(user_id: int, db: None = Depends(get_db)):
    user = User.get_or_none((User.id == user_id) & (~User.deleted))
    if not user:
        raise HTTPException(status_code=404, detail="User not found")

    UserToken.delete().where(UserToken.user == user).execute()
    user.deleted = True
    user.updated_at = datetime.datetime.now()
    user.save()
    return {"success": True}
