package forms

import (
	"time"

	"github.com/gin-gonic/gin"
	"github.com/shopspring/decimal"
)

type PageQuery struct {
	Page     int `form:"page,default=1"`
	PageSize int `form:"page_size,default=20"`
}

type UnitCostsInput struct {
	//optional
	CostID        string            `json:"cost_id"`
	CostTimeStamp int64             `json:"cost_time_stamp"`
	Unit          string            `json:"unit"`
	Cost          int               `json:"cost"`
	Labels        map[string]string `json:"labels"`
}

type UnitCostsSqs struct {
	UnitCostsInput
	TenantID int64 `json:"tenant_id"`
}

type UnitCosts struct {
	CostID        string            `json:"cost_id"`
	CostTimeStamp int64             `json:"cost_time_stamp"`
	Unit          string            `json:"unit"`
	Cost          int               `json:"cost"`
	Labels        map[string]string `json:"labels"`

	CostPrice       decimal.Decimal `json:"price"`
	RawPrice        decimal.Decimal `json:"raw_price"`
	PackageID       uint            `json:"package_id"`
	PackageVersion  uint            `json:"package_version"`
	BindedPackageID uint            `json:"binded_package_id"`
	ConsumedSource  string          `json:"consumed_source"`
	InvoiceID       int             `json:"invoice_id"`
	Discount        decimal.Decimal `json:"discount"`
	Internal        bool            `json:"internal"`

	BindedBillingConfigID uint `json:"-"`
}

type UnitCostSummary struct {
	Unit      string            `json:"unit"`
	Labels    map[string]string `json:"labels"`
	CostPrice decimal.Decimal   `json:"price"`
	RawPrice  decimal.Decimal   `json:"raw_price"`

	ConsumedSource string `json:"-"`
	InvoiceID      int    `json:"-"`
	Cost           int    `json:"-"`
	Internal       bool   `json:"-"`
	TenantID       uint   `json:"-"`
}

type UnitInfo struct {
	UnitKey     string `json:"unit" validate:"min=1"`
	Description string `json:"description"`
	//optional
	Provider string `json:"provider"`
	//optional
	Category string `json:"category"`
	//optional
	Region string `json:"region"`
	//optional
	EditionCode string `json:"edition_code"`
	//optional
	CommodityCode string `json:"commodity_code"`
	//optional
	PriceType string `json:"price_type"`
	//optional
	Price decimal.Decimal `json:"price"`
	//optional
	PriceExpression map[string]string `json:"price_expression"`
	//optional
	SkuType string `json:"sku_type"`
	//optional
	MeasureUnit string `json:"measure_unit"`
	//optional
	SkuTemplateID uint `json:"sku_template_id"`
	//optional
	Version uint `json:"version"`
	//optional
	GroupID uint `json:"group_id"`
	//optional
	BetaEndTime *time.Time `json:"beta_end_time"`
	//optional
	UnitEndTime *time.Time `json:"unit_end_time"`
	//optional
	BetaInternal bool `json:"beta_internal"`
}

type UnitCSVImportResult struct {
	ImportedRows int `json:"imported_rows"`
}

type UnitCount struct {
	Unit  string `json:"unit"`
	Count int    `json:"count"`
}

type LabelMultipleFactorPrice struct {
	MultipleFactorLabel     string `json:"multiple_factor_label,omitempty"`
	MultipleFactorThreshold int    `json:"multiple_factor_threshold,omitempty"`
}

type UnitPrice struct {
	Unit  string          `json:"unit"`
	Price decimal.Decimal `json:"price"`
	LabelMultipleFactorPrice
}

type UnitPrices map[string]UnitPrice

type PackageInfoInput struct {
	UnitPrices           UnitPrices        `json:"unit_prices"`
	Discount             decimal.Decimal   `json:"discount"`
	Credits              decimal.Decimal   `json:"credits"`
	Labels               map[string]string `json:"labels"`
	Description          string            `json:"description"`
	CreditsEnable        bool              `json:"credits_enable"`
	CreditsOnly          bool              `json:"credits_only"`
	TenantMaxBindedTimes uint              `json:"tenant_max_binded_times"`
	ExpressionLabels     []ExpressionLabel `json:"expression_labels"`
	ExtraPricingInfos    []PricingInfo     `json:"extra_pricing_infos"`
}

type ExpressionLabel struct {
	Label    string `json:"label"`
	Operator string `json:"operator"`
	Value    string `json:"value"`
}

type PricingInfo struct {
	UnitPrices       UnitPrices        `json:"unit_prices"`
	Discount         *decimal.Decimal  `json:"discount"`
	Labels           map[string]string `json:"labels"`
	ExpressionLabels []ExpressionLabel `json:"expression_labels"`
}

type PackageInfo struct {
	PackageID  uint       `json:"package_id"`
	UnitPrices UnitPrices `json:"unit_prices"`
	// no need unit count for now, only pay for need
	// UnitCount   []UnitCount
	Discount             decimal.Decimal   `json:"discount"`
	Credits              decimal.Decimal   `json:"credits"`
	Labels               map[string]string `json:"labels"`
	ExpressionLabels     []ExpressionLabel `json:"expression_labels"`
	Description          string            `json:"description"`
	Version              uint              `json:"version"`
	CreditsEnable        bool              `json:"credits_enable"`
	CreditsOnly          bool              `json:"credits_only"`
	TenantMaxBindedTimes uint              `json:"tenant_max_binded_times"`
	ExtraPricingInfos    []PricingInfo     `json:"extra_pricing_infos"`
}

type BindedPackageInfoInput struct {
	PackageID             uint             `json:"package_id"`
	StartedDate           *time.Time       `json:"-"`
	ExpiredDate           *time.Time       `json:"-"`
	ChargeCredits         *decimal.Decimal `json:"-"`
	UnitFilters           []*UnitFilter    `json:"-"`
	DiscountEnabled       bool             `json:"-"`
	Internal              bool             `json:"-"`
	InvoicePayable        bool             `json:"-"`
	BindedBillingConfigID *uint            `json:"binded_billing_config_id"`
}

type BindedPackageInfo struct {
	BindedPackageID  uint            `json:"binded_package_id"`
	TenantID         uint            `json:"tenant_id"`
	PackageID        uint            `json:"package_id"`
	DiscountEnabled  bool            `json:"discount_enabled"`
	StartedDate      *time.Time      `json:"started_date"`
	ExpiredDate      *time.Time      `json:"expired_date"`
	ClosedDate       *time.Time      `json:"closed_date"`
	RemainingCredits decimal.Decimal `json:"remaining_credits"`
	Active           string          `json:"status"`
	//PackageInfo      *PackageInfo    `json:"package_info"`
	UnitFilters           []*UnitFilter `json:"unit_filters"`
	Internal              bool          `json:"internal"`
	InvoicePayable        bool          `json:"invoice_payable"`
	BindedBillingConfigID *uint         `json:"binded_billing_config_id"`
	CreditsPackageUsage   string        `json:"-"`
}

type CreditsChargeInfoInput struct {
	ChargeCount     decimal.Decimal `json:"charge_count"`
	ChargerTenantID uint            `json:"charger_tenant_id"`
	ChargerUserID   uint            `json:"charger_user_id"`
	ChargeReason    string          `json:"charge_reason"`
}

type CreditsChargeInfoMigrateInput struct {
	ChargeCount     decimal.Decimal `json:"charge_count"`
	ChargerTenantID uint            `json:"charger_tenant_id"`
	ChargerUserID   uint            `json:"charger_user_id"`
	ChargeReason    string          `json:"charge_reason"`
	ChargeTime      time.Time       `json:"charge_time"`
}

type ChangeBindedDiscountInput struct {
	BindedDiscount        decimal.Decimal `json:"binded_discount"`
	ChangerTenantID       uint            `json:"changer_tenant_id"`
	ChangerUserID         uint            `json:"changer_user_id"`
	ChangeReason          string          `json:"change_reason"`
	BindedBillingConfigID *uint           `json:"binded_billing_config_id"`
}

type CreditsChargeInfo struct {
	BindedPackageID uint            `json:"binded_package_id"`
	ChargeCount     decimal.Decimal `json:"charge_count"`
	ChargerTenantID uint            `json:"charger_tenant_id"`
	ChargerUserID   uint            `json:"charger_user_id"`
	ChargeReason    string          `json:"charge_reason"`
	ChargeTime      time.Time       `json:"charge_time"`
}

