# ============================================================
# Authentication API — login / me / logout
# ============================================================
from datetime import datetime, timezone
from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel
from sqlalchemy import select
from sqlalchemy.orm import Session

from app.core.database import get_db
from app.core.models import Tenant, TenantStatus, User, UserRole, UserStatus
from app.core.security import (
    PLATFORM_TENANT_CODE,
    create_jwt_token,
    get_allowed_routes,
    get_client_permissions,
    get_current_user,
    verify_password,
)


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


# -------------------- Pydantic models --------------------
class LoginRequest(BaseModel):
    company_code: str
    username: str
    password: str


class TenantResponse(BaseModel):
    id: int
    company_code: str
    name: str


class UserResponse(BaseModel):
    id: int
    username: str
    display_name: str | None
    role: str
    status: str
    permissions: list[str]
    allowed_routes: list[str]
    is_platform_admin: bool
    tenant: TenantResponse

    class Config:
        from_attributes = True


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


def _to_user_response(user: User, tenant: Tenant) -> UserResponse:
    return UserResponse(
        id=user.id,
        username=user.username,
        display_name=user.display_name,
        role=user.role.value if hasattr(user.role, "value") else user.role,
        status=user.status.value if hasattr(user.status, "value") else user.status,
        permissions=get_client_permissions(user),
        allowed_routes=get_allowed_routes(user),
        is_platform_admin=user.role == UserRole.admin and tenant.company_code == PLATFORM_TENANT_CODE,
        tenant=TenantResponse(id=tenant.id, company_code=tenant.company_code, name=tenant.name),
    )


# -------------------- Endpoints --------------------
@router.post("/login", response_model=LoginResponse)
async def login(data: LoginRequest, db: Session = Depends(get_db)):
    """Authenticate user and return JWT + user info."""
    # Resolve tenant
    tenant = db.execute(
        select(Tenant).where(Tenant.company_code == data.company_code.strip().lower())
    ).scalar_one_or_none()
    if not tenant:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid company code")
    if tenant.status != TenantStatus.active:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Company account is disabled")

    # Query user within tenant
    user = db.execute(
        select(User).where(User.tenant_id == tenant.id, User.username == data.username)
    ).scalar_one_or_none()

    if not user or not verify_password(data.password, user.password_hash):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid username or password",
        )

    if user.status != UserStatus.active:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="User account is disabled",
        )

    # Update last_login_at
    user.last_login_at = datetime.now(timezone.utc)
    db.commit()

    # Create JWT
    role_val = user.role.value if hasattr(user.role, "value") else user.role
    token = create_jwt_token({
        "sub": str(user.id),
        "tenant_id": user.tenant_id,
        "username": user.username,
        "role": role_val,
    })

    return LoginResponse(
        access_token=token,
        token_type="bearer",
        user=_to_user_response(user, tenant),
    )


@router.get("/me", response_model=UserResponse)
async def get_me(user: User = Depends(get_current_user), db: Session = Depends(get_db)):
    """Return current logged-in user info."""
    tenant = db.get(Tenant, user.tenant_id)
    return _to_user_response(user, tenant)


@router.post("/logout")
async def logout(user: User = Depends(get_current_user)):
    """
    Logout endpoint. Token invalidation is client-side;
    server confirms the token was valid and user is authenticated.
    """
    return {"message": "Logged out successfully", "user_id": user.id}
