package middleware

import (
	"context"

	"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"

	"github.com/labstack/echo/v4"
)

// AuditLogMiddleware 创建一个Echo中间件，用于在请求结束后记录用户操作审计日志。
// 它依赖于控制器通过调用 SendSuccessWithAudit 或 SendErrorWithAudit 在上下文中设置的审计信息。
func AuditLogMiddleware(ctx context.Context, auditService service.AuditService) echo.MiddlewareFunc {
	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			newCtx := logs.AddFuncName(c.Request().Context(), ctx, "AuditLogMiddleware")

			// 首先执行请求链中的后续处理程序（即业务控制器）
			err := next(c)

			// --- 在这里，请求已经处理完毕 ---

			// 从上下文中尝试获取由控制器设置的业务审计信息
			actionType, exists := c.Get(models.ContextAuditActionType.String()).(string)
			if !exists || actionType == "" {
				// 如果上下文中没有 actionType，说明此接口无需记录审计日志，直接返回
				return err
			}

			// 从 Context 中获取用户对象
			var user *models.User
			if userCtx := c.Get(models.ContextUserKey.String()); userCtx != nil {
				user, _ = userCtx.(*models.User)
			}

			// 构建 AuditRequestContext
			reqCtx := service.AuditRequestContext{
				ClientIP:   c.RealIP(),
				HTTPPath:   c.Request().URL.Path,
				HTTPMethod: c.Request().Method,
			}

			// 直接从上下文中获取所有其他审计信息
			description, _ := c.Get(models.ContextAuditDescription.String()).(string)
			targetResource := c.Get(models.ContextAuditTargetResource.String())
			status, _ := c.Get(models.ContextAuditStatus.String()).(models.AuditStatus)
			resultDetails, _ := c.Get(models.ContextAuditResultDetails.String()).(string)

			// 为异步任务创建一个分离的 Context，以防止原始请求的 Context 被取消
			detachedCtx := logs.DetachContext(newCtx)

			// 调用审计服务记录日志（异步）
			auditService.LogAction(
				detachedCtx,
				user,
				reqCtx,
				actionType,
				description,
				targetResource,
				status,
				resultDetails,
			)

			return err
		}
	}
}