type CreditsChargeHistory struct {
	BindedPackageID uint                `json:"binded_package_id"`
	History         []CreditsChargeInfo `json:"history"`
	TotalAmounts    decimal.Decimal     `json:"total_amounts"`
}

type PaymentResult struct {
	PaymentMethodID uint      `json:"payment_method_id"`
	PaidInvoices    []Invoice `json:"-"`
}

type CreateInvoiceReq struct {
	StartDate time.Time `json:"start_date"`
	Type      string    `json:"type"`
}

const (
	TenantKindInternal = "internal"
	TenantKindExternal = "external"
)

type Tenant struct {
	TenantID                  uint      `json:"tenant_id"`
	Name                      string    `json:"name"`
	Email                     string    `json:"email"`
	CreatedAt                 time.Time `json:"created_at"`
	ThirdPartyAccountProvider string    `json:"third_party_account_provider"`
	ThirdPartyAccountCode     string    `json:"-"`
	ThirdPartyFreeTrial       bool      `json:"third_party_free_trial"`
	Status                    string    `json:"status"`
	IsMsp                     bool      `json:"is_msp"`
	IsMspCustomer             bool      `json:"is_msp_customer"`
	IsCPPOReseller            bool      `json:"is_cppo_reseller"`
	IsCPPOCustomer            bool      `json:"is_cppo_customer"`
	OrgTag                    string    `json:"org_tag"`
	Kind                      string    `json:"kind"`
	IsMCPOReseller            bool      `json:"is_mcpo_reseller"`
	IsMCPOCustomer            bool      `json:"is_mcpo_customer"`
	IsResalePartner           bool      `json:"is_resale_partner"`
	IsResaleCustomer          bool      `json:"is_resale_customer"`
}

type User struct {
	UserID    uint   `json:"user_id"`
	FirstName string `json:"first_name"`
	LastName  string `json:"last_name"`
	Email     string `json:"email"`
	Role      string `json:"role"`
}

type Cluster struct {
	ID                uint   `json:"id,omitempty,string"`
	TenantID          uint   `json:"tenant_id,omitempty,string"`
	ProjectID         uint   `json:"project_id,omitempty,string"`
	CloudProviderName string `json:"cloud_provider_name,omitempty"`
	InfraProviderType string `json:"infra_provider_type,omitempty"`
	RegionName        string `json:"region_name,omitempty"`
	RegionDisplayName string `json:"region_display_name,omitempty"`
	Name              string `json:"name,omitempty"`
	IsDevTier         bool   `json:"is_dev_tier,omitempty"`
	Status            string `json:"status"`
	DeletedAt         *int64 `json:"-"`
	DeployType        int32  `json:"deploy_type,omitempty"`
	ServicePlan       string `json:"service_plan,omitempty"`
}

type Project struct {
	ID       uint   `json:"id,omitempty,string"`
	TenantID uint   `json:"tenant_id,omitempty,string"`
	Name     string `json:"name,omitempty"`
	Status   string `json:"status,omitempty"`
	Type     int32  `json:"type,omitempty"`
}

type Provider struct {
	//Name of the cloud provider
	Name string `json:"name"`
	//Name of the region
	Regions []string `json:"regions"`
}

type UsageDetails struct {
	BilledDate   string          `json:"billed_date"`
	ProjectName  string          `json:"project_name"`
	ClusterName  string          `json:"cluster_name"`
	Service      string          `json:"service"`
	BillableCost decimal.Decimal `json:"billable_cost"`
	CreditUsage  decimal.Decimal `json:"credit_usage"`
	DiscountCost decimal.Decimal `json:"discount_cost"`
	Amount       decimal.Decimal `json:"amount"`
}

type ExportUsageDetails struct {
	TenantID        uint `json:"tenant_id"`
	BillingConfigID uint `json:"billing_config_id"`

	BilledDate    string          `json:"billed_date"`
	Service       string          `json:"service"`
	Usage         decimal.Decimal `json:"usage"`
	Unit          string          `json:"unit"`
	CloudProvider string          `json:"cloud_provider"`
	Region        string          `json:"region"`
	ProjectName   string          `json:"project_name"`
	ProjectID     string          `json:"project_id"`
	ClusterName   string          `json:"cluster_name"`
	ClusterID     string          `json:"cluster_id"`
	ResourceID    string          `json:"resource_id"`
	Amount        decimal.Decimal `json:"amount"`
	BillableCost  decimal.Decimal `json:"billable_cost"`
	CreditUsage   decimal.Decimal `json:"credit_usage"`
}

type CostExplorerQuery struct {
	StartDate time.Time `json:"start_date"`
	EndDate   time.Time `json:"end_date"`
	InvoiceID uint      `json:"invoice_id"`

	Labels          map[string]string `json:"-"`
	Units           []string          `json:"-"`
	Internal        bool              `json:"-"`
	IgnoreBeta      bool              `json:"-"`
	IgnoreInvoiceId bool              `json:"-"`
	UseMainDB       bool              `json:"-"`

	DisableAttachProjectName bool `json:"-"`
	DisableAttachClusterName bool `json:"-"`

	// June2026DailySplit forces the per-day-split + per-row-truncate streaming
	// path inside queryCostStreaming. Set ONLY by GetMonthlyCost (and the
	// MSP equivalents) for the June 2026 freeze — see those functions. The
	// main bills path leaves this false and uses the single full-month scan,
	// which is the correct (pre-3bfb2859) cents-precise algorithm.
	June2026DailySplit bool `json:"-"`
}

type CostExplorerInternalQuery struct {
	StartDate time.Time `json:"start_date"`
	EndDate   time.Time `json:"end_date"`
	InvoiceID uint      `json:"invoice_id"`

	Labels     map[string]string `json:"labels"`
	Units      []string          `json:"units"`
	Internal   bool              `json:"internal"`
	IgnoreBeta bool              `json:"ignore_beta"`
}

type CostExplorerQueryV2 struct {
	StartDate time.Time `json:"start_date"`
	EndDate   time.Time `json:"end_date"`
	InvoiceID uint      `json:"invoice_id"`

	BindedPackageIDs []uint `json:"binded_package_ids"`

	Labels          map[string]string `json:"labels"`
	Units           []string          `json:"units"`
	IgnoreBeta      bool              `json:"ignore_beta"`
	IgnoreInvoiceId bool              `json:"ignore_invoice_id"`
	UseMainDB       bool              `json:"-"`

	DisableAttachProjectName bool `json:"-"`
	DisableAttachClusterName bool `json:"-"`

	// SplitLoopDeadline, when set, overrides the config-based split-loop timeout.
	// Workers set this so long-running background jobs don't get killed by the
	// HTTP-oriented default.
	SplitLoopDeadline time.Time `json:"-"`
	InvoiceIDs        []uint    `json:"-"`

	// June2026DailySplit forces the per-day-split + per-row-truncate streaming
	// path inside queryCostStreaming. Set ONLY by GetMonthlyCost (and the
	// MSP equivalents) for the June 2026 freeze — see those functions. The
	// main bills path leaves this false and uses the single full-month scan,
	// which is the correct (pre-3bfb2859) cents-precise algorithm.
	June2026DailySplit bool `json:"-"`
}

type Service struct {
	TierName string     `json:"tier_name"` // Service/Category/Component
	Depth    int        `json:"depth"`
	Name     string     `json:"name"` // Display Name
	Children []*Service `json:"children"`
}

type CostExplorerService struct {
	// The service product name (first level).
	Product *string `json:"product"`
	// The service category name (second level).
	Category *string `json:"category"`
	// The service component name (third level).
	Component *string `json:"component"`

	// The full service name, typically combining all levels.
	Service *string `json:"service"`
}

type CostExplorerProvider struct {
	// The name of the cloud provider to include in the query.
	Name string `json:"name"`
	// A list of region names to include in the query.
	Regions []string `json:"regions"`
}

type CostExplorerArgs struct {
	Products  []string               `json:"products"`
	Services  []*CostExplorerService `json:"services"`
	Providers []*Provider            `json:"providers"`
	Clusters  []*Cluster             `json:"clusters"`
	Projects  []*Project             `json:"projects"`
}

