package service

import (
	"fmt"
	"one-api/common"
	"one-api/constant"
	"one-api/model"
	"strings"
	"time"

	"github.com/bytedance/gopkg/util/gopool"
)

// StartClaudeTokenRefreshScheduler starts the scheduled token refresh for Claude Code channels
func StartClaudeTokenRefreshScheduler() {
	ticker := time.NewTicker(5 * time.Minute)
	gopool.Go(func() {
		defer ticker.Stop()
		for range ticker.C {
			RefreshClaudeCodeTokens()
		}
	})
	common.SysLog("Claude Code token refresh scheduler started (5 minute interval)")
}

// RefreshClaudeCodeTokens refreshes tokens for all active Claude Code channels
func RefreshClaudeCodeTokens() {
	var channels []model.Channel

	// Get all active Claude Code channels
	err := model.DB.Where("type = ? AND status = ?", constant.ChannelTypeClaudeCode, common.ChannelStatusEnabled).Find(&channels).Error
	if err != nil {
		common.SysError("Failed to get Claude Code channels: " + err.Error())
		return
	}

	refreshCount := 0
	for _, channel := range channels {
		if refreshTokenForChannel(&channel) {
			refreshCount++
		}
	}

	if refreshCount > 0 {
		common.SysLog(fmt.Sprintf("Successfully refreshed %d Claude Code channel tokens", refreshCount))
	}
}

// refreshTokenForChannel attempts to refresh token for a single channel
func refreshTokenForChannel(channel *model.Channel) bool {
	// Parse key in format: accesstoken|refreshtoken
	if channel.Key == "" || !strings.Contains(channel.Key, "|") {
		common.SysError(fmt.Sprintf("Channel %d has invalid key format, expected accesstoken|refreshtoken", channel.Id))
		return false
	}

	parts := strings.Split(channel.Key, "|")
	if len(parts) < 2 {
		common.SysError(fmt.Sprintf("Channel %d has invalid key format, expected accesstoken|refreshtoken", channel.Id))
		return false
	}

	accessToken := parts[0]
	refreshToken := parts[1]

	if refreshToken == "" {
		common.SysError(fmt.Sprintf("Channel %d has empty refresh token", channel.Id))
		return false
	}

	// Check if token needs refresh (refresh 30 minutes before expiry)
	// if !shouldRefreshToken(accessToken) {
	// 	return false
	// }

	// Use shared refresh function
	newToken, err := RefreshClaudeToken(accessToken, refreshToken)
	if err != nil {
		common.SysError(fmt.Sprintf("Failed to refresh token for channel %d: %s", channel.Id, err.Error()))
		return false
	}

	// Update channel with new tokens
	newKey := fmt.Sprintf("%s|%s", newToken.AccessToken, newToken.RefreshToken)

	err = model.DB.Model(channel).Update("key", newKey).Error
	if err != nil {
		common.SysError(fmt.Sprintf("Failed to update channel %d with new token: %s", channel.Id, err.Error()))
		return false
	}

	common.SysLog(fmt.Sprintf("Successfully refreshed token for Claude Code channel %d (%s)", channel.Id, channel.Name))
	return true
}
