package integration

import (
	"context"
	"time"

	walletv1 "hyapp.local/api/proto/wallet/v1"
	"hyapp/services/cron-service/internal/scheduler"
)

// WalletCronClient delegates wallet-owned salary settlement batches to wallet-service.
type WalletCronClient struct {
	client walletv1.WalletCronServiceClient
}

var walletCronNowUTC = func() time.Time {
	return time.Now().UTC()
}

// NewWalletCronClient creates scheduler handlers backed by wallet-service gRPC.
func NewWalletCronClient(client walletv1.WalletCronServiceClient) *WalletCronClient {
	return &WalletCronClient{client: client}
}

func (c *WalletCronClient) ProcessHostSalaryDailySettlementBatch(ctx context.Context, req scheduler.BatchRequest) (scheduler.BatchResult, error) {
	resp, err := c.client.ProcessHostSalaryDailySettlementBatch(ctx, walletCronBatchRequest(req))
	return walletCronBatchResult(resp), err
}

// ProcessVIPDailyCoinRebateBatch 每分钟触发 wallet owner 的 UTC 日 run。cron 不传 task_day，
// 避免调度进程所在时区或延迟重启改变业务日期；wallet 会以自己的 UTC 时钟创建/复用当日快照。
func (c *WalletCronClient) ProcessVIPDailyCoinRebateBatch(ctx context.Context, req scheduler.BatchRequest) (scheduler.BatchResult, error) {
	resp, err := c.client.ProcessVipDailyCoinRebateBatch(ctx, &walletv1.ProcessVipDailyCoinRebateBatchRequest{
		RequestId: req.RunID,
		AppCode:   req.AppCode,
		BatchSize: int32(req.BatchSize),
	})
	if err != nil || resp == nil {
		return scheduler.BatchResult{}, err
	}
	return scheduler.BatchResult{
		ClaimedCount:   int(resp.GetScannedCount()),
		ProcessedCount: int(resp.GetScannedCount()),
		SuccessCount:   int(resp.GetCreatedCount()),
		HasMore:        resp.GetHasMore(),
	}, nil
}

func (c *WalletCronClient) ProcessHostSalaryHalfMonthSettlementBatch(ctx context.Context, req scheduler.BatchRequest) (scheduler.BatchResult, error) {
	if !isHostSalaryHalfMonthDue(walletCronNowUTC()) {
		// 半月结是否适用于某个主播由后台工资政策 settlement_mode 决定；cron 这里只负责在月中打开一次全局触发窗口。
		return scheduler.BatchResult{}, nil
	}
	resp, err := c.client.ProcessHostSalaryHalfMonthSettlementBatch(ctx, walletCronBatchRequest(req))
	return walletCronBatchResult(resp), err
}

func (c *WalletCronClient) ProcessHostSalaryMonthEndBatch(ctx context.Context, req scheduler.BatchRequest) (scheduler.BatchResult, error) {
	if !isHostSalaryMonthEndDue(walletCronNowUTC()) {
		// 月末批次负责最终等级差额、剩余钻石折美元和周期关闭；非月末触发只记录一次空跑，不进入 wallet 账务。
		return scheduler.BatchResult{}, nil
	}
	resp, err := c.client.ProcessHostSalaryMonthEndBatch(ctx, walletCronBatchRequest(req))
	return walletCronBatchResult(resp), err
}

func isHostSalaryHalfMonthDue(now time.Time) bool {
	return now.UTC().Day() == 15
}

func isHostSalaryMonthEndDue(now time.Time) bool {
	utc := now.UTC()
	return utc.AddDate(0, 0, 1).Day() == 1
}

func walletCronBatchRequest(req scheduler.BatchRequest) *walletv1.CronBatchRequest {
	// scheduler 的 RunID 同时作为请求幂等标识传给 wallet；wallet 内部会继续按主播和周期生成账务幂等键。
	return &walletv1.CronBatchRequest{
		RequestId: req.RunID,
		AppCode:   req.AppCode,
		RunId:     req.RunID,
		WorkerId:  req.WorkerID,
		BatchSize: int32(req.BatchSize),
		LockTtlMs: req.LockTTL.Milliseconds(),
	}
}

func walletCronBatchResult(resp *walletv1.CronBatchResponse) scheduler.BatchResult {
	if resp == nil {
		return scheduler.BatchResult{}
	}
	return scheduler.BatchResult{
		ClaimedCount:   int(resp.GetClaimedCount()),
		ProcessedCount: int(resp.GetProcessedCount()),
		SuccessCount:   int(resp.GetSuccessCount()),
		FailureCount:   int(resp.GetFailureCount()),
		HasMore:        resp.GetHasMore(),
	}
}
