package applogic

import (
	"fmt"
	"strconv"

	"aijianzhan/platform/internal/authx"
	"aijianzhan/platform/internal/types"
)

func (l *CrudLogic) Aggregate(slug, resource, groupBy, sumField string) (*types.AggregateResp, error) {
	tenantID := authx.TenantID(l.ctx)
	ref, err := l.svcCtx.Meta.ResolveResource(l.ctx, tenantID, slug, resource)
	if err != nil {
		return nil, err
	}
	if groupBy != "" {
		ok := false
		if ref.Resource.List != nil {
			for _, f := range ref.Resource.List.AllowedFilters {
				if f == groupBy {
					ok = true
					break
				}
			}
		}
		for _, f := range ref.Entity.Fields {
			if f.Name == groupBy {
				ok = true
				break
			}
		}
		if !ok {
			return nil, fmt.Errorf("group_by not allowed: %s", groupBy)
		}
	}
	items, total, err := l.svcCtx.CRUD.List(l.ctx, ref, tenantID, 1, 5000, nil, "")
	if err != nil {
		return nil, err
	}
	resp := &types.AggregateResp{Total: total, GroupBy: groupBy, SumField: sumField}
	if groupBy == "" {
		if sumField != "" {
			for _, it := range items {
				resp.Sum += toFloat(it[sumField])
			}
		}
		return resp, nil
	}
	buckets := map[string]*types.AggregateBucket{}
	order := []string{}
	for _, it := range items {
		key := fmt.Sprint(it[groupBy])
		if key == "" || key == "<nil>" {
			key = "(空)"
		}
		b, ok := buckets[key]
		if !ok {
			b = &types.AggregateBucket{Key: key}
			buckets[key] = b
			order = append(order, key)
		}
		b.Count++
		if sumField != "" {
			b.Sum += toFloat(it[sumField])
			resp.Sum += toFloat(it[sumField])
		}
	}
	for _, k := range order {
		resp.Buckets = append(resp.Buckets, *buckets[k])
	}
	return resp, nil
}

func toFloat(v any) float64 {
	switch t := v.(type) {
	case float64:
		return t
	case float32:
		return float64(t)
	case int:
		return float64(t)
	case int64:
		return float64(t)
	case string:
		n, _ := strconv.ParseFloat(t, 64)
		return n
	default:
		return 0
	}
}
