package grpc

import (
	"context"

	activityv1 "hyapp.local/api/proto/activity/v1"
	"hyapp/pkg/appcode"
	"hyapp/pkg/xerr"
	domain "hyapp/services/activity-service/internal/domain/roomturnoverreward"
	service "hyapp/services/activity-service/internal/service/roomturnoverreward"
)

// RoomTurnoverRewardServer 暴露 App 房间流水奖励查询入口。
type RoomTurnoverRewardServer struct {
	activityv1.UnimplementedRoomTurnoverRewardServiceServer

	svc *service.Service
}

func NewRoomTurnoverRewardServer(svc *service.Service) *RoomTurnoverRewardServer {
	return &RoomTurnoverRewardServer{svc: svc}
}

func (s *RoomTurnoverRewardServer) GetRoomTurnoverRewardStatus(ctx context.Context, req *activityv1.GetRoomTurnoverRewardStatusRequest) (*activityv1.GetRoomTurnoverRewardStatusResponse, error) {
	// AppCode 从 protobuf meta 写入 context，下面 service 和 repository 都按这个上下文隔离配置、流水和结算记录。
	ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
	status, err := s.svc.GetStatus(ctx, req.GetUserId(), req.GetRegionId(), req.GetRoomId(), req.GetOwnerUserId())
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &activityv1.GetRoomTurnoverRewardStatusResponse{Status: roomTurnoverRewardStatusToProto(status)}, nil
}

// AdminRoomTurnoverRewardServer 暴露后台配置、结算记录和 retry 入口。
type AdminRoomTurnoverRewardServer struct {
	activityv1.UnimplementedAdminRoomTurnoverRewardServiceServer

	svc *service.Service
}

func NewAdminRoomTurnoverRewardServer(svc *service.Service) *AdminRoomTurnoverRewardServer {
	return &AdminRoomTurnoverRewardServer{svc: svc}
}

func (s *AdminRoomTurnoverRewardServer) GetRoomTurnoverRewardConfig(ctx context.Context, req *activityv1.GetRoomTurnoverRewardConfigRequest) (*activityv1.GetRoomTurnoverRewardConfigResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
	config, err := s.svc.GetConfig(ctx, req.GetRegionId())
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &activityv1.GetRoomTurnoverRewardConfigResponse{Config: roomTurnoverRewardConfigToProto(config)}, nil
}

