package service

import (
	"context"
	"fmt"
	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
	"github.com/go-nunu/nunu-layout-advanced/internal/model"
	"github.com/go-nunu/nunu-layout-advanced/internal/repository"
	"github.com/spf13/cast"
	"strconv"
)

type UdpLimitService interface {
	GetUdpLimit(ctx context.Context, id int64) (*model.UdpLimit, error)
	AddUdpLimit(ctx context.Context, req *v1.GeneralLimitRequireRequest) (int, error)
	UpdateUdpLimit(ctx context.Context, req *v1.UdpLimitSendRequest) error
	DeleteUdpLimit(ctx context.Context, UdpLimitId int) (string, error)
}

func NewUdpLimitService(
	service *Service,
	udpLimitRepository repository.UdpLimitRepository,
	required RequiredService,
	crawler CrawlerService,
	parser ParserService,
	host HostService,
) UdpLimitService {
	return &udpLimitService{
		Service:            service,
		udpLimitRepository: udpLimitRepository,
		required:           required,
		crawler:            crawler,
		parser:             parser,
		host:               host,
	}
}

type udpLimitService struct {
	*Service
	udpLimitRepository repository.UdpLimitRepository
	required           RequiredService
	crawler            CrawlerService
	parser             ParserService
	host               HostService
}

func (s *udpLimitService) Required(ctx context.Context, req v1.GeneralLimitRequireRequest) (v1.UdpLimitSendRequest, error) {
	config, err := s.host.GetUdpLimitConfig(ctx, req.HostId)
	if err != nil {
		return v1.UdpLimitSendRequest{}, fmt.Errorf("获取配置限制失败: %w", err)
	}
	return v1.UdpLimitSendRequest{
		Tag:               req.Tag,
		QosPacketCount:    config.QosPacketCount,
		QosPacketDuration: config.QosPacketDuration,
		MaxConnCount:      config.MaxConnCount,
		RuleId:            req.RuleId,
	}, nil
}
func (s *udpLimitService) GetUdpLimit(ctx context.Context, id int64) (*model.UdpLimit, error) {
	return s.udpLimitRepository.GetUdpLimit(ctx, id)
}

func (s *udpLimitService) AddUdpLimit(ctx context.Context, req *v1.GeneralLimitRequireRequest) (int, error) {
	required, err := s.Required(ctx, *req)
	if err != nil {
		return 0, err
	}
	formData := map[string]interface{}{
		"tag":                 req.Tag,
		"qos_packet_count":    required.QosPacketCount,
		"qos_packet_duration": required.QosPacketDuration,
		"max_conn_count":      required.MaxConnCount,
		"waf_common_limit_id": required.RuleId,
		"comment":             "",
	}
	respBody, err := s.required.SendForm(ctx, "admin/info/waf_udp_limit/new", "admin/new/waf_udp_limit", formData)
	if err != nil {
		return 0, err
	}
	// 解析响应内容中的 alert 消息
	res, err := s.parser.ParseAlert(string(respBody))
	if err != nil {
		return 0, err
	}
	if res != "" {
		return 0, fmt.Errorf(res)
	}
	udpLimitIdBase, err := s.parser.GetRuleIdByColumnName(ctx, respBody, req.Tag)
	if err != nil {
		return 0, err
	}
	udpLimitId, err := cast.ToIntE(udpLimitIdBase)
	if err != nil {
		return 0, err
	}
	if udpLimitId == 0 {
		res, err := s.parser.ParseAlert(string(respBody))
		if err != nil {
			return 0, err
		}
		return 0, fmt.Errorf(res)
	}
	return udpLimitId, nil
}

func (s *udpLimitService) UpdateUdpLimit(ctx context.Context, req *v1.UdpLimitSendRequest) error {
	formData := map[string]interface{}{
		"tag":                 req.Tag,
		"waf_udp_limit_id":    req.WafUdpLimitId,
		"qos_packet_count":    req.QosPacketCount,
		"qos_packet_duration": req.QosPacketDuration,
		"max_conn_count":      req.MaxConnCount,
		"waf_common_limit_id": req.RuleId,
		"comment":             "",
	}
	respBody, err := s.required.SendForm(ctx, "admin/info/waf_udp_limit/edit?&__goadmin_edit_pk="+strconv.Itoa(req.WafUdpLimitId), "admin/edit/waf_udp_limit", formData)
	if err != nil {
		return err
	}
	// 解析响应内容中的 alert 消息
	res, err := s.parser.ParseAlert(string(respBody))
	if err != nil {
		return err
	}
	if res != "" {
		return fmt.Errorf(res)
	}
	return nil
}

func (s *udpLimitService) DeleteUdpLimit(ctx context.Context, WafUdpLimitId int) (string, error) {
	res, err := s.crawler.DeleteRule(ctx, WafUdpLimitId, "admin/delete/waf_udp_limit?page=1&__pageSize=10&__sort=waf_udp_limit_id&__sort_type=desc")
	if err != nil {
		return "", err
	}
	return res, nil
}
