package service

import (
	"context"
	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"
	"strings"
	"time"
)

// HostService 接口定义
type HostService interface {
	GetHost(ctx context.Context, id int64) (*model.Host, error)
	GetGameShieldConfig(ctx context.Context, hostId int) (v1.GameShieldHostBackendConfigResponse, error)
	GetGlobalLimitConfig(ctx context.Context, hostId int) (v1.GlobalLimitConfigResponse, error)
	// 检查是否过期 到期false 未到期true
	CheckExpired(ctx context.Context, uid int64, hostId int64) (bool, error)
}

func NewHostService(
	service *Service,
	hostRepository repository.HostRepository,
) HostService {
	return &hostService{
		Service:        service,
		hostRepository: hostRepository,
	}
}

// 常量定义，包含新增的配置项名称
const (
	ConfigOnlineDevices        = "在线设备数"
	ConfigRuleEntries          = "规则条目"
	ConfigMaxBandwidth         = "高带宽转发规则条目"
	ConfigSourceMachines       = "支持源机"
	ConfigBps                  = "带宽"
	ConfigMaxProtection      = "高防防护能力"
	ConfigPortCount 		   = "防御端口数量"
	ConfigDomainCount          = "防御域名（需要备案）"
	ConfigOperator             = "高防线路"
	ConfigIpCount              = "高防节点IP"
	NodeArea                   = "节点区域"
	IsBanUdp                   = "UDP协议"
	IsBanOverseas              = "海外访问"
)

// unitSuffixMap 存储需要去除的单位后缀
var unitSuffixMap = map[string]string{
	ConfigOnlineDevices: "个",
	ConfigRuleEntries:   "个",
	ConfigMaxBandwidth:  "条",
	ConfigIpCount:      "个",
}

type hostService struct {
	*Service
	hostRepository repository.HostRepository
}

func (s *hostService) GetHost(ctx context.Context, id int64) (*model.Host, error) {
	return s.hostRepository.GetHost(ctx, id)
}

// GetHostConfig 保持不变，它是一个通用的底层数据获取方法。
func (s *hostService) GetHostConfig(ctx context.Context, hostId int) ([]map[string]string, error) {
	configOptions, err := s.hostRepository.GetHostConfig(ctx, hostId)
	if err != nil {
		return nil, err
	}

	// 2. 收集ID和建立映射关系 (优化部分)
	var configIDs []int
	// 只收集那些我们需要查询详情的 option ID
	var optionIDsToFetch []int
	optionMap := make(map[int]int)
	qtyMap := make(map[int]int)

	for _, item := range configOptions {
		configIDs = append(configIDs, item.Configid)
		qtyMap[item.Configid] = item.Qty

		// 核心优化：只有当数量为0时，我们才需要Option的名称，
		// 因此才需要记录其ID用于后续查询，并建立 configID -> optionID 的映射。
		if item.Qty == 0 {
			optionIDsToFetch = append(optionIDsToFetch, item.Optionid)
			optionMap[item.Configid] = item.Optionid
		}
	}

	// 3. 获取配置和选项数据
	var configs []v1.ProductConfigOption
	if len(configIDs) > 0 {
		configs, err = s.hostRepository.GetProductConfigOption(ctx, configIDs)
		if err != nil {
			return nil, err
		}
	}

	// 只有在确实需要查询的情况下才执行
	var options []v1.ProductConfigOptionSub
	if len(optionIDsToFetch) > 0 {
		options, err = s.hostRepository.GetProductConfigOptionSub(ctx, optionIDsToFetch)
		if err != nil {
			return nil, err
		}
	}

	// 4. 转换选项为关联数组
	optionsByID := make(map[int]v1.ProductConfigOptionSub)
	for _, option := range options {
		optionsByID[option.ID] = option
	}

	// 5. 构建结果数据 (逻辑更清晰)
	var data []map[string]string
	for _, config := range configs {
		var optionName string

		// 直接通过qtyMap判断，逻辑更直接
		if qty := qtyMap[config.ID]; qty != 0 {
			// 如果数量不为0，直接使用数量作为名称
			optionName = strconv.Itoa(qty)
		} else {
			// 否则，我们知道它一定在 optionMap 和 optionsByID 中 (如果数据一致)
			optionID := optionMap[config.ID] // 这个查找现在是必要的
			if opt, ok := optionsByID[optionID]; ok {
				optionName = opt.OptionName
			}
		}

		data = append(data, map[string]string{
			"config_name": config.OptionName,
			"option_name": optionName,
		})
	}
	return data, nil
}

// cleanConfigOptionName 简化后的清理函数，直接返回清理后的字符串。
func (s *hostService) cleanConfigOptionName(configName string, optionName string) string {
	// 根据配置名称去除相应的单位后缀
	if suffix, ok := unitSuffixMap[configName]; ok {
		optionName = strings.TrimSuffix(optionName, suffix)
	}
	return optionName
}