type CostExplorerTrendsBreakdownKey string

const (
	CostExploreTrendsBreakdownKeyService  CostExplorerTrendsBreakdownKey = "service"
	CostExploreTrendsBreakdownKeyProduct  CostExplorerTrendsBreakdownKey = "product"
	CostExploreTrendsBreakdownKeyProject  CostExplorerTrendsBreakdownKey = "project"
	CostExploreTrendsBreakdownKeyCluster  CostExplorerTrendsBreakdownKey = "cluster"
	CostExploreTrendsBreakdownKeyProvider CostExplorerTrendsBreakdownKey = "provider"
	CostExploreTrendsBreakdownKeyRegion   CostExplorerTrendsBreakdownKey = "region"
	CostExploreTrendsBreakdownKeyCustomer CostExplorerTrendsBreakdownKey = "customer"
)

type CostExplorerTrendsTimeGroup string

const (
	CostExploreTrendsTimeGroupDay   CostExplorerTrendsTimeGroup = "day"
	CostExploreTrendsTimeGroupMonth CostExplorerTrendsTimeGroup = "month"
	CostExploreTrendsTimeGroupTotal CostExplorerTrendsTimeGroup = "total"
)

type CostExplorerTrendsFilter struct {
	StartDate      *time.Time `json:"start_date"`
	EndDate        *time.Time `json:"end_date"`
	Internal       *bool      `json:"-"`
	ConsumedSource *string    `json:"consumed_source"`

	Services  []CostExplorerService  `json:"services"`
	Providers []CostExplorerProvider `json:"providers"`
	Projects  []string               `json:"projects"`
	Clusters  []string               `json:"clusters"`
	Invoices  []string               `json:"invoices"`
	Customer  []string               `json:"customers"`

	IgnoreBeta bool `json:"ignore_beta"`

	// SplitLoopDeadline, when set, overrides the config-based split-loop timeout
	// for trends queries. Workers set this for long-running background jobs.
	SplitLoopDeadline time.Time `json:"-"`
}

type CostExploreTrendsInput struct {
	CostExplorerTrendsFilter
	BreakdownBy []CostExplorerTrendsBreakdownKey `json:"breakdown_by"`
	TimeGroup   *CostExplorerTrendsTimeGroup     `json:"time_group"`
}

type CostExploreTrendsCSVInput struct {
	CostExploreTrendsInput
	DisplayCreditsAndDiscountOnCSV bool `json:"display_credits_and_discount_on_csv"`
}

type CostExploreTrendsOutputPrice struct {
	RawPrice     decimal.Decimal `json:"raw_price"`
	Discount     decimal.Decimal `json:"discount"`
	CreditsUsage decimal.Decimal `json:"credits_usage"`
	CostPrice    decimal.Decimal `json:"cost_price"`
}

type CostExploreTrendsOutputBreakdownDetail struct {
	BillingDate string `json:"billing_date"`
	DetailName  string `json:"detail_name"`
	DetailKey   string `json:"detail_key"`

	CostExploreTrendsOutputPrice
	CostExplorerService
	Provider     *string `json:"provider"`
	Region       *string `json:"region"`
	ProjectName  *string `json:"project_name"`
	ProjectID    *uint   `json:"project_id,string"`
	ClusterName  *string `json:"cluster_name"`
	ClusterID    *uint   `json:"cluster_id,string"`
	CustomerID   *string `json:"customer_id"`
	CustomerName *string `json:"customer_name"`
}

type CostExploreTrendsOutputElement struct {
	CostExploreTrendsOutputPrice
	Prediction  bool   `json:"prediction"`
	BillingDate string `json:"billing_date"`

	Breakdown []CostExploreTrendsOutputBreakdownDetail `json:"breakdown"`
}

type CostExploreTrendsOutput struct {
	CostExploreTrendsOutputPrice
	Elements []CostExploreTrendsOutputElement `json:"elements"`
}

type CostExploreTrendsDashboard struct {
	UserID   uint   `json:"user_id"`
	TimeRule string `json:"time_rule"`
	CostExploreTrendsInput
}

type Price struct {
	Order         int32           `json:"order"`
	CostPrice     decimal.Decimal `json:"cost_price"`
	RawPrice      decimal.Decimal `json:"raw_price"`
	DiscountPrice decimal.Decimal `json:"discount_price"`
}

type LabelCosts map[string]CategoryCosts

type CategoryCosts struct {
	Price
	Order              int32            `json:"order"`
	UnitsCosts         []UnitCosts      `json:"unit_costs,omitempty"` // unused?
	CategoryUnitsCosts map[string]Price `json:"category_unit_costs"`
	ServicePlan        *string          `json:"service_plan"`
}

type CategoryItemCosts struct {
	Order int32 `json:"order"`
	Price
	UnitsCosts             []UnitCosts              `json:"unit_costs,omitempty"`
	CategoryItemUnitsCosts map[string]CategoryCosts `json:"category_item_unit_costs"`
}

type Costs struct {
	CategoryCosts
	LabelsUnitsCosts       map[string]LabelCosts        `json:"label_unit_costs"`
	CategoryItemUnitsCosts map[string]CategoryCosts     `json:"category_item_unit_costs"`
	CategoryUseItem        bool                         `json:"category_use_item"`
	KindCategoryUnitsCost  map[string]CategoryItemCosts `json:"kind_category_units_costs"`
}

type InvoiceAppliedFXRate struct {
	ID     uint            `json:"-"`
	Date   time.Time       `json:"date"`
	Base   Currency        `json:"base"`
	Target Currency        `json:"target"`
	Value  decimal.Decimal `json:"value"`
}

type InvoiceMeta struct {
	PaymentMeta
	AppliedFXRate *InvoiceAppliedFXRate `json:"applied_fx_rate"`
}

type Invoice struct {
	Costs
	InvoiceID             uint            `json:"invoice_id,string"`
	TenantID              uint            `json:"tenant_id,string"`
	Status                string          `json:"status"`
	Type                  string          `json:"type"`
	StartDate             time.Time       `json:"start_date"`
	EndDate               time.Time       `json:"end_date"`
	SentDate              *time.Time      `json:"-"`
	PaymentMethodID       *uint           `json:"-"`
	Brief                 bool            `json:"brief"`
	TaxRate               *TaxRate        `json:"tax_rate"`
	BindedBillingConfigID *uint           `json:"binded_billing_config_id,string"`
	Meta                  InvoiceMeta     `json:"-"`
	ChannelLoss           decimal.Decimal `json:"-"`
	PaymentType           string          `json:"payment_type"`
	PaymentCode           *string         `json:"payment_code"`
	ParentInvoiceID       uint            `json:"parent_invoice_id"`
	// StripeInvoiceID is populated after the invoice has been pushed to Stripe.
	StripeInvoiceID string `json:"stripe_invoice_id,omitempty"`
	// ChargeMode is the charge behavior chosen at push time, "auto" or "manual".
	ChargeMode string `json:"charge_mode,omitempty"`
}

type InvoiceForOpsList struct {
	Invoice
	TenantName string `json:"tenant_name"`
	From       string `json:"from"`
	To         string `json:"to"`
}

type TaxRate struct {
	StripeTaxRateID  string          `json:"-"`
	TenantID         uint            `json:"tenant_id"`
	Value            decimal.Decimal `json:"rate"`
	TaxCode          string          `json:"-"`
	DisplayName      string          `json:"display_name"`
	Inclusive        bool            `json:"inclusive"`
	Country          string          `json:"country"`
	State            string          `json:"state"`
	TaxType          string          `json:"tax_type"`
	TaxAbilityReason string          `json:"tax_ability_reason"`
}

type MonthlyAggregateInvoice struct {
	TenantID        uint            `json:"-"`
	PaymentMethodID uint            `json:"-"`
	InvoiceMonth    string          `json:"-"`
	Invoice         decimal.Decimal `json:"-"`
}

type CostExplorerResult struct {
	BindedInvoiceCosts   Costs             `json:"binded_invoice_costs"`
	UnbindedInvoiceCosts Costs             `json:"unbind_invoice_costs"`
	InvoiceCostsCosts    Costs             `json:"invoice_costs"`
	CreditsCosts         Costs             `json:"credits_costs"`
	TotalCosts           Costs             `json:"total_costs"`
	AllCosts             []UnitCostSummary `json:"-"`
}