func (s *AdminRoomTurnoverRewardServer) UpdateRoomTurnoverRewardConfig(ctx context.Context, req *activityv1.UpdateRoomTurnoverRewardConfigRequest) (*activityv1.UpdateRoomTurnoverRewardConfigResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
	tiers := make([]domain.Tier, 0, len(req.GetTiers()))
	for _, tier := range req.GetTiers() {
		// protobuf 层只做字段转换，具体默认值、排序和合法性都留给 service，避免入口之间校验规则分叉。
		tiers = append(tiers, domain.Tier{
			TierID:             tier.GetTierId(),
			TierCode:           tier.GetTierCode(),
			TierName:           tier.GetTierName(),
			ThresholdCoinSpent: tier.GetThresholdCoinSpent(),
			RewardCoinAmount:   tier.GetRewardCoinAmount(),
			Status:             tier.GetStatus(),
			SortOrder:          tier.GetSortOrder(),
		})
	}
	config, err := s.svc.UpdateConfig(ctx, domain.Config{
		RegionID:         req.GetRegionId(),
		Enabled:          req.GetEnabled(),
		Tiers:            tiers,
		UpdatedByAdminID: req.GetOperatorAdminId(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &activityv1.UpdateRoomTurnoverRewardConfigResponse{Config: roomTurnoverRewardConfigToProto(config)}, nil
}

func (s *AdminRoomTurnoverRewardServer) ListRoomTurnoverRewardSettlements(ctx context.Context, req *activityv1.ListRoomTurnoverRewardSettlementsRequest) (*activityv1.ListRoomTurnoverRewardSettlementsResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
	// 查询条件完整透传到 domain query，分页上限由 service 统一收敛，后台和潜在内部工具不会各自实现分页规则。
	items, total, err := s.svc.ListSettlements(ctx, domain.SettlementQuery{
		RegionID:      req.GetRegionId(),
		Status:        req.GetStatus(),
		RoomID:        req.GetRoomId(),
		OwnerUserID:   req.GetOwnerUserId(),
		PeriodStartMS: req.GetPeriodStartMs(),
		Page:          req.GetPage(),
		PageSize:      req.GetPageSize(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	resp := &activityv1.ListRoomTurnoverRewardSettlementsResponse{
		Settlements: make([]*activityv1.RoomTurnoverRewardSettlement, 0, len(items)),
		Total:       total,
	}
	for _, item := range items {
		resp.Settlements = append(resp.Settlements, roomTurnoverRewardSettlementToProto(item))
	}
	return resp, nil
}

func (s *AdminRoomTurnoverRewardServer) RetryRoomTurnoverRewardSettlement(ctx context.Context, req *activityv1.RetryRoomTurnoverRewardSettlementRequest) (*activityv1.RetryRoomTurnoverRewardSettlementResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
	// operator_admin_id 当前只由 admin-server 审计使用；retry 的业务幂等仍由 settlement 和 wallet command_id 保证。
	settlement, err := s.svc.RetrySettlement(ctx, req.GetSettlementId())
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &activityv1.RetryRoomTurnoverRewardSettlementResponse{Settlement: roomTurnoverRewardSettlementToProto(settlement)}, nil
}

func roomTurnoverRewardStatusToProto(status domain.StatusResult) *activityv1.RoomTurnoverRewardStatus {
	return &activityv1.RoomTurnoverRewardStatus{
		Config:                   roomTurnoverRewardConfigToProto(status.Config),
		RoomId:                   status.RoomID,
		OwnerUserId:              status.OwnerUserID,
		PeriodStartMs:            status.PeriodStartMS,
		PeriodEndMs:              status.PeriodEndMS,
		CurrentCoinSpent:         status.CurrentCoinSpent,
		ExpectedRewardCoinAmount: status.ExpectedRewardCoinAmount,
		MatchedTier:              roomTurnoverRewardTierToProto(status.MatchedTier),
		LatestSettlement:         roomTurnoverRewardSettlementToProto(status.LatestSettlement),
		ServerTimeMs:             status.ServerTimeMS,
	}
}

func roomTurnoverRewardConfigToProto(config domain.Config) *activityv1.RoomTurnoverRewardConfig {
	resp := &activityv1.RoomTurnoverRewardConfig{
		AppCode:          config.AppCode,
		RegionId:         config.RegionID,
		Enabled:          config.Enabled,
		Tiers:            make([]*activityv1.RoomTurnoverRewardTier, 0, len(config.Tiers)),
		UpdatedByAdminId: config.UpdatedByAdminID,
		CreatedAtMs:      config.CreatedAtMS,
		UpdatedAtMs:      config.UpdatedAtMS,
	}
	for _, tier := range config.Tiers {
		resp.Tiers = append(resp.Tiers, roomTurnoverRewardTierToProto(tier))
	}
	return resp
}

func roomTurnoverRewardTierToProto(tier domain.Tier) *activityv1.RoomTurnoverRewardTier {
	if tier.TierID == 0 && tier.TierCode == "" {
		return nil
	}
	return &activityv1.RoomTurnoverRewardTier{
		TierId:             tier.TierID,
		TierCode:           tier.TierCode,
		TierName:           tier.TierName,
		ThresholdCoinSpent: tier.ThresholdCoinSpent,
		RewardCoinAmount:   tier.RewardCoinAmount,
		Status:             tier.Status,
		SortOrder:          tier.SortOrder,
		CreatedAtMs:        tier.CreatedAtMS,
		UpdatedAtMs:        tier.UpdatedAtMS,
	}
}

func roomTurnoverRewardSettlementToProto(item domain.Settlement) *activityv1.RoomTurnoverRewardSettlement {
	if item.SettlementID == "" {
		return nil
	}
	return &activityv1.RoomTurnoverRewardSettlement{
		SettlementId:        item.SettlementID,
		AppCode:             item.AppCode,
		RegionId:            item.RegionID,
		RoomId:              item.RoomID,
		OwnerUserId:         item.OwnerUserID,
		PeriodStartMs:       item.PeriodStartMS,
		PeriodEndMs:         item.PeriodEndMS,
		CoinSpent:           item.CoinSpent,
		TierId:              item.TierID,
		TierCode:            item.TierCode,
		ThresholdCoinSpent:  item.ThresholdCoinSpent,
		RewardCoinAmount:    item.RewardCoinAmount,
		Status:              item.Status,
		WalletCommandId:     item.WalletCommandID,
		WalletTransactionId: item.WalletTransactionID,
		FailureReason:       item.FailureReason,
		SettledAtMs:         item.SettledAtMS,
		CreatedAtMs:         item.CreatedAtMS,
		UpdatedAtMs:         item.UpdatedAtMS,
	}
}
