package service

import (
	"context"
	"log/slog"
	"net/http"
	"sync"
	"time"

	"juhe-factory/api/internal/provider/apimart"

	"github.com/google/uuid"
)

type balanceChannel struct {
	ID               uuid.UUID
	Name             string
	BaseURL          string
	APIKeyCiphertext string
}

func (s *AdminData) triggerChannelBalanceSync() {
	if !s.balanceSyncing.CompareAndSwap(false, true) {
		return
	}
	go func() {
		defer s.balanceSyncing.Store(false)
		s.syncChannelBalances(context.Background())
	}()
}

func (s *AdminData) syncChannelBalances(ctx context.Context) {
	if s.Encryptor == nil {
		return
	}
	var channels []balanceChannel
	if err := s.DB.Table("channels").Select("id,name,base_url,api_key_ciphertext").
		Where("deleted_at IS NULL AND api_key_ciphertext IS NOT NULL AND api_key_ciphertext<>''").
		Find(&channels).Error; err != nil {
		slog.Warn("读取待同步渠道余额失败", "error", err)
		return
	}

	syncCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
	defer cancel()
	client := s.HTTPClient
	if client == nil {
		client = http.DefaultClient
	}

	var wait sync.WaitGroup
	for _, channel := range channels {
		channel := channel
		wait.Add(1)
		go func() {
			defer wait.Done()
			apiKey, err := s.Encryptor.Decrypt(channel.APIKeyCiphertext)
			if err != nil {
				slog.Warn("解密渠道 API Key 失败", "channel", channel.Name, "error", err)
				return
			}
			balance, err := apimart.NewClient(client).Balance(syncCtx, channel.BaseURL, apiKey)
			if err != nil {
				slog.Warn("同步渠道余额失败", "channel", channel.Name, "error", err)
				return
			}
			remainBalance := balance.RemainBalance
			if balance.UnlimitedQuota {
				remainBalance = -1
			}
			if err := s.DB.Exec(`INSERT INTO channel_balance_snapshots(channel_id,balance,currency,synced_at)
				VALUES(?,?,?,?)`, channel.ID, remainBalance, "USD", time.Now()).Error; err != nil {
				slog.Warn("保存渠道余额快照失败", "channel", channel.Name, "error", err)
			}
		}()
	}
	wait.Wait()
}
