package scheduler

import (
	"log"
	"strings"
	"time"

	"go-helper/internal/chatgpt"
	"go-helper/internal/database"
)

// StartTokenChecker runs a periodic loop that refreshes access tokens
// for all accounts that have a refresh token.
func StartTokenChecker(db *database.DB, client *chatgpt.Client, intervalMinutes int) {
	if intervalMinutes <= 0 {
		intervalMinutes = 30
	}
	interval := time.Duration(intervalMinutes) * time.Minute
	log.Printf("[Scheduler] Token 定时检测已启动，间隔 %d 分钟", intervalMinutes)

	go func() {
		// Run once immediately at startup.
		checkAndRefreshAll(db, client)

		ticker := time.NewTicker(interval)
		defer ticker.Stop()
		for range ticker.C {
			checkAndRefreshAll(db, client)
		}
	}()
}

func checkAndRefreshAll(db *database.DB, client *chatgpt.Client) {
	accounts, err := db.GetAccountsWithRT()
	if err != nil {
		log.Printf("[Scheduler] 获取账号列表失败: %v", err)
		return
	}

	if len(accounts) == 0 {
		return
	}

	log.Printf("[Scheduler] 开始检查 %d 个账号的 Token 状态", len(accounts))

	refreshed, failed, banned := 0, 0, 0
	for _, acc := range accounts {
		result, err := client.RefreshAccessToken(acc.RefreshToken)
		if err != nil {
			log.Printf("[Scheduler] 刷新失败 [ID=%d %s]: %v", acc.ID, acc.Email, err)
			failed++

			// Check if the error indicates token is completely invalid.
			errMsg := strings.ToLower(err.Error())
			if strings.Contains(errMsg, "invalid_grant") ||
				strings.Contains(errMsg, "token has been revoked") ||
				strings.Contains(errMsg, "unauthorized") {
				log.Printf("[Scheduler] RT 无效，标记封号 [ID=%d %s]", acc.ID, acc.Email)
				_ = db.BanAccount(acc.ID)
				banned++
			}
			continue
		}

		if err := db.UpdateAccountTokens(acc.ID, result.AccessToken, result.RefreshToken); err != nil {
			log.Printf("[Scheduler] 更新 Token 失败 [ID=%d]: %v", acc.ID, err)
			failed++
			continue
		}

		// Also try to fetch account info to update subscription expiry.
		infos, err := client.FetchAccountInfo(result.AccessToken)
		if err != nil {
			// Token works but account info fetch failed — might be account_deactivated.
			errMsg := strings.ToLower(err.Error())
			if strings.Contains(errMsg, "account_deactivated") || strings.Contains(errMsg, "已停用") {
				log.Printf("[Scheduler] 账号已停用，标记封号 [ID=%d %s]", acc.ID, acc.Email)
				_ = db.BanAccount(acc.ID)
				banned++
				continue
			}
		} else if len(infos) > 0 {
			// Update expire_at from subscription info.
			for _, info := range infos {
				if info.AccountID == acc.ChatgptAccountID && info.ExpiresAt != "" {
					_ = db.UpdateAccountInfo(acc.ID, acc.ChatgptAccountID, info.ExpiresAt)
					break
				}
			}
		}

		refreshed++
	}

	log.Printf("[Scheduler] 检查完成: 刷新成功 %d, 失败 %d, 封号 %d", refreshed, failed, banned)
}
