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"
)

// GetActiveHostSalaryPolicy 按周期读取主播工资政策，供 gateway 展示与该周期结算完全一致的规则。
func (s *Server) GetActiveHostSalaryPolicy(ctx context.Context, req *walletv1.GetActiveHostSalaryPolicyRequest) (*walletv1.GetActiveHostSalaryPolicyResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	policy, found, err := s.svc.GetActiveHostSalaryPolicy(ctx, req.GetAppCode(), req.GetRegionId(), req.GetSettlementMode(), req.GetSettlementTriggerMode(), req.GetCycleKey(), req.GetNowMs())
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	response := &walletv1.GetActiveHostSalaryPolicyResponse{Found: found}
	if found {
		response.Policy = hostSalaryPolicyToProto(policy)
	}
	return response, nil
}

// GetHostSalaryProgress 读取主播当前工资周期钻石累计，gateway 用它计算工资政策等级进度。
func (s *Server) GetHostSalaryProgress(ctx context.Context, req *walletv1.GetHostSalaryProgressRequest) (*walletv1.GetHostSalaryProgressResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	progress, err := s.svc.GetHostSalaryProgress(ctx, req.GetAppCode(), req.GetHostUserId(), req.GetCycleKey(), req.GetNowMs())
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.GetHostSalaryProgressResponse{Progress: hostSalaryProgressToProto(progress)}, nil
}

// GetTeamHostSalaryStats 按 Agency 收款人集合聚合主播预收入工资；gateway 经理中心概览调用。
func (s *Server) GetTeamHostSalaryStats(ctx context.Context, req *walletv1.GetTeamHostSalaryStatsRequest) (*walletv1.GetTeamHostSalaryStatsResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	stats, err := s.svc.GetTeamHostSalaryStats(ctx, req.GetAppCode(), ledger.TeamHostSalaryStatsQuery{
		AgencyOwnerUserIDs: req.GetAgencyOwnerUserIds(),
		CycleKeys:          req.GetCycleKeys(),
		NowMs:              req.GetNowMs(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	response := &walletv1.GetTeamHostSalaryStatsResponse{
		Stats:        make([]*walletv1.TeamHostSalaryCycleStat, 0, len(stats)),
		ServerTimeMs: time.Now().UTC().UnixMilli(),
	}
	for _, stat := range stats {
		response.Stats = append(response.Stats, &walletv1.TeamHostSalaryCycleStat{
			CycleKey:                    stat.CycleKey,
			EstimatedHostSalaryUsdMinor: stat.EstimatedHostSalaryUSDMinor,
			SettledHostSalaryUsdMinor:   stat.SettledHostSalaryUSDMinor,
			ActiveHostCount:             int32(stat.ActiveHostCount),
			TotalDiamonds:               stat.TotalDiamonds,
		})
	}
	return response, nil
}

func hostSalaryProgressToProto(progress ledger.HostSalaryProgress) *walletv1.HostSalaryProgress {
	return &walletv1.HostSalaryProgress{
		HostUserId:        progress.HostUserID,
		CycleKey:          progress.CycleKey,
		RegionId:          progress.RegionID,
		AgencyOwnerUserId: progress.AgencyOwnerUserID,
		TotalDiamonds:     progress.TotalDiamonds,
		GiftDiamondTotal:  progress.GiftDiamondTotal,
		UpdatedAtMs:       progress.UpdatedAtMS,
	}
}

func hostSalaryPolicyToProto(policy ledger.HostSalaryPolicy) *walletv1.HostSalaryPolicy {
	levels := make([]*walletv1.HostSalaryPolicyLevel, 0, len(policy.Levels))
	for _, level := range policy.Levels {
		levels = append(levels, hostSalaryPolicyLevelToProto(level))
	}
	return &walletv1.HostSalaryPolicy{
		PolicyId:                          policy.PolicyID,
		CycleKey:                          policy.CycleKey,
		PolicyVersion:                     policy.PolicyVersion,
		Name:                              policy.Name,
		PolicyType:                        policy.PolicyType,
		RegionId:                          policy.RegionID,
		Status:                            policy.Status,
		SettlementMode:                    policy.SettlementMode,
		SettlementTriggerMode:             policy.SettlementTriggerMode,
		GiftCoinToDiamondRatio:            policy.GiftCoinToDiamondRatio,
		PointDiamondsPerUsd:               policy.PointDiamondsPerUSD,
		CoinsPerUsd:                       policy.CoinsPerUSD,
		MinimumWithdrawUsdMinor:           policy.MinimumWithdrawUSDMinor,
		CoinSellerMinimumWithdrawUsdMinor: policy.CoinSellerMinimumWithdrawUSDMinor,
		PlatformMinimumWithdrawUsdMinor:   policy.PlatformMinimumWithdrawUSDMinor,
		DiamondExchangeEnabled:            policy.DiamondExchangeEnabled,
		WithdrawFeeBps:                    policy.WithdrawFeeBPS,
		AgencyPointShareBps:               policy.AgencyPointShareBPS,
		ResidualDiamondToUsdRate:          policy.ResidualDiamondToUSDRate,
		EffectiveFromMs:                   policy.EffectiveFromMs,
		EffectiveToMs:                     policy.EffectiveToMs,
		Levels:                            levels,
	}
}

func hostSalaryPolicyLevelToProto(level ledger.HostSalaryPolicyLevel) *walletv1.HostSalaryPolicyLevel {
	return &walletv1.HostSalaryPolicyLevel{
		LevelNo:              int32(level.LevelNo),
		RequiredDiamonds:     level.RequiredDiamonds,
		HostSalaryUsdMinor:   level.HostSalaryUSDMinor,
		HostCoinReward:       level.HostCoinReward,
		AgencySalaryUsdMinor: level.AgencySalaryUSDMinor,
		Status:               level.Status,
		SortOrder:            int32(level.SortOrder),
	}
}
