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 TcpLimitService interface {
	GetTcpLimit(ctx context.Context, id int64) (*model.TcpLimit, error)
	AddTcpLimit(ctx context.Context, req *v1.GeneralLimitRequireRequest) (int, error)
	UpdateTcpLimit(ctx context.Context, req *v1.TcpLimitSendRequest) error
	DeleteTcpLimit(ctx context.Context, TcpWebLimitId int) (string, error)
}

func NewTcpLimitService(
	service *Service,
	tcpLimitRepository repository.TcpLimitRepository,
	required RequiredService,
	parser ParserService,
	crawler CrawlerService,
	host HostService,
) TcpLimitService {
	return &tcpLimitService{
		Service:            service,
		tcpLimitRepository: tcpLimitRepository,
		required:           required,
		parser:             parser,
		crawler:            crawler,
		host:               host,
	}
}

type tcpLimitService struct {
	*Service
	tcpLimitRepository repository.TcpLimitRepository
	required           RequiredService
	parser             ParserService
	crawler            CrawlerService
	host               HostService
}

func (s *tcpLimitService) GetTcpLimit(ctx context.Context, id int64) (*model.TcpLimit, error) {
	return s.tcpLimitRepository.GetTcpLimit(ctx, id)
}

func (s *tcpLimitService) Required(ctx context.Context, req v1.GeneralLimitRequireRequest) (*v1.TcpLimitSendRequest, error) {
	configCount, err := s.host.GetTcpLimitConfig(ctx, req.HostId)
	if err != nil {
		return nil, fmt.Errorf("获取配置限制失败: %w", err)
	}
	return &v1.TcpLimitSendRequest{
		Tag:          req.Tag,
		ConnCount:    configCount.ConnCount,
		ConnDuration: configCount.ConnDuration,
		MaxConnCount: configCount.MaxConnCount,
		RuleId:       req.RuleId,
	}, nil
}
func (s *tcpLimitService) AddTcpLimit(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,
		"conn_count":          required.ConnCount,
		"conn_duration":       required.ConnDuration,
		"max_conn_count":      required.MaxConnCount,
		"waf_common_limit_id": required.RuleId,
		"comment":             "",
	}
	respBody, err := s.required.SendForm(ctx, "admin/info/waf_tcp_limit/new", "admin/new/waf_tcp_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)
	}
	tcpLimitIdBase, err := s.parser.GetRuleIdByColumnName(ctx, respBody, req.Tag)
	if err != nil {
		return 0, err
	}
	tcpLimitId, err := cast.ToIntE(tcpLimitIdBase)
	if err != nil {
		return 0, err
	}
	if tcpLimitId == 0 {
		res, err := s.parser.ParseAlert(string(respBody))
		if err != nil {
			return 0, err
		}
		return 0, fmt.Errorf(res)
	}
	return tcpLimitId, nil
}

func (s *tcpLimitService) UpdateTcpLimit(ctx context.Context, req *v1.TcpLimitSendRequest) error {
	formData := map[string]interface{}{
		"tag":                 req.Tag,
		"conn_count":          req.ConnCount,
		"conn_duration":       req.ConnDuration,
		"max_conn_count":      req.MaxConnCount,
		"waf_common_limit_id": req.RuleId,
		"comment":             "",
	}
	respBody, err := s.required.SendForm(ctx, "admin/info/waf_tcp_limit/edit?&__goadmin_edit_pk="+strconv.Itoa(req.WafTcpLimitId), "admin/edit/waf_tcp_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 *tcpLimitService) DeleteTcpLimit(ctx context.Context, TcpWebLimitId int) (string, error) {
	res, err := s.crawler.DeleteRule(ctx, TcpWebLimitId, "admin/delete/waf_tcp_limit?page=1&__pageSize=10&__sort=waf_tcp_limit_id&__sort_type=desc")
	if err != nil {
		return "", err
	}
	return res, nil
}