type CompleteCostExplorerResult struct {
	InternalCosts CostExplorerResult `json:"internal_costs"`
	ExternalCosts CostExplorerResult `json:"external_costs"`

	AllCosts []UnitCostSummary `json:"-"`
}

type CostExplorerDetailsResult struct {
	Details []UsageDetails `json:"details"`
}

type S3BillsDetailRecord struct {
	ClusterID       string          `json:"cluster_id"`
	BilledDate      string          `json:"billedDate"`
	Credits         decimal.Decimal `json:"credits"`
	Discounts       decimal.Decimal `json:"discounts"`
	RunningTotal    decimal.Decimal `json:"runningTotal"`
	ServicePathName string          `json:"servicePathName"`
	TotalCost       decimal.Decimal `json:"totalCost"`
}

type S3BillsDetailResult struct {
	Details []S3BillsDetailRecord `json:"details"`
}

type MonthlycostExplorerResult struct {
	CostExplorerResult
	InvoiceGenerated bool `json:"invoice_generated"`
}

type BillsEnabled struct {
	BillsEnabled bool `json:"bills_enabled"`
}

type CommitmentInvoiceInput struct {
	Amount                decimal.Decimal `json:"amount"`
	Owner                 string          `json:"owner"`
	Date                  time.Time       `json:"time"`
	BindedBillingConfigID *uint           `json:"binded_billing_config_id"`
	PaymentCode           *string         `json:"payment_code"`
}

type OKType struct {
	Status string `json:"status" example:"ok"`
}

type RecalculateBillsPreviewReq struct {
	StartDate string `json:"start_date" binding:"required"`
	EndDate   string `json:"end_date" binding:"required"`
}

type RecalculateBillsApplyReq struct {
	SourceRunID uint `json:"source_run_id,string,omitempty"`
}

type RecalculateStartResponse struct {
	Mode   string                 `json:"mode"`
	Status string                 `json:"status"`
	Items  []RecalculateStartItem `json:"items"`
}

type RecalculateStartItem struct {
	Status      string   `json:"status"`
	SourceRunID uint     `json:"source_run_id,string,omitempty"`
	Missing     []string `json:"missing,omitempty"`
	Error       string   `json:"error,omitempty"`
}

type RecalculateRun struct {
	RunID           uint       `json:"run_id,string"`
	TenantID        uint       `json:"tenant_id,string"`
	BillingConfigID uint       `json:"billing_config_id,string"`
	InputBundleID   uint       `json:"input_bundle_id,string"`
	Status          string     `json:"status"`
	InvoiceType     string     `json:"invoice_type"`
	InvoiceDate     time.Time  `json:"invoice_date"`
	PeriodMonth     string     `json:"period_month"`
	WindowStart     time.Time  `json:"window_start"`
	WindowEnd       time.Time  `json:"window_end"`
	SourceMode      string     `json:"source_mode"`
	CreatedAt       time.Time  `json:"created_at"`
	FinishedAt      *time.Time `json:"finished_at,omitempty"`
	ErrorMessage    string     `json:"error_message,omitempty"`
}

type RecalculateRunListResponse struct {
	Runs         []RecalculateRun `json:"runs"`
	Page         int              `json:"page"`
	PageSize     int              `json:"page_size"`
	TotalResults int              `json:"total_results"`
}

type RecalculatePreviewResponse struct {
	Mode    string                    `json:"mode"`
	Status  string                    `json:"status"`
	Items   []RecalculatePreviewItem  `json:"items"`
	Summary RecalculatePreviewSummary `json:"summary"`
	Meta    map[string]string         `json:"meta,omitempty"`
}

type RecalculatePreviewSummary struct {
	ItemCount                  int             `json:"item_count"`
	FoundCount                 int             `json:"found_count"`
	RunningCount               int             `json:"running_count"`
	ErrorCount                 int             `json:"error_count"`
	MatchCount                 int             `json:"match_count"`
	LegacyRawPrice             decimal.Decimal `json:"legacy_raw_price"`
	LegacyCostPrice            decimal.Decimal `json:"legacy_cost_price"`
	SnapshotRawPrice           decimal.Decimal `json:"snapshot_raw_price"`
	SnapshotCostPrice          decimal.Decimal `json:"snapshot_cost_price"`
	LegacyRoundingAdjustment   decimal.Decimal `json:"legacy_rounding_adjustment"`
	SnapshotRoundingAdjustment decimal.Decimal `json:"snapshot_rounding_adjustment"`
	DiffRaw                    decimal.Decimal `json:"diff_raw"`
	DiffRoundingAdjustment     decimal.Decimal `json:"diff_rounding_adjustment"`
	DiffCost                   decimal.Decimal `json:"diff_cost"`
}

type RecalculatePreviewItem struct {
	Status                     string            `json:"status"`
	ComparisonScope            string            `json:"comparison_scope"`
	TenantID                   uint              `json:"tenant_id,string"`
	BillingConfigID            uint              `json:"billing_config_id,string"`
	InvoiceID                  *uint             `json:"invoice_id,omitempty,string"`
	InvoiceType                string            `json:"invoice_type"`
	InvoiceDate                time.Time         `json:"invoice_date"`
	PeriodMonth                string            `json:"period_month"`
	WindowStart                time.Time         `json:"window_start"`
	WindowEnd                  time.Time         `json:"window_end"`
	SourceRunID                uint              `json:"source_run_id,string,omitempty"`
	InputBundleID              uint              `json:"input_bundle_id,string,omitempty"`
	SourceMode                 string            `json:"source_mode,omitempty"`
	LegacyRawPrice             decimal.Decimal   `json:"legacy_raw_price"`
	LegacyCostPrice            decimal.Decimal   `json:"legacy_cost_price"`
	LegacyCredits              decimal.Decimal   `json:"legacy_credits"`
	LegacyDiscounts            decimal.Decimal   `json:"legacy_discounts"`
	LegacyRoundingAdjustment   decimal.Decimal   `json:"legacy_rounding_adjustment"`
	LegacyRowCount             int64             `json:"legacy_row_count"`
	SnapshotRawPrice           decimal.Decimal   `json:"snapshot_raw_price"`
	SnapshotCostPrice          decimal.Decimal   `json:"snapshot_cost_price"`
	SnapshotCredits            decimal.Decimal   `json:"snapshot_credits"`
	SnapshotDiscounts          decimal.Decimal   `json:"snapshot_discounts"`
	SnapshotRoundingAdjustment decimal.Decimal   `json:"snapshot_rounding_adjustment"`
	SnapshotFactCount          int64             `json:"snapshot_fact_count"`
	DiffRaw                    decimal.Decimal   `json:"diff_raw"`
	DiffCredits                decimal.Decimal   `json:"diff_credits"`
	DiffRoundingAdjustment     decimal.Decimal   `json:"diff_rounding_adjustment"`
	DiffCost                   decimal.Decimal   `json:"diff_cost"`
	AbsDiffRaw                 decimal.Decimal   `json:"abs_diff_raw"`
	AbsDiffCredits             decimal.Decimal   `json:"abs_diff_credits"`
	AbsDiffRoundingAdjustment  decimal.Decimal   `json:"abs_diff_rounding_adjustment"`
	AbsDiffCost                decimal.Decimal   `json:"abs_diff_cost"`
	Match                      bool              `json:"match"`
	LegacyCreditPackageIDs     string            `json:"legacy_credit_package_ids,omitempty"`
	LegacyDiscountIDs          string            `json:"legacy_discount_ids,omitempty"`
	SnapshotCreditPackageIDs   string            `json:"snapshot_credit_package_ids,omitempty"`
	SnapshotDiscountIDs        string            `json:"snapshot_discount_ids,omitempty"`
	Missing                    []string          `json:"missing,omitempty"`
	Risks                      []string          `json:"risks,omitempty"`
	Error                      string            `json:"error,omitempty"`
	Meta                       map[string]string `json:"meta,omitempty"`
}

var OK = gin.H{
	"status": "success",
}

type BriefForm struct {
	Brief bool `form:"brief" json:"brief"`
}

