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 WebLimitService interface {
	GetWebLimit(ctx context.Context, id int64) (*model.WebLimit, error)
	AddWebLimit(ctx context.Context, req *v1.GeneralLimitRequireRequest) (int, error)
	UpdateWebLimit(ctx context.Context, req *v1.WebLimitSendRequest) error
	DeleteWebLimit(ctx context.Context, wafWebId int) (string, error)
}

func NewWebLimitService(
	service *Service,
	webLimitRepository repository.WebLimitRepository,
	require RequiredService,
	parser ParserService,
	crawler CrawlerService,
	host HostService,
) WebLimitService {
	return &webLimitService{
		Service:            service,
		webLimitRepository: webLimitRepository,
		required:           require,
		parser:             parser,
		crawler:            crawler,
		host:               host,
	}
}

type webLimitService struct {
	*Service
	webLimitRepository repository.WebLimitRepository
	required           RequiredService
	parser             ParserService
	crawler            CrawlerService
	host               HostService
}

func (s *webLimitService) Required(ctx context.Context, req v1.GeneralLimitRequireRequest) (v1.WebLimitSendRequest, error) {
	config, err := s.host.GetWebLimitConfig(ctx, req.HostId)
	if err != nil {
		return v1.WebLimitSendRequest{}, fmt.Errorf("获取配置限制失败: %w", err)
	}
	return v1.WebLimitSendRequest{
		Tag:         req.Tag,
		QpsCount:    config.QpsCount,
		QpsDuration: config.QpsDuration,
		RuleId:      req.RuleId,
	}, nil
}

func (s *webLimitService) GetWebLimit(ctx context.Context, id int64) (*model.WebLimit, error) {
	return s.webLimitRepository.GetWebLimit(ctx, id)
}

func (s *webLimitService) AddWebLimit(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,
		"qps_count":           required.QpsCount,
		"qps_duration":        required.QpsDuration,
		"waf_common_limit_id": required.RuleId,
		"comment":             "",
	}

	respBody, err := s.required.SendForm(ctx, "admin/info/waf_web_limit/new", "admin/new/waf_web_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)
	}
	webLimitIdBase, err := s.parser.GetRuleIdByColumnName(ctx, respBody, req.Tag)
	if err != nil {
		return 0, err
	}
	webLimitId, err := cast.ToIntE(webLimitIdBase)
	if err != nil {
		return 0, err
	}
	if webLimitId == 0 {
		res, err := s.parser.ParseAlert(string(respBody))
		if err != nil {
			return 0, err
		}
		return 0, fmt.Errorf(res)
	}
	return webLimitId, nil
}

func (s *webLimitService) UpdateWebLimit(ctx context.Context, req *v1.WebLimitSendRequest) error {
	formData := map[string]interface{}{
		"waf_web_limit_id":    req.WafWebLimitId,
		"tag":                 req.Tag,
		"qps_count":           req.QpsCount,
		"qps_duration":        req.QpsDuration,
		"waf_common_limit_id": req.RuleId,
		"comment":             "",
	}
	respBody, err := s.required.SendForm(ctx, "admin/info/waf_web_limit/edit?&__goadmin_edit_pk="+strconv.Itoa(req.WafWebLimitId), "admin/edit/waf_web_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 *webLimitService) DeleteWebLimit(ctx context.Context, WafWebLimitId int) (string, error) {
	res, err := s.crawler.DeleteRule(ctx, WafWebLimitId, "admin/delete/waf_web_limit?page=1&__pageSize=10&__sort=waf_web_limit_id&__sort_type=desc")
	if err != nil {
		return "", err
	}
	return res, nil
}
