package waf

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/api/waf"
	"github.com/go-nunu/nunu-layout-advanced/internal/service"
)

type AllowAndDenyIpService interface {
	GetAllowAndDenyIp(ctx context.Context, id int64) (*model.AllowAndDenyIp, error)
	GetAllowAndDenyIpsAllByHostId(ctx context.Context, hostId int64) ([]*model.AllowAndDenyIp, error)
	AddAllowAndDenyIps(ctx context.Context, req v1.AllowAndDenyIpRequest) (int, error)
	EditAllowAndDenyIps(ctx context.Context, req v1.AllowAndDenyIpRequest) error
	DeleteAllowAndDenyIps(ctx context.Context, req v1.DelAllowAndDenyIpRequest) error
}
func NewAllowAndDenyIpService(
    service *service.Service,
    allowAndDenyIpRepository waf.AllowAndDenyIpRepository,
	wafformatter WafFormatterService,
	gatewayIp GatewayipService,

) AllowAndDenyIpService {
	return &allowAndDenyIpService{
		Service:        service,
		allowAndDenyIpRepository: allowAndDenyIpRepository,
		wafformatter : wafformatter,
		gatewayIp : gatewayIp,
	}
}

type allowAndDenyIpService struct {
	*service.Service
	allowAndDenyIpRepository waf.AllowAndDenyIpRepository
	wafformatter             WafFormatterService
	gatewayIp                GatewayipService
}

func (s *allowAndDenyIpService) GetAllowAndDenyIp(ctx context.Context, id int64) (*model.AllowAndDenyIp, error) {
	res, err := s.allowAndDenyIpRepository.GetAllowAndDenyIp(ctx, id)
	if err != nil {
		return nil, err
	}
	return res, nil
}

func (s *allowAndDenyIpService) GetAllowAndDenyIpsAllByHostId(ctx context.Context, hostId int64) ([]*model.AllowAndDenyIp, error) {
	res, err := s.allowAndDenyIpRepository.GetAllowAndDenyIpsAllByHostId(ctx, hostId)
	if err != nil {
		return nil, err
	}
	return res, nil
}

func (s *allowAndDenyIpService) AddAllowAndDenyIps(ctx context.Context, req v1.AllowAndDenyIpRequest) (int, error) {
	// 判断ip是否存在
	err := s.IsExistIp(ctx, int64(req.HostId), req.Ip)
	if err != nil {
		return 0, err
	}


	gatewayGroupIps, err := s.gatewayIp.GetGatewayipOnlyIpByHostIdAll(ctx, int64(req.HostId), int64(req.Uid))
	if err != nil {
		return 0, err
	}
	if len(gatewayGroupIps) == 0 {
		return 0, fmt.Errorf("请先配置实例")
	}

	color := "black"
	if req.AllowOrDeny == 1 {
		color = "white"
	}


	for _, v := range gatewayGroupIps {
		go s.wafformatter.PublishIpWhitelistTask([]string{req.Ip}, "add",v,color)
	}
	id, err := s.allowAndDenyIpRepository.AddAllowAndDenyIps(ctx, model.AllowAndDenyIp{
		Ip:         req.Ip,
		HostId:     req.HostId,
		AllowOrDeny: req.AllowOrDeny,
		Uid:        req.Uid,
	});
	if err != nil {
		return 0, err
	}
	return id, nil
}

func (s *allowAndDenyIpService) EditAllowAndDenyIps(ctx context.Context, req v1.AllowAndDenyIpRequest) error {
	// 判断ip是否存在
	err := s.IsExistIp(ctx, int64(req.HostId), req.Ip)
	if err != nil {
		return err
	}


	gatewayGroupIps, err := s.gatewayIp.GetGatewayipOnlyIpByHostIdAll(ctx, int64(req.HostId), int64(req.Uid))
	if err != nil {
		return err
	}

	if len(gatewayGroupIps) == 0 {
		return fmt.Errorf("请先配置实例")
	}


	color := "black"
	if req.AllowOrDeny == 1 {
		color = "white"
	}
	oldIp, err := s.GetAllowAndDenyIp(ctx, int64(req.Id))
	if err != nil {
		return err
	}

	if oldIp.Ip != req.Ip {
		for _, v := range gatewayGroupIps {
			go s.wafformatter.PublishIpWhitelistTask([]string{oldIp.Ip}, "del",v,color)
		}
	}

	for _, v := range gatewayGroupIps {
		go s.wafformatter.PublishIpWhitelistTask([]string{req.Ip}, "add",v,color)
	}


	if err := s.allowAndDenyIpRepository.EditAllowAndDenyIps(ctx, model.AllowAndDenyIp{
		Id:         req.Id,
		Ip:         req.Ip,
		HostId:     req.HostId,
		AllowOrDeny: req.AllowOrDeny,
		Uid:        req.Uid,
	}); err != nil {
		return err
	}
	return nil
}

func (s *allowAndDenyIpService) DeleteAllowAndDenyIps(ctx context.Context, req v1.DelAllowAndDenyIpRequest) error {

	for _, id := range req.Ids {
		gatewayGroupIps, err := s.gatewayIp.GetGatewayipOnlyIpByHostIdAll(ctx, int64(req.HostId), int64(req.Uid))
		if err != nil {
			return err
		}


		ip, err := s.GetAllowAndDenyIp(ctx, int64(id))
		if err != nil {
			return err
		}
		color := "black"
		if ip.AllowOrDeny == 1 {
			color = "white"
		}
		for _, v := range gatewayGroupIps {
			go s.wafformatter.PublishIpWhitelistTask([]string{ip.Ip}, "del",v,color)
		}

		if err := s.allowAndDenyIpRepository.DeleteAllowAndDenyIps(ctx, int64(id)); err != nil {
			return err
		}
	}
	return nil
}

func (s *allowAndDenyIpService) IsExistIp(ctx context.Context, hostId int64, Ip string) error {
	count, err := s.allowAndDenyIpRepository.GetIpCount(ctx, hostId, Ip)
	if err != nil {
		return err
	}
	if count > 0 {
		return fmt.Errorf("ip已存在,请勿重复添加")
	}
	return nil
}
