package oci

import (
	"context"
	"fmt"
	"strings"
	"time"

	"github.com/oracle/oci-go-sdk/v65/common"
	"github.com/oracle/oci-go-sdk/v65/usageapi"
)

// CostQuery 是一次成本/用量分析的条件。
type CostQuery struct {
	StartTime   time.Time
	EndTime     time.Time
	Granularity string // DAILY / MONTHLY
	QueryType   string // COST / USAGE
	GroupBy     string // service / skuName / region 等维度
}

// CostItem 是一个时间桶内某分组维度的成本或用量。
type CostItem struct {
	TimeStart        *time.Time `json:"timeStart"`
	GroupValue       string     `json:"groupValue"`
	ComputedAmount   float32    `json:"computedAmount"`
	ComputedQuantity float32    `json:"computedQuantity"`
	Currency         string     `json:"currency"`
	Unit             string     `json:"unit,omitempty"`
}

// SummarizeCosts 实现 Client：调用 Usage API 汇总租户成本或用量。
func (c *RealClient) SummarizeCosts(ctx context.Context, cred Credentials, q CostQuery) ([]CostItem, error) {
	uc, err := usageapi.NewUsageapiClientWithConfigurationProvider(provider(cred))
	if err != nil {
		return nil, fmt.Errorf("new usageapi client: %w", err)
	}
	applyProxy(&uc.BaseClient, cred)
	details, err := buildUsageDetails(cred.TenancyOCID, q)
	if err != nil {
		return nil, err
	}
	var items []CostItem
	var page *string
	for {
		resp, err := uc.RequestSummarizedUsages(ctx, usageapi.RequestSummarizedUsagesRequest{
			RequestSummarizedUsagesDetails: details,
			Page:                           page,
		})
		if err != nil {
			return nil, fmt.Errorf("request summarized usages: %w", err)
		}
		for _, item := range resp.Items {
			items = append(items, toCostItem(item, q.GroupBy))
		}
		if resp.OpcNextPage == nil {
			return orEmpty(items), nil
		}
		page = resp.OpcNextPage
	}
}

func buildUsageDetails(tenancyOCID string, q CostQuery) (usageapi.RequestSummarizedUsagesDetails, error) {
	granularity, ok := usageapi.GetMappingRequestSummarizedUsagesDetailsGranularityEnum(strings.ToUpper(q.Granularity))
	if !ok {
		return usageapi.RequestSummarizedUsagesDetails{}, fmt.Errorf("cost query: unsupported granularity %q", q.Granularity)
	}
	queryType, ok := usageapi.GetMappingRequestSummarizedUsagesDetailsQueryTypeEnum(strings.ToUpper(q.QueryType))
	if !ok {
		return usageapi.RequestSummarizedUsagesDetails{}, fmt.Errorf("cost query: unsupported queryType %q", q.QueryType)
	}
	return usageapi.RequestSummarizedUsagesDetails{
		TenantId:         &tenancyOCID,
		TimeUsageStarted: &common.SDKTime{Time: q.StartTime},
		TimeUsageEnded:   &common.SDKTime{Time: q.EndTime},
		Granularity:      granularity,
		QueryType:        queryType,
		GroupBy:          []string{q.GroupBy},
	}, nil
}

// toCostItem 把响应条目转为本地 DTO，分组值按 groupBy 维度取对应字段。
func toCostItem(item usageapi.UsageSummary, groupBy string) CostItem {
	out := CostItem{
		Currency: deref(item.Currency),
		Unit:     deref(item.Unit),
	}
	if item.TimeUsageStarted != nil {
		out.TimeStart = &item.TimeUsageStarted.Time
	}
	if item.ComputedAmount != nil {
		out.ComputedAmount = *item.ComputedAmount
	}
	if item.ComputedQuantity != nil {
		out.ComputedQuantity = *item.ComputedQuantity
	}
	switch strings.ToLower(groupBy) {
	case "skuname":
		out.GroupValue = deref(item.SkuName)
	case "region":
		out.GroupValue = deref(item.Region)
	case "compartmentname":
		out.GroupValue = deref(item.CompartmentName)
	default:
		out.GroupValue = deref(item.Service)
	}
	return out
}