type InvoicesQuery struct {
	BriefForm
	From          *time.Time `json:"from" form:"from"`
	To            *time.Time `json:"to" form:"to"`
	Status        string     `json:"status" form:"status"`
	Statuses      []string   `json:"statuses" form:"statuses[]"`
	ActivePayment string     `json:"active_payment" form:"active_payment"`
	TenantIDs     string     `json:"tenant_ids" form:"tenant_ids"`
}

type SubscriptionInput struct {
	FilePath      string `json:"file_path"`
	ContractEmail string `json:"contract_email"`
}

type Subscription struct {
	SubscriptionID uint       `json:"subscription_id"`
	TenantID       uint       `json:"tenant_id"`
	Status         string     `json:"status"`
	FilePath       string     `json:"file_path"`
	ContractEmail  string     `json:"contract_email"`
	AcceptedUser   *string    `json:"accepted_user"`
	AcceptedDate   *time.Time `json:"accepted_date"`
	RejectedUser   *string    `json:"rejected_user"`
	RejectedDate   *time.Time `json:"rejected_date"`
}

type SubscriptionChange struct {
	ChangeUser string `json:"change_user"`
}

type BillingAddress struct {
	CompanyName  string `json:"company_name"`
	BillingEmail string `json:"billing_email"`
	// `X` stands `Others`
	CountryCode            string `json:"country_code"`
	CustomInputCountryName string `json:"custom_input_country_name"`
	State                  string `json:"state"`
	City                   string `json:"city"`
	Line1                  string `json:"line1"`
	Line2                  string `json:"line2"`
	PostalCode             string `json:"postal_code"`
}

type TaxInfo struct {
	TaxIDCountryCode string   `json:"tax_id_country_code"`
	TaxIDType        string   `json:"tax_id_type"`
	TaxID            string   `json:"tax_vat"`
	TaxRateID        string   `json:"-"`
	TaxRate          *TaxRate `json:"tax_rate"`
}

type BillingCompany struct {
	CompanyKey     string `json:"company_key"`
	Name           string `json:"name"`
	PaymentSubCode string `json:"payment_sub_code"`
	StripeTaxID    string `json:"-"`

	UsingDesignatedTaxAddressToCalculateTaxRate bool            `json:"-"`
	DesignatedTaxAddress                        *BillingAddress `json:"-"`

	LocalCurrency                        string `json:"-"`
	DisplayLocalCurrencyCommentOnInvoice bool   `json:"-"`
}

type TenantBillingCompanyInput struct {
	CompanyKey string `json:"company_key"`
}

type TenantBillingCompany struct {
	TenantID   uint   `json:"tenant_id"`
	CompanyKey string `json:"company_key"`
}

type BillingInformationInput struct {
	BillingAddress
	TaxInfo
}

type BillingInformation struct {
	TenantID   uint   `json:"tenant_id"`
	StripeCode string `json:"-"`
	BillingAddress
	TaxInfo
}

type DateInterval struct {
	StartDate *time.Time `json:"start_date"`
	EndDate   *time.Time `json:"end_date"`
}

type TieredPriceRule struct {
	LowerBound             decimal.Decimal  `json:"lower_bound"`
	UpperBound             *decimal.Decimal `json:"upper_bound"`
	SupportPricePercentage decimal.Decimal  `json:"support_price_percentage"`
}

type SupportPlan struct {
	FixedChargePrice       decimal.Decimal   `json:"fixed_charge_price"`
	SupportPricePercentage decimal.Decimal   `json:"support_price_percentage"`
	Type                   string            `json:"type"`
	Public                 bool              `json:"public"`
	Level                  string            `json:"level"`
	SupportPlanID          uint              `json:"support_plan_id"`
	TieredPriceRules       []TieredPriceRule `json:"tiered_price_rules"`
	IsSupportFreeTrial     bool              `json:"is_support_free_trial"`
}

type SupportPlanInput struct {
	SupportPlan
	ActiveDate  time.Time  `json:"active_date"`
	ExpiredDate *time.Time `json:"expired_date"`
}

type BindedSupportPlanInput struct {
	SupportPlanID uint `json:"support_plan_id"`
}

type BindedSupportPlan struct {
	SupportPlan
	BindedSupportPlanID    uint       `json:"binded_support_plan_id"`
	TenantID               uint       `json:"tenant_id"`
	Status                 string     `json:"status"`
	ActiveDate             time.Time  `json:"active_date"`
	ClosedDate             *time.Time `json:"closed_date"`
	ExpiredDate            *time.Time `json:"expired_date"`
	BindedPackageID        *uint      `json:"-"`
	IsEligibleForFreeTrial bool       `json:"is_eligible_for_free_trial"`
	IsInFreeTrial          bool       `json:"is_in_free_trial"`
	RestDaysOfFreeTrial    uint       `json:"rest_days_of_free_trial"`
}

type BindedSupportPlanDetails struct {
	BindedSupportPlans     []*BindedSupportPlan `json:"binded_support_plans"`
	IsEligibleForFreeTrial bool                 `json:"is_eligible_for_free_trial"`
}

type WorkerTaskAction struct {
	Action  string    `json:"action"`
	RunTime time.Time `json:"run_time"`
}

type WorkerSubTaskAction struct {
	Action   string    `json:"action"`
	RunTime  time.Time `json:"run_time"`
	TenantID uint      `json:"tenant_id"`
}

type ProviderEnum string

const (
	Provider_All      ProviderEnum = UnitFilterALL
	Provider_AWS      ProviderEnum = "AWS"
	Provider_GCP      ProviderEnum = "GCP"
	Provider_Azure    ProviderEnum = "AZURE"
	Provider_AliCloud ProviderEnum = "Alicloud"

	Provider_PINGCAP ProviderEnum = "PINGCAP"
)

type CopyUnitFilterArgs struct {
	Customers []string      `json:"customers"`
	Projects  []string      `json:"projects"`
	Clusters  []string      `json:"clusters"`
	Provider  *ProviderEnum `json:"provider"`
}

type CreateCreditsPackageReq struct {
	StartDate       time.Time         `json:"start_date"`
	ExpiredDate     time.Time         `json:"expired_date"`
	TotalCredits    decimal.Decimal   `json:"total_credits"`
	Type            string            `json:"type"`
	Usage           string            `json:"usage"`
	Note            string            `json:"note"`
	DiscountEnabled bool              `json:"discount_enabled"`
	BindTypes       []*UnitFilterSlim `json:"bind_types"`
	UnitFilter      []*UnitFilterSlim `json:"unit_filters"`
	UsageExtend     string            `json:"usage_extend"`
	UserEmail       string            `json:"user_email"`
	ForeignID       string            `json:"foreign_id"`

	CopyUnitFilterArgs
}

type CreditsPackageFilter struct {
	TenantID    uint       `json:"tenant_id"`
	StartDate   *time.Time `json:"start_date"`
	ExpiredDate *time.Time `json:"expired_date"`
	Usage       string     `json:"usage"`
	Status      string     `json:"status"`
	Internal    *bool      `json:"internal"`
}

const UnitFilterALL = "all"

type UnitFilterSlim struct {
	FilterID    uint   `json:"filter_id"`
	TypeID      uint   `json:"type_id"` // this field is a deprecated
	Name        string `json:"name"`
	Description string `json:"description"`
	ParentID    uint   `json:"parent_id"`
	Internal    bool   `json:"-"`
	Priority    int    `json:"-"`
}

type UnitFilter struct {
	UnitFilterSlim
	General        bool              `json:"general"`
	Provider       string            `json:"provider"`
	Region         string            `json:"region"`
	Category       string            `json:"category"`
	Labels         map[string]string `json:"labels"`
	UnitKeyPattern string            `json:"unit_key_pattern"`
}

type CreateCopyUnitFilterArgs struct {
	Providers      []ProviderEnum
	LabelsCopyArgs []LabelsCopiedUnitFilterArgs
}

type LabelsCopiedUnitFilterArgs struct {
	DisplayName string
	LabelKey    string
	Targets     []string
}

type UnitFilterQuery struct {
	Internal bool
}

type UnitFilterNode struct {
	UnitFilterSlim
	Children []*UnitFilterNode `json:"children"`
}

