package proxy_pool

import (
	"context"
	"encoding/json"
	"github.com/duke-git/lancet/v2/convertor"
	"strings"
	"time"

	"kami/internal/model"
	"kami/utility/cache"

	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/net/gclient"
)

type MinuteExpireStrategy struct {
	cache     *cache.Cache
	apiURL    string
	ttl       time.Duration
	validator *ProxyValidator
}

func NewMinuteExpireStrategy(apiURL string, ttl time.Duration) *MinuteExpireStrategy {
	return &MinuteExpireStrategy{
		cache:     cache.NewCache(),
		apiURL:    apiURL,
		ttl:       ttl,
		validator: NewProxyValidator(),
	}
}

func (s *MinuteExpireStrategy) GetProxy(ctx context.Context, orderId string) (*model.ProxyInfo, error) {
	key := cache.PrefixProxyPool.Key(orderId)

	result, err := s.cache.Get(ctx, key)
	if err != nil {
		return nil, gerror.Wrap(err, "获取代理缓存失败")
	}

	if result != nil && !result.IsNil() {
		var proxy model.ProxyInfo
		if err := json.Unmarshal(result.Bytes(), &proxy); err != nil {
			return nil, gerror.Wrap(err, "解析代理信息失败")
		}

		if s.validator.ValidateProxy(ctx, &proxy) {
			return &proxy, nil
		}

		_ = s.RemoveProxy(ctx, orderId)
	}

	proxy, err := s.validator.GetValidProxy(ctx, s.fetchProxyFromAPI)
	if err != nil {
		return nil, err
	}

	if err := s.SetProxy(ctx, orderId, proxy); err != nil {
		return nil, err
	}

	return proxy, nil
}

func (s *MinuteExpireStrategy) SetProxy(ctx context.Context, orderId string, proxy *model.ProxyInfo) error {
	key := cache.PrefixProxyPool.Key(orderId)

	data, err := json.Marshal(proxy)
	if err != nil {
		return gerror.Wrap(err, "序列化代理信息失败")
	}

	if err := s.cache.Set(ctx, key, data, s.ttl); err != nil {
		return gerror.Wrap(err, "设置代理缓存失败")
	}

	return nil
}

func (s *MinuteExpireStrategy) RemoveProxy(ctx context.Context, orderId string) error {
	key := cache.PrefixProxyPool.Key(orderId)

	if _, err := s.cache.Remove(ctx, key); err != nil {
		return gerror.Wrap(err, "删除代理缓存失败")
	}

	return nil
}

func (s *MinuteExpireStrategy) GetTTL(ctx context.Context, orderId string) (time.Duration, error) {
	key := cache.PrefixProxyPool.Key(orderId)

	ttl, err := s.cache.GetExpire(ctx, key)
	if err != nil {
		return 0, gerror.Wrap(err, "获取代理过期时间失败")
	}

	return ttl, nil
}

func (s *MinuteExpireStrategy) fetchProxyFromAPI(ctx context.Context) (*model.ProxyInfo, error) {
	client := gclient.New()

	resp, err := client.Get(ctx, s.apiURL)
	if err != nil {
		return nil, gerror.Wrap(err, "调用代理API失败")
	}
	defer resp.Close()

	if resp.StatusCode != 200 {
		return nil, gerror.Newf("代理API返回异常状态码: %d", resp.StatusCode)
	}

	ipList := strings.Split(resp.ReadAllString(), ":")
	if len(ipList) != 2 {
		return nil, gerror.New("代理API返回格式错误")
	}
	port, err := convertor.ToInt(ipList[1])
	if err != nil {
		return nil, gerror.Wrap(err, "代理API返回格式错误")
	}
	return &model.ProxyInfo{
		Host: ipList[0],
		Port: int(port),
		//Username: "8LO6KX52",
		//Password: "9583D10B85D9",
		Protocol: "socks5",
	}, nil
}
