package user

import (
	"context"
	"log/slog"
	"strings"
	"time"

	"hyapp/pkg/logx"
	userdomain "hyapp/services/user-service/internal/domain/user"
)

const (
	defaultRegionRebuildLockTTL   = 30 * time.Second
	defaultRegionRebuildBatchSize = 500
)

// RegionRebuildWorkerOptions 控制 cron-service 触发的单批 user_region_rebuild_tasks 处理边界。
type RegionRebuildWorkerOptions struct {
	// WorkerID 写入 task locked_by，便于排查某个节点是否卡住任务。
	WorkerID string
	// LockTTL 是单个 task claim 后允许本节点持有的最长时间，过期可被其他节点接管。
	LockTTL time.Duration
	// BatchSize 是单次最多更新的 users 数量，避免大国家全量更新长事务。
	BatchSize int
}

func normalizeRegionRebuildWorkerOptions(options RegionRebuildWorkerOptions) RegionRebuildWorkerOptions {
	options.WorkerID = strings.TrimSpace(options.WorkerID)
	if options.WorkerID == "" {
		options.WorkerID = "user-region-rebuild"
	}
	if options.LockTTL <= 0 {
		options.LockTTL = defaultRegionRebuildLockTTL
	}
	if options.BatchSize <= 0 {
		options.BatchSize = defaultRegionRebuildBatchSize
	}

	return options
}

// ProcessNextRegionRebuildTask 处理一个待重算任务；错误只影响本批，cron-service 下一轮继续触发。
func (s *Service) ProcessNextRegionRebuildTask(ctx context.Context, options RegionRebuildWorkerOptions) (userdomain.RegionRebuildProcessResult, error) {
	options = normalizeRegionRebuildWorkerOptions(options)
	if s.regionRebuildRepository == nil {
		return userdomain.RegionRebuildProcessResult{NoTask: true}, nil
	}

	result, err := s.regionRebuildRepository.ProcessNextRegionRebuildTask(ctx, options.WorkerID, s.now().UnixMilli(), options.LockTTL, options.BatchSize)
	if err != nil {
		logx.Error(ctx, "worker_batch_failed", err, slog.String("worker", "user_region_rebuild"), slog.String("worker_id", options.WorkerID), slog.Int("batch_size", options.BatchSize))
		return result, err
	}
	if result.NoTask {
		return result, nil
	}
	logx.Info(ctx, "worker_batch_processed",
		slog.String("worker", "user_region_rebuild"),
		slog.String("worker_id", options.WorkerID),
		slog.Int64("task_id", result.TaskID),
		slog.String("country", result.CountryCode),
		slog.Int64("target_region_id", result.TargetRegionID),
		slog.String("status", result.Status),
		slog.Int("processed_users", result.ProcessedUsers),
		slog.Int64("cursor_user_id", result.CursorUserID),
	)

	return result, nil
}
