package restriction

import (
	"context"
	"kami/api/restriction/v1"
	"kami/internal/consts"
	"kami/internal/errHandler"
	"kami/internal/model"
	"kami/internal/service"
	"net"

	"github.com/duke-git/lancet/v2/netutil"
	"github.com/duke-git/lancet/v2/pointer"
	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/os/glog"
)

func (c *ControllerV1) CheckIPAllowed(ctx context.Context, req *v1.CheckIPAllowedReq) (res *v1.CheckIPAllowedRes, err error) {
	res = &v1.CheckIPAllowedRes{}
	glog.Info(ctx, "开始获取IP，当前订单号", req.OrderNo, "当前IP", req.Ip)
	res.IsAllowed = false
	strategy, err := service.MerchantDeployInfo().GetRestrictStrategyById(ctx, req.MerchantDeployID)
	defer func() {
		var status consts.RestrictStatus
		if res.IsAllowed {
			status = consts.RestrictStatus_Enable
		} else {
			status = consts.RestrictStatus_Disable
		}
		_ = service.Restriction().AddToRestrictIP(ctx, model.AddRestrictionRecordInput{
			Ip:       req.Ip,
			DeviceId: req.DeviceId,
			Status:   status,
			Strategy: strategy,
			CardPass: req.CardPass,
			OrderNo:  req.OrderNo,
		})
		glog.Info(ctx, "当前订单号", req.OrderNo, "限制IP返回结果是：", res)
	}()
	if err != nil || pointer.IsNil(strategy) {
		err = errHandler.WrapError(ctx, gcode.CodeInternalError, err, "获取限制策略失败")
		return
	}
	if strategy.IsRestrictCardPass && service.Restriction().IsRestrictExistByCardPass(ctx, req.CardPass) {
		return
	}
	if strategy.IsRestrictDevice && service.Restriction().IsRestrictDevice(ctx, req.DeviceId) {
		return
	}
	if strategy.IsRestrictAgent && service.Restriction().CheckIsDeviceUseProxy(ctx, req.DeviceId, req.Ip) {
		return
	}
	if strategy.IsRestrictIp && netutil.IsPublicIP(net.ParseIP(req.Ip)) && service.Restriction().IsRestrictExistByIP(ctx, req.Ip) {
		return
	}
	if netutil.IsInternalIP(net.ParseIP(req.Ip)) {
		if !strategy.IsRestrictInternalIp {
			res.IsAllowed = true
		}
		return
	}
	if len(strategy.RestrictArea) > 0 {
		isAllowed, _ := service.Restriction().CheckIPIsAllowed(ctx, req.Ip, strategy.RestrictArea)
		res.IsAllowed = isAllowed
		return
	}
	res.IsAllowed = true
	return
}
