// Package middleware ...
//
// Description : middleware ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2026-01-04 14:17
package middleware

import (
	"fmt"
	"net/http"

	"git.zhangdeman.cn/zhangdeman/gin/define"
	"git.zhangdeman.cn/zhangdeman/gin/logger"
	"git.zhangdeman.cn/zhangdeman/gin/util"
	loggerPkg "git.zhangdeman.cn/zhangdeman/logger"
	"git.zhangdeman.cn/zhangdeman/rate_limit/abstract"
	rateLimitDefine "git.zhangdeman.cn/zhangdeman/rate_limit/define"
	"github.com/gin-gonic/gin"
)

// RateLimit 接口流控
func RateLimit(rl abstract.IRateLimit, uriConfigTable map[string]define.UriConfig) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		if nil == rl {
			ctx.Next()
			return
		}
		requestUri := ctx.Request.URL.Path
		if _, exist := uriConfigTable[requestUri]; !exist {
			ctx.Next()
			return
		}
		if uriConfigTable[requestUri].RateLimitConfig.Total <= 0 || uriConfigTable[requestUri].RateLimitConfig.TimeInterval <= 0 {
			// 配置异常, 不做处理
			ctx.Next()
			return
		}
		var (
			allow bool
			err   error
		)

		if allow, err = rl.AllowN(ctx, &rateLimitDefine.LimitConfig{
			Key:          fmt.Sprintf("__gin_pkg_%v", requestUri), // TODO: 支持配置key的格式
			Total:        uriConfigTable[requestUri].RateLimitConfig.Total,
			Rate:         uriConfigTable[requestUri].RateLimitConfig.Use,
			TimeInterval: uriConfigTable[requestUri].RateLimitConfig.TimeInterval,
		}, uriConfigTable[requestUri].RateLimitConfig.Use); nil != err {
			// 留空处理出现异常, 默认放行, 避免放大问题, 但是记录 Error 日志
			logger.Instance.Error("无法正确执行流量控制程序", loggerPkg.NewLogData(util.GinCtxToContext(ctx), logger.RecordType, logger.CodeServiceRateLimitFailure, map[string]any{
				"err_msg": err.Error(),
			}).ToFieldList()...)
			ctx.Next()
			return
		}
		if !allow {
			logger.Instance.Error("流量负载已饱和, 请稍后再试", loggerPkg.NewLogData(util.GinCtxToContext(ctx), logger.RecordType, logger.CodeServiceRateLimitDisable, map[string]any{
				"rate_limit_config": uriConfigTable[requestUri].RateLimitConfig,
			}).ToFieldList()...)
			// 429 : Too Many Requests
			ctx.JSON(http.StatusTooManyRequests, gin.H{
				"err_msg": "流量负载已饱和, 请稍后再试",
			})
			ctx.Abort()
			return
		}
		// 流控校验通过
		ctx.Next()
	}
}
