"""/admin-api/organizations 接口：仅供 X-Admin-Api-Key 调用。

提供组织 列表 / 创建 / 更新；不要求 captcha（X-Admin-Api-Key 自身已是凭证）。
"""
import logging
from typing import List, Optional

from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import Session

from app.api.v1 import deps
from app.core.utils import get_client_ip
from app.models.admin_api_key import AdminApiKey
from app.models.organization import Organization
from app.schemas.admin_api_key import (
    AdminApiOrganizationCreate,
    AdminApiOrganizationUpdate,
)
from app.schemas.operation_log import ActionType
from app.schemas.organization import OrganizationResponse
from app.services.log_service import LogService

router = APIRouter()
logger = logging.getLogger(__name__)


def _audit_details(api_key: AdminApiKey, extra: Optional[dict] = None) -> dict:
    base = {
        "via": "admin_api_key",
        "key_id": api_key.id,
        "key_prefix": api_key.key_prefix,
    }
    if extra:
        base.update(extra)
    return base


def _has_scope(api_key: AdminApiKey, scope: str) -> bool:
    return scope in (api_key.scopes or "").split(",")


@router.get("/", response_model=List[OrganizationResponse], summary="组织列表（管理 API）")
def list_organizations(
    db: Session = Depends(deps.get_db),
    api_key: AdminApiKey = Depends(deps.get_admin_api_key),
):
    if not _has_scope(api_key, "org:read"):
        raise HTTPException(status_code=403, detail="API Key 缺少 org:read 权限")

    return (
        db.query(Organization)
        .order_by(Organization.sort_order.asc(), Organization.id.asc())
        .all()
    )


@router.post("/", response_model=OrganizationResponse, summary="创建组织（管理 API）")
def create_organization(
    body: AdminApiOrganizationCreate,
    request: Request,
    db: Session = Depends(deps.get_db),
    api_key: AdminApiKey = Depends(deps.get_admin_api_key),
):
    if not _has_scope(api_key, "org:write"):
        raise HTTPException(status_code=403, detail="API Key 缺少 org:write 权限")

    org = Organization(
        name=body.name.strip(),
        description=body.description,
        sort_order=body.sort_order,
    )
    db.add(org)
    try:
        db.commit()
        db.refresh(org)
    except IntegrityError:
        db.rollback()
        raise HTTPException(status_code=400, detail="组织名称已存在")

    LogService.create_log(
        db=db,
        operator_id=api_key.created_by,
        action_type=ActionType.ORG_CREATE,
        ip_address=get_client_ip(request),
        details=_audit_details(
            api_key,
            {
                "resource": "organization",
                "organization_id": org.id,
                "name": org.name,
                "description": org.description,
                "sort_order": org.sort_order,
            },
        ),
    )
    logger.info(
        f"[admin-api] 创建组织: {org.name} (key_prefix={api_key.key_prefix})"
    )
    return org


@router.put("/{organization_id}", response_model=OrganizationResponse, summary="更新组织（管理 API）")
def update_organization(
    organization_id: int,
    body: AdminApiOrganizationUpdate,
    request: Request,
    db: Session = Depends(deps.get_db),
    api_key: AdminApiKey = Depends(deps.get_admin_api_key),
):
    if not _has_scope(api_key, "org:write"):
        raise HTTPException(status_code=403, detail="API Key 缺少 org:write 权限")

    org = db.query(Organization).filter(Organization.id == organization_id).first()
    if not org:
        raise HTTPException(status_code=404, detail="组织不存在")

    raw = body.model_dump(exclude_unset=True)
    if not raw:
        raise HTTPException(status_code=400, detail="请至少修改一项内容")

    changes: dict = {}
    if "name" in raw and raw["name"] is not None:
        new_name = raw["name"].strip()
        if new_name != org.name:
            changes["name"] = {"old": org.name, "new": new_name}
            org.name = new_name
    if "description" in raw:
        if raw["description"] != org.description:
            changes["description"] = {"old": org.description, "new": raw["description"]}
            org.description = raw["description"]
    if "sort_order" in raw and raw["sort_order"] is not None:
        if raw["sort_order"] != org.sort_order:
            changes["sort_order"] = {"old": org.sort_order, "new": raw["sort_order"]}
            org.sort_order = raw["sort_order"]

    if not changes:
        raise HTTPException(status_code=400, detail="未检测到变更")

    try:
        db.commit()
        db.refresh(org)
    except IntegrityError:
        db.rollback()
        raise HTTPException(status_code=400, detail="组织名称已存在")

    LogService.create_log(
        db=db,
        operator_id=api_key.created_by,
        action_type=ActionType.ORG_UPDATE,
        ip_address=get_client_ip(request),
        details=_audit_details(
            api_key,
            {
                "resource": "organization",
                "organization_id": org.id,
                "changes": changes,
            },
        ),
    )
    logger.info(
        f"[admin-api] 更新组织: {org.name} (key_prefix={api_key.key_prefix})"
    )
    return org