type CreditsPackage struct {
	CreditsPackageID      uint              `json:"credits_package_id"`
	CreditsCode           string            `json:"credits_code"`
	TenantID              uint              `json:"tenant_id"`
	Status                string            `json:"status"`
	StartDate             time.Time         `json:"start_date"`
	ClosedDate            *time.Time        `json:"closed_date"`
	ExpiredDate           time.Time         `json:"expired_date"`
	BindedPackageID       *uint             `json:"binded_package_id"`
	RemainingCredits      decimal.Decimal   `json:"remaining_credits"`
	TotalCredits          decimal.Decimal   `json:"total_credits"`
	Type                  string            `json:"type"`
	Usage                 string            `json:"usage"`
	ClosedReason          string            `json:"closed_reason"`
	Note                  string            `json:"note"`
	BindTypes             []*UnitFilterSlim `json:"bind_types"`
	UnitFilters           []*UnitFilterSlim `json:"unit_filters"`
	DiscountEnabled       bool              `json:"discount_enabled"`
	UnitFiltersInternal   []*UnitFilter     `json:"-"`
	Internal              bool              `json:"internal"`
	BindedBillingConfigID *uint             `json:"binded_billing_config_id"`
	UsageExtend           string            `json:"usage_extend"`
	ForeignID             string            `json:"foreign_id"`
	UserEmail             string            `json:"user_email"`

	CopyUnitFilterArgs
}

type CreditsSummary struct {
	TenantID                      uint            `json:"tenant_id"`
	TotalCredits                  decimal.Decimal `json:"total_credits"`
	TotalCostedCredits            decimal.Decimal `json:"total_costed_credits"`
	AvailableCredits              decimal.Decimal `json:"available_credits"`
	AvailableCostedCredits        decimal.Decimal `json:"available_costed_credits"`
	AvailableRemainingCredits     decimal.Decimal `json:"available_remaining_credits"`
	AvailablePOCCredits           decimal.Decimal `json:"available_poc_credits"`
	AvailableCostedPOCCredits     decimal.Decimal `json:"available_costed_poc_credits"`
	AvailableRemainingPOCCredits  decimal.Decimal `json:"available_remaining_poc_credits"`
	LastCreditsClosedDate         *time.Time      `json:"last_credits_closed_date"`
	ActiveCreditsPacakgesCount    uint            `json:"active_credits_packages_count"`
	ActivePOCCreditsPackagesCount uint            `json:"active_poc_credits_packages_count"`
}

type TenantID struct {
	TenantID uint `json:"tenant_id"`
}
type CreditsPackageID struct {
	CreditsPackageID uint `json:"credits_package_id"`
}
type OrgEventData struct {
	OrgId        uint64
	OrgEventType string
	EventTime    *time.Time
}
type CostQuota struct {
	CostQuotaLimit decimal.Decimal `json:"cost_quota_limit"`
}

type CreditRiskLevel struct {
	CreditRiskLevelID uint      `json:"credit_risk_level_id"`
	Name              string    `json:"credit_risk_level_name"`
	CostQuota         CostQuota `json:"cost_quota"`
}

type CreditRiskLevelInput struct {
	Name string `json:"credit_risk_level_name"`
}

type CreditRiskLevelIDInput struct {
	CreditRiskLevelID uint `json:"credit_risk_level_id"`
}

type AuditLogSearchQuery struct {
	Action     string    `form:"action"`
	StartDate  time.Time `form:"start_date" time_format:"2006-01-02" time_utc:"1"`
	EndDate    time.Time `form:"end_date"  time_format:"2006-01-02" time_utc:"1"`
	TenantID   uint      `form:"tenant_id"`
	OperatorID uint      `form:"operator_id"`
	Page       int       `form:"page,default=1"`
	PageSize   int       `form:"page_size,default=20"`
}

type AuditLog struct {
	Tenant
	Operator      User      `json:"operator"`
	Action        string    `json:"action"`
	OperationTime time.Time `json:"operation_time"`
}
type ContractInput struct {
	ContractID   string `json:"contract_id"`
	ContractType string `json:"contract_type"`
	FilePath     string `json:"file_path" binding:"required"`
	ContactEmail string `json:"contact_email" binding:"required"`
}

type ContractOperationInput struct {
	ContractID uint   `json:"contract_id" binding:"required"`
	Action     string `json:"action" binding:"required"`
	Reason     string `json:"reason"`
}

type Contract struct {
	ID                     uint      `json:"id"`
	ContractID             string    `json:"contract_id"`
	TenantID               uint      `json:"tenant_id"`
	CreatedAt              time.Time `json:"created_at"`
	Status                 string    `json:"status"`
	ContractType           string    `json:"contract_type"`
	FilePath               string    `json:"file_path"`
	ContactEmail           string    `json:"contact_email"`
	LastOperatorID         uint      `json:"last_operator_id"`
	OperatedAt             time.Time `json:"operated_at"`
	ReasonForLastOperation string    `json:"reason_for_last_operation"`
}

type ContractsResponse struct {
	Contracts    *[]Contract `json:"contracts"`
	Page         int         `json:"page"`
	PageSize     int         `json:"page_size"`
	TotalResults int         `json:"total_results"`
}

type SwitchResponse struct {
	TenantID                    uint `json:"tenant_id"`
	IsAllowed                   bool `json:"is_allowed"`
	RequireCreditCardValidation bool `json:"require_credit_card_validation"`
}

type CloseAction struct {
	Action           string `json:"action"`
	ActionTimeInHour uint   `json:"action_time_in_hour"`
}

type CloseActionStatusInner map[string]string

// only struct can use in db gorm query set to generate the function
type CloseActionsStatus struct {
	Status CloseActionStatusInner `json:"status"`
}

type ClosePolicy struct {
	Actions      []*CloseAction `json:"actions"`
	CancelAction *CloseAction   `json:"cancel_action"`
}

type TenantClosePolicy struct {
	PolicyID          uint        `json:"policy_id"`
	Reason            string      `json:"reason"`
	CreditRiskLevelID uint        `json:"credit_risk_level_id"`
	ClosePolicy       ClosePolicy `json:"close_policy"`
}

type TenantClosePolicyInput struct {
	ClosePolicy ClosePolicy `json:"close_policy"`
}

type TenantCloseInfo struct {
	TenantID           uint               `json:"tenant_id"`
	CreditRiskLevelID  uint               `json:"credit_risk_level_id"`
	ClosePolicy        ClosePolicy        `json:"close_policy"`
	CloseActionsStatus CloseActionsStatus `json:"close_actions_status"`
	Reason             string             `json:"reason"`
	Status             string             `json:"status"`
	StartedAt          time.Time          `json:"started_at"`
	ClosedAt           *time.Time         `json:"closed_at"`
}

type PlanInfo struct {
	PlanID                uint       `json:"plan_id"`
	Plan                  string     `json:"plan"`
	Status                string     `json:"status"`
	StartedAt             *time.Time `json:"started_at"`
	ClosedAt              *time.Time `json:"closed_at"`
	BindedPackageID       uint       `json:"-"`
	BindedBillingConfigID *uint      `json:"binded_billing_config_id"`
}

type TenantPlanInfo struct {
	TenantID          uint            `json:"tenant_id"`
	TenantIDStr       uint            `json:"tenant_id_str,string"`
	EffectivePlan     string          `json:"effective_plan"`
	DevTierPlanInfo   *PlanInfo       `json:"dev_tier_plan_info"`
	POCPlanInfo       *PlanInfo       `json:"poc_plan_info"`
	OnDemandPlanInfo  *PlanInfo       `json:"ondemand_plan_info"`
	EffectiveDiscount decimal.Decimal `json:"effective_discount"`
	POCCredits        decimal.Decimal `json:"poc_credits"`
}

type TenantPlanEvent struct {
	TenantID      uint   `json:"tenant_id"`
	ChangedPlan   string `json:"changed_plan"`
	ChangedStatus string `json:"changed_status"`
	EffectivePlan string `json:"effective_plan"`
}

type DiscountInfo struct {
	Discount decimal.Decimal `json:"discount"`
}

