package billing

import (
	"context"
	"time"

	"github.com/pingcap-inc/pchub/internal/pkg/code"
	"github.com/pingcap-inc/pchub/model/v1/fao"
	"github.com/pingcap-inc/pchub/pkg/errors"
	"github.com/pingcap-inc/pchub/pkg/log"
)

// CloudBilling Filter and Order.
type BillingFAO struct {
	Filter  BillingFilter `json:"filter"`
	OrderBy fao.OrderBy   `json:"orderBy"`
}

type BillingFilter struct {
	Department         string   `json:"department"`
	Owner              string   `json:"owner"`
	Provider           int      `json:"provider"`
	DateBetween        []string `json:"dateBetween"`
	CompareDateBetween []string `json:"compareDateBetween"`
}

const (
	OrderByFieldCost = "cost"
)

func (r *BillingFAO) ValidateComplete(ctx context.Context) error {
	err := errors.WithCode(code.ErrValidation, "Invalid filter or orderBy")

	validOrderField := map[string]bool{
		OrderByFieldCost: true,
	}
	if r.OrderBy.Field != "" && !validOrderField[r.OrderBy.Field] {
		log.L(ctx).Error("OrderBy field: " + r.OrderBy.Field + " is not valid")

		return err
	}
	if r.OrderBy.Field == "" {
		r.OrderBy.Field = OrderByFieldCost
		r.OrderBy.IsDesc = true
	}

	if len(r.Filter.DateBetween) == 0 {
		yesterday := time.Now().Add(-time.Hour * 24)
		before7d := yesterday.Add(-time.Hour * 24 * 7)
		ystr := yesterday.Format("2006-01-02")
		b7dstr := before7d.Format("2006-01-02")
		r.Filter.DateBetween = []string{b7dstr, ystr}
	} else if len(r.Filter.DateBetween) == 2 {
		_, berr := time.Parse("2006-01-02", r.Filter.DateBetween[0])
		_, eerr := time.Parse("2006-01-02", r.Filter.DateBetween[1])
		if berr != nil || eerr != nil {
			log.L(ctx).Error("Filter.DateBetween must be like [\"YYYY-MM-DD\", \"YYYY-MM-DD\"]")

			return err
		}
	} else {
		log.L(ctx).Error("Filter.DateBetween must only contain begin-time and end-time")

		return err
	}

	if len(r.Filter.CompareDateBetween) == 2 {
		_, berr := time.Parse("2006-01-02", r.Filter.CompareDateBetween[0])
		_, eerr := time.Parse("2006-01-02", r.Filter.CompareDateBetween[1])
		if berr != nil || eerr != nil {
			log.L(ctx).Error("Filter.CompareDateBetween must be like [\"YYYY-MM-DD\", \"YYYY-MM-DD\"]")

			return err
		}
	} else {
		r.Filter.CompareDateBetween = []string{}
	}

	return nil
}