// getHostConfigsMap 新增的辅助函数，用于获取所有清理后的配置映射。
func (s *hostService) getHostConfigsMap(ctx context.Context, hostId int) (map[string]string, error) {
	baseData, err := s.GetHostConfig(ctx, hostId)
	if err != nil {
		return nil, err
	}

	configsMap := make(map[string]string)
	for _, item := range baseData {
		configName := item["config_name"]
		optionName := item["option_name"]
		// 将清理后的值存储到 map 中
		configsMap[configName] = s.cleanConfigOptionName(configName, optionName)
	}
	return configsMap, nil
}

func (s *hostService) GetGameShieldConfig(ctx context.Context, hostId int) (v1.GameShieldHostBackendConfigResponse, error) {
	// 调用新辅助函数获取处理好的配置映射
	configsMap, err := s.getHostConfigsMap(ctx, hostId)
	if err != nil {
		return v1.GameShieldHostBackendConfigResponse{}, err
	}

	var data v1.GameShieldHostBackendConfigResponse
	var parseErr error // 用于统一处理类型转换错误

	// 从映射中获取值并进行类型转换
	if val, ok := configsMap[ConfigOnlineDevices]; ok {
		data.OnlineDevicesCount, parseErr = cast.ToInt64E(val)
		if parseErr != nil {
			return data, parseErr
		}
	}
	if val, ok := configsMap[ConfigRuleEntries]; ok {
		data.RuleEntriesCount, parseErr = cast.ToInt64E(val)
		if parseErr != nil {
			return data, parseErr
		}
	}
	if val, ok := configsMap[ConfigMaxBandwidth]; ok {
		data.MaxBandwidthCount, parseErr = cast.ToInt64E(val)
		if parseErr != nil {
			return data, parseErr
		}
	}
	if val, ok := configsMap[ConfigSourceMachines]; ok {
		data.SourceMachinesCount, parseErr = cast.ToInt64E(val)
		if parseErr != nil {
			return data, parseErr
		}
	}
	return data, nil
}

func (s *hostService) GetGlobalLimitConfig(ctx context.Context, hostId int) (v1.GlobalLimitConfigResponse, error) {
	configsMap, err := s.getHostConfigsMap(ctx, hostId)
	if err != nil {
		return v1.GlobalLimitConfigResponse{}, err
	}
	data := v1.GlobalLimitConfigResponse{
		MaxBytesMonth: "0",
		Bps:           "0",
		IpCount:       0,
		Operator:      0,
		NodeArea:      "",
		ConfigMaxProtection: "",
		IsBanUdp:      0,
	}
	if val, ok := configsMap[ConfigBps]; ok {
		data.Bps = val
	}
	//if val, ok := configsMap[ConfigMaxBytesMonth]; ok {
	//	data.MaxBytesMonth = val
	//}
	if val, ok := configsMap[ConfigPortCount]; ok {
		data.PortCount, err = cast.ToIntE(val)
		if err != nil {
			return data, err
		}
	}
	if val, ok := configsMap[ConfigDomainCount]; ok {
		data.DomainCount, err = cast.ToIntE(val)
		if err != nil {
			return data, err
		}
	}
	if val, ok := configsMap[ConfigOperator]; ok {
		if val == "电信" {
			data.IpCount = 1
		}
		if val == "BGP" {
			data.IpCount = 2
		}
	}
	if val, ok := configsMap[ConfigIpCount]; ok {
		data.Operator, err = cast.ToIntE(val)
		if err != nil {
			return data, err
		}
	}

	if val, ok := configsMap[NodeArea]; ok {
		data.NodeArea = val
	}

	if val, ok := configsMap[ConfigMaxProtection]; ok {
		data.ConfigMaxProtection = val
	}

	if val, ok := configsMap[IsBanUdp]; ok {
		if val == "开通" {
			data.IsBanUdp = 0
		}
		if val == "关闭" {
			data.IsBanUdp = 1
		}
	}

	if val, ok := configsMap[IsBanOverseas]; ok {
		if val == "开放" {
			data.IsBanOverseas = 0
		}
		if val == "封堵" {
			data.IsBanOverseas = 1
		}
	}
	return data, nil
}

// GetTcpLimitConfig 修正返回类型，并使用新的辅助函数

// 检查是否过期 到期false 未到期true
func (s *hostService) CheckExpired(ctx context.Context, uid int64, hostId int64) (bool, error) {
	var expireTime string
	expireTime, err := s.hostRepository.GetExpireTime(ctx, uid, hostId)
	if err != nil {
		return false, err
	}
	if expireTime == "" {
		return true, nil
	}
	unixTime, err := strconv.ParseInt(expireTime, 10, 64)
	if err != nil {
		return false, err
	}
	now := time.Now().Unix() // 当前时间戳（秒级）
	if now > unixTime {
		return false, nil
	}

	return true, nil
}