type Discount struct {
	DiscountID            uint              `json:"discount_id"`
	DiscountSID           string            `json:"discount_sid"`
	TenantID              uint              `json:"tenant_id"`
	Value                 decimal.Decimal   `json:"discount"`
	UnitFilters           []*UnitFilterSlim `json:"unit_filters"`
	Status                string            `json:"status"`
	StartedAt             time.Time         `json:"started_at"`
	ExpiredAt             time.Time         `json:"expired_at"`
	ClosedAt              *time.Time        `json:"closed_at"`
	Code                  string            `json:"discount_code"`
	Description           string            `json:"description"`
	Usage                 string            `json:"usage"`
	Note                  string            `json:"note"`
	CreatedAt             string            `json:"-"`
	Version               uint              `json:"-"`
	UnitFiltersInternal   []*UnitFilter     `json:"-"`
	OldDiscountUniqueMark *uint             `json:"-"`
	Active                string            `json:"-"`
	BindedBillingConfigID *uint             `json:"binded_billing_config_id"`

	CopyUnitFilterArgs
}

type ModifierAndCreator struct {
	Modifier string `json:"modifier"`
	Creator  string `json:"creator"`
	//optional
	Describe string `json:"describe"`
}
type Commodity struct {
	ID                 uint               `json:"ID"`
	CreatedAt          time.Time          `json:"created_at"`
	UpdatedAt          time.Time          `json:"updated_at"`
	CommodityCode      string             `json:"commodity_code"`
	CommodityShowName  string             `json:"commodity_show_name"`
	CommodityType      string             `json:"commodity_type"`
	Owner              string             `json:"owner"`
	ModifierAndCreator ModifierAndCreator `json:"modifier_info"`
}
type CommodityModify struct {
	Commodity Commodity `json:"commodity"`
	ModifyID  uint      `json:"modifyID"`
}
type DimensionValue map[string]string
type DimensionValueParameters map[string]DimensionValue

type EditionDimensionValue map[string]DimensionValueParameters

type CommodityDimension struct {
	ID            uint      `json:"ID"`
	CreatedAt     time.Time `json:"created_at"`
	UpdatedAt     time.Time `json:"updated_at"`
	DimensionCode string    `json:"dimension_code"`
	//optional
	CommodityCode      string             `json:"commodity_code"`
	DimensionShowName  string             `json:"dimension_show_name"`
	DimensionValue     DimensionValue     `json:"dimension_value"`
	IsShare            bool               `json:"is_share"`
	IsCharge           bool               `json:"is_charge"`
	ModifierAndCreator ModifierAndCreator `json:"modifier_info"`
}
type CommodityDimensionModify struct {
	CommodityDimension CommodityDimension `json:"commodity_dimension"`
	ModifyID           uint               `json:"modifyID"`
}
type CommodityEdition struct {
	ID                    uint                  `json:"ID"`
	CreatedAt             time.Time             `json:"created_at"`
	UpdatedAt             time.Time             `json:"updated_at"`
	EditionCode           string                `json:"edition_code"`
	CommodityCode         string                `json:"commodity_code"`
	EditionShowName       string                `json:"edition_show_name"`
	EditionDimensionValue EditionDimensionValue `json:"edition_dimension_value"`
	ModifierAndCreator    ModifierAndCreator    `json:"modifier_info"`
}
type CommodityEditionModify struct {
	CommodityEdition CommodityEdition `json:"commodity_edition"`
	ModifyID         uint             `json:"modifyID"`
}
type SkuTemplate struct {
	ID                 uint               `json:"ID"`
	CreatedAt          time.Time          `json:"created_at"`
	UpdatedAt          time.Time          `json:"updated_at"`
	EditionCode        string             `json:"edition_code"`
	CommodityCode      string             `json:"commodity_code"`
	Template           DimensionValue     `json:"template"`
	ModifierAndCreator ModifierAndCreator `json:"modifier_info"`
}
type SkuTemplateModify struct {
	SkuTemplate SkuTemplate `json:"sku_template"`
	ModifyID    uint        `json:"modifyID"`
}

type CommodityQuery struct {
	//optional
	CommodityCode string `json:"commodity_code"`
	//optional
	CommodityShowName string `json:"commodity_show_name"`
	//optional
	Owner string `json:"owner"`
	//optional
	QueryType string `json:"query_type"`
}

type CommodityDimensionQuery struct {
	//optional
	DimensionCode string `json:"dimension_code"`
	//optional
	CommodityCode string `json:"commodity_code"`
	//optional
	DimensionShowName string `json:"dimension_show_name"`
	//optional
	QueryType string `json:"query_type"`
}
type CommodityEditionQuery struct {
	//optional
	EditionCode string `json:"edition_code"`
	//optional
	CommodityCode string `json:"commodity_code"`
	//optional
	EditionShowName string `json:"edition_show_name"`
	//optional
	QueryType string `json:"query_type"`
}

type SkuTemplateQuery struct {
	//optional
	EditionCode string `json:"edition_code"`
	//optional
	CommodityCode string `json:"commodity_code"`
}
type SkuInfo struct {
	UnitKey            string             `json:"unit_key"`
	Description        string             `json:"description"`
	Category           string             `json:"category"`
	Provider           string             `json:"provider"`
	Region             string             `json:"region"`
	Price              decimal.Decimal    `json:"price"`
	EditionCode        string             `json:"edition_code"`
	CommodityCode      string             `json:"commodity_code"`
	MeasureUnit        string             `json:"measure_unit"`
	SkuTemplateID      uint               `json:"sku_template_id"`
	ModifierAndCreator ModifierAndCreator `json:"modifier_info"`
}

type SkuInfoQuery struct {
	//optional
	UnitKey string `json:"unit_key"`
	//optional
	EditionCode string `json:"edition_code"`
	//optional
	CommodityCode string `json:"commodity_code"`
	//optional
	SkuTemplateID uint `json:"sku_template_id"`
}
type SkuModify struct {
	ModifyMap map[string]SkuInfo
}
type SpendLimitFilter struct {
	RangeType     string `form:"range_type"`
	RangeID       uint   `form:"range_id"`
	BizType       string `form:"biz_type"`
	IgnoreBizProc bool   `form:"-"`

	HasServerlessFreeCredits *bool `form:"has_serverless_free_credits"`
}

type SpendLimitSettingInput struct {
	Interval  string          `json:"interval"`
	CostType  string          `json:"cost_type"`
	RangeType string          `json:"range_type"`
	RangeID   uint            `json:"range_id"`
	Limit     decimal.Decimal `json:"limit"`
	BizType   string          `json:"biz_type"`
}

type SpendLimitSetting struct {
	SpendLimitSettingID uint            `json:"spendlimit_setting_id"`
	Name                string          `json:"name"`
	TenantID            uint            `json:"tenant_id"`
	Interval            string          `json:"interval"`
	CostType            string          `json:"cost_type"`
	RangeType           string          `json:"range_type"`
	RangeID             uint            `json:"range_id"`
	RangeIDStr          uint            `json:"range_id_str,string"`
	Limit               decimal.Decimal `json:"limit"`
	Status              string          `json:"status"`
	BizType             string          `json:"biz_type"`
	BizData             string          `json:"biz_data"`
	BizUniqueKey        *string         `json:"-"`
	WaterMark           decimal.Decimal `json:"-"`
	CreatedAt           time.Time       `json:"-"`

	HasServerlessFreeCredits bool `json:"has_serverless_free_credits"`
}

type ServerlessBizData struct {
	FreeCredits          decimal.Decimal `json:"free_credits"`
	InvoiceLimit         decimal.Decimal `json:"invoice_limit"`
	ActiveTotalCredits   decimal.Decimal `json:"active_total_credits"`
	RemainingCredits     decimal.Decimal `json:"remaining_credits"`
	RechargePlanID       uint            `json:"recharge_plan_id"`
	TenantRechargePlanID uint            `json:"tenant_recharge_plan_id"`
	TieredBillingID      uint            `json:"tiered_billing_id"`
}

type NormalBizData struct {
	EnableEmailNotification bool `json:"enable_email"`
	EnableInAppNotification bool `json:"enable_in_app_notification"`
	ApplyCredits            bool `json:"apply_credits"`
	ApplyDiscount           bool `json:"apply_discounts"`
}

type SpendLimitInfo struct {
	SpendLimitSetting
	Costs     decimal.Decimal `json:"costs"`
	StartDate time.Time       `json:"start_date"`
}

type Budget struct {
	SpendLimitInfo
	Thresholds []*SpendLimitThreshold `json:"thresholds"`
	Meta       map[string]string      `json:"meta"`
}

