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 verify_password, create_access_token, hash_password, get_current_user

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


class LoginRequest(BaseModel):
    username: str
    password: str


class LoginResponse(BaseModel):
    access_token: str
    token_type: str = "bearer"
    user: dict


class ChangePasswordRequest(BaseModel):
    old_password: str
    new_password: str


def _build_user_dict(user: User) -> dict:
    permissions = []
    for role in user.roles:
        for perm in role.permissions:
            permissions.append({"module": perm.module, "action": perm.action})
    seen = set()
    unique_perms = []
    for p in permissions:
        key = (p["module"], p["action"])
        if key not in seen:
            seen.add(key)
            unique_perms.append(p)

    return {
        "id": user.id,
        "username": user.username,
        "email": user.email,
        "full_name": user.full_name,
        "roles": [r.name for r in user.roles],
        "permissions": unique_perms,
        "branch_id": user.branch_id,
    }


@router.post("/login", response_model=LoginResponse)
def login(data: LoginRequest, db: Session = Depends(get_db)):
    user = db.query(User).filter(User.username == data.username).first()
    if not user or not verify_password(data.password, user.password_hash):
        raise HTTPException(status_code=401, detail="Invalid credentials")
    if not user.is_active:
        raise HTTPException(status_code=403, detail="Account disabled")

    token = create_access_token({"sub": user.id, "branch_id": user.branch_id})
    return LoginResponse(
        access_token=token,
        user=_build_user_dict(user),
    )


@router.get("/me")
def get_me(current_user: User = Depends(get_current_user)):
    return _build_user_dict(current_user)


@router.post("/change-password")
def change_password(data: ChangePasswordRequest, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
    if not verify_password(data.old_password, current_user.password_hash):
        raise HTTPException(status_code=400, detail="Invalid old password")
    current_user.password_hash = hash_password(data.new_password)
    db.commit()
    return {"detail": "Password changed"}
