from __future__ import annotations
import uuid
from datetime import datetime
from typing import Optional, List
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from pydantic import BaseModel
from app.database import get_db
from app.models.user import User, Role
from app.services.auth import get_current_user, hash_password

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


class UserCreate(BaseModel):
    username: str
    email: str
    password: str
    full_name: str
    phone: Optional[str] = None
    is_active: bool = True
    branch_id: Optional[str] = None
    role_ids: List[str] = []

class UserUpdate(BaseModel):
    username: Optional[str] = None
    email: Optional[str] = None
    full_name: Optional[str] = None
    phone: Optional[str] = None
    is_active: Optional[bool] = None
    branch_id: Optional[str] = None
    role_ids: Optional[List[str]] = None

class UserOut(BaseModel):
    id: str
    username: str
    email: str
    full_name: str
    phone: Optional[str] = None
    is_active: bool
    branch_id: Optional[str] = None
    created_at: datetime
    updated_at: datetime
    roles: List[str] = []
    model_config = {"from_attributes": True}

class RoleOut(BaseModel):
    id: str
    name: str
    description: Optional[str] = None
    created_at: datetime
    model_config = {"from_attributes": True}


@router.get("/roles", response_model=list[RoleOut])
def list_roles(db: Session = Depends(get_db), _=Depends(get_current_user)):
    return db.query(Role).order_by(Role.name).all()


def _user_out(u: User) -> UserOut:
    return UserOut(
        id=u.id, username=u.username, email=u.email, full_name=u.full_name,
        phone=u.phone, is_active=u.is_active, branch_id=u.branch_id,
        created_at=u.created_at, updated_at=u.updated_at, roles=[r.name for r in u.roles],
    )


@router.get("", response_model=list[UserOut])
def list_users(search: Optional[str] = None, db: Session = Depends(get_db), _=Depends(get_current_user)):
    q = db.query(User)
    if search:
        q = q.filter(User.username.ilike(f"%{search}%") | User.full_name.ilike(f"%{search}%"))
    return [_user_out(u) for u in q.order_by(User.created_at.desc()).all()]


@router.post("", response_model=UserOut, status_code=201)
def create_user(data: UserCreate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    existing = db.query(User).filter((User.username == data.username) | (User.email == data.email)).first()
    if existing:
        raise HTTPException(status_code=400, detail="Username or email already exists")
    user = User(
        username=data.username, email=data.email,
        password_hash=hash_password(data.password),
        full_name=data.full_name, phone=data.phone,
        is_active=data.is_active, branch_id=data.branch_id,
    )
    if data.role_ids:
        user.roles = db.query(Role).filter(Role.id.in_(data.role_ids)).all()
    db.add(user)
    db.commit()
    db.refresh(user)
    return _user_out(user)


@router.get("/{user_id}", response_model=UserOut)
def get_user(user_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    return _user_out(user)


@router.put("/{user_id}", response_model=UserOut)
def update_user(user_id: str, data: UserUpdate, db: Session = Depends(get_db), _=Depends(get_current_user)):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    update_data = data.model_dump(exclude_unset=True)
    role_ids = update_data.pop("role_ids", None)
    for k, v in update_data.items():
        setattr(user, k, v)
    if role_ids is not None:
        user.roles = db.query(Role).filter(Role.id.in_(role_ids)).all()
    db.commit()
    db.refresh(user)
    return _user_out(user)


@router.delete("/{user_id}")
def delete_user(user_id: str, db: Session = Depends(get_db), _=Depends(get_current_user)):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    db.delete(user)
    db.commit()
    return {"detail": "User deleted"}
