"""
審計日誌裝飾器和工具函數
"""
from functools import wraps
from typing import Callable, Optional
from fastapi import Request
from sqlalchemy.orm import Session


def get_current_username() -> str:
    """
    獲取當前用戶名稱

    TODO: 實作後從 JWT Token 獲取
    目前返回系統用戶
    """
    # TODO: 從 Keycloak JWT Token 解析用戶名
    return "system@porscheworld.tw"


def audit_log_decorator(
    action: str,
    resource_type: str,
    get_resource_id: Optional[Callable] = None,
    get_details: Optional[Callable] = None,
):
    """
    審計日誌裝飾器

    使用範例:
    @audit_log_decorator(
        action="create",
        resource_type="employee",
        get_resource_id=lambda result: result.id,
        get_details=lambda result: {"employee_id": result.employee_id}
    )
    def create_employee(...):
        pass

    Args:
        action: 操作類型
        resource_type: 資源類型
        get_resource_id: 從返回結果獲取資源 ID 的函數
        get_details: 從返回結果獲取詳細資訊的函數
    """
    def decorator(func: Callable):
        @wraps(func)
        async def async_wrapper(*args, **kwargs):
            # 執行原函數
            result = await func(*args, **kwargs)

            # 獲取 DB Session
            db: Optional[Session] = kwargs.get("db")
            if not db:
                return result

            # 獲取 Request (用於 IP)
            request: Optional[Request] = kwargs.get("request")
            ip_address = None
            if request:
                from app.services.audit_service import audit_service
                ip_address = audit_service.get_client_ip(request)

            # 獲取資源 ID
            resource_id = None
            if get_resource_id and result:
                resource_id = get_resource_id(result)

            # 獲取詳細資訊
            details = None
            if get_details and result:
                details = get_details(result)

            # 記錄審計日誌
            from app.services.audit_service import audit_service
            audit_service.log(
                db=db,
                action=action,
                resource_type=resource_type,
                resource_id=resource_id,
                performed_by=get_current_username(),
                details=details,
                ip_address=ip_address,
            )

            return result

        @wraps(func)
        def sync_wrapper(*args, **kwargs):
            # 執行原函數
            result = func(*args, **kwargs)

            # 獲取 DB Session
            db: Optional[Session] = kwargs.get("db")
            if not db:
                return result

            # 獲取 Request (用於 IP)
            request: Optional[Request] = kwargs.get("request")
            ip_address = None
            if request:
                from app.services.audit_service import audit_service
                ip_address = audit_service.get_client_ip(request)

            # 獲取資源 ID
            resource_id = None
            if get_resource_id and result:
                resource_id = get_resource_id(result)

            # 獲取詳細資訊
            details = None
            if get_details and result:
                details = get_details(result)

            # 記錄審計日誌
            from app.services.audit_service import audit_service
            audit_service.log(
                db=db,
                action=action,
                resource_type=resource_type,
                resource_id=resource_id,
                performed_by=get_current_username(),
                details=details,
                ip_address=ip_address,
            )

            return result

        # 檢查是否為異步函數
        import asyncio
        if asyncio.iscoroutinefunction(func):
            return async_wrapper
        else:
            return sync_wrapper

    return decorator
