package grpc

import (
	"context"
	"time"

	walletv1 "hyapp.local/api/proto/wallet/v1"
	"hyapp/pkg/appcode"
	"hyapp/pkg/xerr"
	"hyapp/services/wallet-service/internal/domain/ledger"
	walletservice "hyapp/services/wallet-service/internal/service/wallet"
)

// CronServer exposes wallet-service owned settlement batches to cron-service.
type CronServer struct {
	walletv1.UnimplementedWalletCronServiceServer

	svc *walletservice.Service
}

// NewCronServer 创建只给 cron-service 调用的批处理适配器；真实账务事务仍在 wallet repository 内完成。
func NewCronServer(svc *walletservice.Service) *CronServer {
	return &CronServer{svc: svc}
}

func (s *CronServer) ProcessHostSalaryDailySettlementBatch(ctx context.Context, req *walletv1.CronBatchRequest) (*walletv1.CronBatchResponse, error) {
	return s.processHostSalarySettlementBatch(ctx, req, ledger.HostSalarySettlementModeDaily)
}

func (s *CronServer) ProcessHostSalaryHalfMonthSettlementBatch(ctx context.Context, req *walletv1.CronBatchRequest) (*walletv1.CronBatchResponse, error) {
	return s.processHostSalarySettlementBatch(ctx, req, ledger.HostSalarySettlementModeHalfMonth)
}

func (s *CronServer) ProcessHostSalaryMonthEndBatch(ctx context.Context, req *walletv1.CronBatchRequest) (*walletv1.CronBatchResponse, error) {
	return s.processHostSalarySettlementBatch(ctx, req, ledger.HostSalarySettlementTypeMonthEnd)
}

// ProcessVipDailyCoinRebateBatch 只把 UTC task_day 和页大小交给 wallet owner；金额快照、
// 会员日切资格、游标和 available outbox 都在 wallet 的同一事务边界内完成。
func (s *CronServer) ProcessVipDailyCoinRebateBatch(ctx context.Context, req *walletv1.ProcessVipDailyCoinRebateBatchRequest) (*walletv1.ProcessVipDailyCoinRebateBatchResponse, error) {
	if s.svc == nil {
		return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "wallet service is not configured"))
	}
	appCode := appcode.Normalize(req.GetAppCode())
	ctx = appcode.WithContext(ctx, appCode)
	result, err := s.svc.ProcessVipDailyCoinRebateBatch(ctx, ledger.ProcessVipDailyCoinRebateBatchCommand{
		AppCode: appCode, TaskDay: req.GetTaskDay(), BatchSize: int(req.GetBatchSize()),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.ProcessVipDailyCoinRebateBatchResponse{
		Run: vipDailyCoinRebateRunToProto(result.Run), ScannedCount: int32(result.ScannedCount),
		CreatedCount: int32(result.CreatedCount), HasMore: result.HasMore,
		ServerTimeMs: time.Now().UTC().UnixMilli(),
	}, nil
}

func (s *CronServer) processHostSalarySettlementBatch(ctx context.Context, req *walletv1.CronBatchRequest, settlementType string) (*walletv1.CronBatchResponse, error) {
	if s.svc == nil {
		return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "wallet service is not configured"))
	}
	appCode := appcode.Normalize(req.GetAppCode())
	ctx = appcode.WithContext(ctx, appCode)
	// cron-service 只决定触发哪类批次；周期、当前时间、幂等交易和余额入账全部由 wallet-service 统一裁决。
	result, err := s.svc.ProcessHostSalarySettlementBatch(ctx, ledger.HostSalarySettlementBatchCommand{
		AppCode:        appCode,
		RunID:          req.GetRunId(),
		WorkerID:       req.GetWorkerId(),
		BatchSize:      int(req.GetBatchSize()),
		SettlementType: settlementType,
		TriggerMode:    req.GetTriggerMode(),
		SettlementRole: req.GetSettlementRole(),
		CycleKey:       req.GetCycleKey(),
		UserIDs:        append([]int64(nil), req.GetUserIds()...),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.CronBatchResponse{
		ClaimedCount:   int32(result.ClaimedCount),
		ProcessedCount: int32(result.ProcessedCount),
		SuccessCount:   int32(result.SuccessCount),
		FailureCount:   int32(result.FailureCount),
		HasMore:        result.HasMore,
	}, nil
}
