package admin_agent

import (
	"context"
	"sort"

	"sim-server/app/main/api/internal/svc"
	"sim-server/app/main/api/internal/types"
	"sim-server/app/main/model"

	"github.com/zeromicro/go-zero/core/logx"
)

type AdminGetProductDistributionLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewAdminGetProductDistributionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetProductDistributionLogic {
	return &AdminGetProductDistributionLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *AdminGetProductDistributionLogic) AdminGetProductDistribution() (resp *types.AdminGetProductDistributionResp, err error) {
	// 1. Query all commissions
	builder := l.svcCtx.AgentCommissionModel.SelectBuilder()

	commissions, err := l.svcCtx.AgentCommissionModel.FindAll(l.ctx, builder, "")
	if err != nil {
		return nil, err
	}

	// 2. Collect all product IDs
	productIds := make([]string, 0, len(commissions))
	productIDSet := make(map[string]bool)
	for _, commission := range commissions {
		if !productIDSet[commission.ProductId] {
			productIDSet[commission.ProductId] = true
			productIds = append(productIds, commission.ProductId)
		}
	}

	// 3. Query products
	var products []*model.Product
	if len(productIds) > 0 {
		products, err = l.svcCtx.ProductModel.FindAll(l.ctx,
			l.svcCtx.ProductModel.SelectBuilder(), "")
		if err != nil {
			return nil, err
		}
	}

	// 4. Build product name map
	productNameMap := make(map[string]string)
	for _, product := range products {
		productNameMap[product.Id] = product.ProductName
	}

	// 5. Group by product in Go
	productStats := make(map[string]*struct {
		Count  int64
		Amount float64
	})

	for _, commission := range commissions {
		productName := productNameMap[commission.ProductId]
		if productName == "" {
			productName = "未知产品"
		}

		if _, exists := productStats[productName]; !exists {
			productStats[productName] = &struct {
				Count  int64
				Amount float64
			}{}
		}
		productStats[productName].Count++
		productStats[productName].Amount += commission.Amount
	}

	// 6. Sort by amount descending
	type ProductStat struct {
		Name   string
		Count  int64
		Amount float64
	}

	stats := make([]ProductStat, 0, len(productStats))
	for name, stat := range productStats {
		stats = append(stats, ProductStat{
			Name:   name,
			Count:  stat.Count,
			Amount: stat.Amount,
		})
	}

	sort.Slice(stats, func(i, j int) bool {
		return stats[i].Amount > stats[j].Amount
	})

	// 7. Build response
	productNames := make([]string, len(stats))
	counts := make([]int64, len(stats))
	amounts := make([]float64, len(stats))

	for i, stat := range stats {
		productNames[i] = stat.Name
		counts[i] = stat.Count
		amounts[i] = stat.Amount
	}

	return &types.AdminGetProductDistributionResp{
		Products: productNames,
		Counts:   counts,
		Amounts:  amounts,
	}, nil
}
