from __future__ import annotations

import json

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import select
from sqlalchemy.orm import Session, selectinload

from app.core.database import get_db
from app.core.dependencies import get_current_admin
from app.core.responses import api_success
from app.core.security import hash_password, verify_password
from app.models.admin import Admin, Role
from app.schemas.admin import AdminPasswordChangeRequest, ManagedAdminCreateRequest, ManagedAdminUpdateRequest
from app.services.admin_permission_service import ALL_PERMISSION_CODES, PERMISSION_TREE, permissions_for, require_permission

router = APIRouter()


def _serialize(admin: Admin) -> dict:
    return {
        "id": admin.id, "username": admin.username, "name": admin.name, "status": admin.status,
        "isSuperAdmin": bool(admin.is_super_admin), "mustChangePassword": bool(admin.must_change_password),
        "permissions": sorted(permissions_for(admin)), "lastLoginAt": admin.last_login_at,
        "createdAt": admin.created_at,
    }


def _validated_permissions(values: list[str]) -> list[str]:
    unknown = set(values) - ALL_PERMISSION_CODES
    if unknown:
        raise HTTPException(status_code=422, detail=f"包含未知权限：{', '.join(sorted(unknown))}")
    return sorted(set(values))


def _require_super(admin: Admin) -> None:
    if not admin.is_super_admin:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="仅超级管理员可管理管理员账号")


@router.get("/permission-tree")
def permission_tree(current: Admin = Depends(get_current_admin)) -> dict:
    _require_super(current)
    return api_success(PERMISSION_TREE)


@router.get("/administrator/list")
def list_administrators(db: Session = Depends(get_db), current: Admin = Depends(get_current_admin)) -> dict:
    _require_super(current)
    rows = db.scalars(select(Admin).options(selectinload(Admin.role)).order_by(Admin.is_super_admin.desc(), Admin.id)).all()
    return api_success([_serialize(item) for item in rows])


@router.post("/administrator")
def create_administrator(payload: ManagedAdminCreateRequest, db: Session = Depends(get_db), current: Admin = Depends(get_current_admin)) -> dict:
    _require_super(current)
    if db.scalar(select(Admin.id).where(Admin.username == payload.username.strip())):
        raise HTTPException(status_code=409, detail="管理员账号已存在")
    permissions = _validated_permissions(payload.permissions)
    role = Role(code=f"admin_{payload.username.strip().lower()}", name=f"{payload.name.strip()}的权限", permissions=json.dumps(permissions))
    db.add(role)
    db.flush()
    item = Admin(username=payload.username.strip(), name=payload.name.strip(), password=hash_password(payload.initialPassword), role_id=role.id, status=payload.status, must_change_password=1, is_super_admin=0)
    db.add(item)
    db.commit()
    db.refresh(item)
    item.role = role
    return api_success(_serialize(item))


@router.put("/administrator/{admin_id}")
def update_administrator(admin_id: int, payload: ManagedAdminUpdateRequest, db: Session = Depends(get_db), current: Admin = Depends(get_current_admin)) -> dict:
    _require_super(current)
    item = db.scalar(select(Admin).options(selectinload(Admin.role)).where(Admin.id == admin_id))
    if item is None:
        raise HTTPException(status_code=404, detail="管理员不存在")
    if item.is_super_admin:
        raise HTTPException(status_code=403, detail="超级管理员账号由环境变量管理，不可修改")
    item.name, item.status = payload.name.strip(), payload.status
    if item.role is None:
        item.role = Role(code=f"admin_{item.username.lower()}", name=f"{item.name}的权限")
    item.role.name = f"{item.name}的权限"
    item.role.permissions = json.dumps(_validated_permissions(payload.permissions))
    if payload.resetPassword:
        item.password = hash_password(payload.resetPassword)
        item.must_change_password = 1
    db.commit()
    db.refresh(item)
    return api_success(_serialize(item))


@router.delete("/administrator/{admin_id}")
def delete_administrator(admin_id: int, db: Session = Depends(get_db), current: Admin = Depends(get_current_admin)) -> dict:
    _require_super(current)
    item = db.scalar(select(Admin).options(selectinload(Admin.role)).where(Admin.id == admin_id))
    if item is None:
        raise HTTPException(status_code=404, detail="管理员不存在")
    if item.is_super_admin:
        raise HTTPException(status_code=403, detail="超级管理员不可删除")
    role = item.role
    db.delete(item)
    db.flush()
    if role is not None:
        db.delete(role)
    db.commit()
    return api_success()


@router.post("/password")
def change_password(payload: AdminPasswordChangeRequest, db: Session = Depends(get_db), current: Admin = Depends(get_current_admin)) -> dict:
    if current.is_super_admin:
        raise HTTPException(status_code=403, detail="超级管理员密码由环境变量管理，不可在后台修改")
    if not verify_password(payload.currentPassword, current.password):
        raise HTTPException(status_code=400, detail="当前密码不正确")
    if payload.currentPassword == payload.newPassword:
        raise HTTPException(status_code=400, detail="新密码不能与当前密码相同")
    current.password = hash_password(payload.newPassword)
    current.must_change_password = 0
    db.commit()
    return api_success()