type SpendLimitThresholdAlert struct {
	SpendLimitInfo
	Threshold decimal.Decimal `json:"threshold"`
}

type SpendLimitThreshold struct {
	ThresholdID  uint            `json:"threshold_id"`
	TenantID     uint            `json:"tenant_id"`
	SpendLimitID uint            `json:"spend_limit_id"`
	BizType      string          `json:"biz_type"`
	Proportion   decimal.Decimal `json:"proportion"`
}

const FirstCycleStartedAt_RightNow = "right_now"
const FirstCycleStartedAt_NextStartOfNaturalCycle = "next_start_of_natural_cycle"

const FirstCycleFinishedAt_EndOfNaturalCycle = "end_of_natural_cycle"

const FirstCreditsConvertor_Full = "full"
const FirstCreditsConvertor_Proportional = "proportional"

type RechargeCreditsPlanRule struct {
	FirstCycleStartedAt   string `json:"first_cycle_started_at"`
	FirstCycleFinishedAt  string `json:"first_cycle_finished_at"`
	FirstCreditsConvertor string `json:"first_credits_convertor"`
}

type RechargeCreditsPlanInput struct {
	Rule     RechargeCreditsPlanRule `json:"rule"`
	Cycle    string                  `json:"cycle"`
	Usage    string                  `json:"usage"`
	Value    decimal.Decimal         `json:"value"`
	Internal bool                    `json:"internal"`
}

type RechargeCreditsPlan struct {
	PlanID      uint                    `json:"plan_id"`
	CreatedAt   time.Time               `json:"created_at"`
	UpdatedAt   time.Time               `json:"updated_at"`
	Value       decimal.Decimal         `json:"value"`
	Usage       string                  `json:"usage"`
	Note        string                  `json:"note"`
	Internal    bool                    `json:"internal"`
	Rule        RechargeCreditsPlanRule `json:"rule"`
	Cycle       string                  `json:"cycle"`
	Trigger     *string                 `json:"-"` // not used
	Duration    time.Duration           `json:"-"`
	StartDate   time.Time               `json:"start_date"`
	ExpiredDate time.Time               `json:"expired_date"`
	ClosedAt    *time.Time              `json:"-"`
	Source      string                  `json:"source"`
	// deprecated
	UnitFilters []*UnitFilterSlim `json:"-"`
}

type TenantRechargeCreditsPlan struct {
	PlanID             uint              `json:"plan_id"`
	MainPlanID         uint              `json:"main_plan_id"`
	TenantID           uint              `json:"tenant_id"`
	StartDate          time.Time         `json:"start_date"`
	ExpiredDate        time.Time         `json:"expired_date"`
	RechargeTimes      uint              `json:"recharge_times"`
	NextCycleStartTime time.Time         `json:"next_cycle_start_time"`
	ClosedAt           *time.Time        `json:"-"`
	UnitFilters        []*UnitFilterSlim `json:"unit_filters"`
	ClusterID          uint              `json:"cluster_id"`
}

type TieredBilling struct {
	TieredID    uint              `json:"tiered_id"`
	TenantID    uint              `json:"tenant_id"`
	Labels      map[string]string `json:"labels"`
	Interval    string            `json:"interval"`
	TargetValue decimal.Decimal   `json:"target_value"`
	Action      string            `json:"action"`
}

type MspCustomerScheduleInfo struct {
	MspTenantID      uint64     `json:"msp_tenant_id"`
	CustomerTenantID uint64     `json:"customer_tenant_id"`
	Status           string     `json:"status"`
	EffectedAt       time.Time  `json:"effected_at"`
	ExpiredAt        *time.Time `json:"expired_at"`
}

type PartnerCustomerScheduleInfo struct {
	PartnerTenantID  uint64     `json:"partner_tenant_id"`
	CustomerTenantID uint64     `json:"customer_tenant_id"`
	Status           string     `json:"status"`
	EffectedAt       time.Time  `json:"effected_at"`
	ExpiredAt        *time.Time `json:"expired_at"`
}

type BillingResourceType string

const BillingResourceType_DedicatedCluster BillingResourceType = "dedicated_cluster"
const BillingResourceType_DedicatedBackup BillingResourceType = "dedicated_backup"
const BillingResourceType_LakeWarehouse BillingResourceType = "lake_warehouse"
const BillingResourceType_ServerlessCluster BillingResourceType = "serverless_cluster"
const BillingResourceType_EssentialCluster BillingResourceType = "essential_cluster"
const BillingResourceType_PremiumCluster BillingResourceType = "premium_cluster"
const BillingResourceType_StarterCluster BillingResourceType = "starter_cluster"

type BillingResource struct {
	Type       BillingResourceType `json:"type"`
	InstanceID *string             `json:"instance_id"`
	Region     *string             `json:"region"`
	Provider   *ProviderEnum       `json:"provider"`
	IsFree     bool                `json:"is_free"`
	Origin     interface{}         `json:"origin"`
}

type BillingAction string

const BillingAction_Create BillingAction = "add"
const BillingAction_Delete BillingAction = "remove"
const BillingAction_Scaleup BillingAction = "expand"
const BillingAction_Scaledown BillingAction = "shrink"
const BillingAction_View BillingAction = "view"

type BillingActionInfo struct {
	Resource BillingResource `json:"resource"`
	Action   BillingAction   `json:"action"`
}

type BillingActionCheckResult struct {
	Pass     bool        `json:"pass"`
	Reason   *string     `json:"reason"`
	Original interface{} `json:"original"`
}

type BillingActionCheckBatchInput struct {
	Actions []*BillingActionInfo `json:"actions"`
}

type BillingActionCheckBatchOutput struct {
	Results []*BillingActionCheckResult `json:"results"`
}

type SKUGroup struct {
	//optional
	GroupID uint `json:"group_id"`

	UnitKeyPattern string `json:"unit_key_pattern" validate:"min=1"`

	Name         string `json:"name"`
	Category     string `json:"category"`
	SKUGroupType string `json:"sku_group_type"`
	PriceType    string `json:"price_type"`
	PriceFormula string `json:"price_formula"`
	//optional
	PriceExpression map[string]string `json:"price_expression"`
	//optional
	MeasureUnit string `json:"measure_unit"`
	//optional
	CreatedAt time.Time `json:"created_at"`
	//optional
	UpdatedAt time.Time `json:"updated_at"`
}
type UnitByGroup struct {
	GroupID           uint              `json:"group_id"`
	Provider          string            `json:"provider"`
	Region            string            `json:"region"`
	GroupLabels       map[string]string `json:"group_labels"`
	UnitKeyParameters map[string]string `json:"unit_key_parameters"`
	Price             *decimal.Decimal  `json:"price"`
	BetaEndTime       *time.Time        `json:"beta_end_time"`
}

type UnitPatch struct {
	UnitKey         *string           `json:"unit"`
	Price           *decimal.Decimal  `json:"price"`
	PriceType       *string           `json:"price_type"`
	PriceExpression map[string]string `json:"price_expression"`
}
type ProviderPriceRes struct {
	SKU     string           `json:"sku"`
	Version string           `json:"version"`
	Price   *decimal.Decimal `json:"price"`
}

type CategoryNode struct {
	Key        string          `json:"key"`
	ParentKey  string          `json:"parent_key"`
	Name       string          `json:"name"`
	Category   string          `json:"category"`
	Categories []string        `json:"categories"`
	Order      int32           `json:"order"`
	Children   []*CategoryNode `json:"children"`
}

type CategoryItemShow struct {
	Category          string            `json:"category"`
	Labels            map[string]string `json:"labels"`
	LabelKey          string            `json:"label_key"`
	ShowServicePrefix string            `json:"show_service_prefix"`
	ShowCategoryName  string            `json:"show_category_name"`
	UseCateGory       bool              `json:"use_cate_gory"`
	ShowKindName      string            `json:"show_kind_name"`
	OrderMap          map[string]int32  `json:"order_map"`
	EditionCode       string            `json:"edition_code"`
	CommodityCode     string            `json:"commodity_code"`
	MeasureUnit       string            `json:"measure_unit"`
	ParentKey         string            `json:"parent_key"`
}

type SQSTarget struct {
	Name       string
	Region     string
	Role       string
	ExternalID string
	QueueURL   string
}
