// Package billing defines the platform-owned billing facade.
package billing

import (
	"context"
	"time"

	platformregistry "github.com/gpuaas/platform/packages/platform/registry"
	"github.com/jackc/pgx/v5"
	"github.com/jackc/pgx/v5/pgconn"
)

type UsageUnitRegistry interface {
	GetUsageUnit(ctx context.Context, unitID string) (*platformregistry.UsageUnit, error)
}

const (
	UsageSourceAppRuntime             = "app_runtime"
	UsageUnitAppRuntimeHour           = "app_runtime_hour"
	UsageUnitManagedIngressRequest    = "managed_ingress_request"
	UsageUnitManagedIngressByte       = "managed_ingress_byte"
	UsageUnitManagedIngressConnection = "managed_ingress_connection_second"
)

type Filters struct {
	Cursor        string
	PageSize      int
	AllocationID  string
	AppInstanceID string
	UsageSource   string
	From          string
	To            string
	Sort          string
}

type UsageRecord struct {
	ID                    string
	UsageSource           string
	UsageUnit             string
	AllocationID          *string
	AppInstanceID         *string
	UserID                string
	SKU                   *string
	ControlPlaneComponent bool
	OperatingMode         *string
	ControlPlaneScope     *string
	RuntimeBackend        *string
	StartTime             time.Time
	EndTime               *time.Time
	LastBilledAt          *time.Time
	CostMinor             int64
	Currency              string
}

type Balance struct {
	AmountMinor int64
	Currency    string
}

type BillingAccount struct {
	ID                     *string
	OrgID                  string
	AccountType            string
	DisplayName            string
	ParentBillingAccountID *string
	ResellerOrgID          *string
	InvoiceRecipientOrgID  *string
	DefaultCurrency        string
	WholesalePricingPlanID *string
	CustomerPricingPlanID  *string
	TaxResponsibility      string
	CreditRiskOwner        string
	Status                 string
}

type FXSnapshot struct {
	SourceCurrency string
	TargetCurrency string
	Rate           string
	Provider       string
	ProviderRateID *string
	CapturedAt     time.Time
}

type CurrencySettings struct {
	OrgID               string
	DefaultCurrency     string
	SupportedCurrencies []string
	FXSnapshot          *FXSnapshot
}

type FinancialRestrictionState string

const (
	FinancialRestrictionHealthy         FinancialRestrictionState = "healthy"
	FinancialRestrictionAtRisk          FinancialRestrictionState = "at_risk"
	FinancialRestrictionRestricted      FinancialRestrictionState = "restricted"
	FinancialRestrictionSuspended       FinancialRestrictionState = "suspended"
	FinancialRestrictionCollectionsHold FinancialRestrictionState = "collections_hold"
)

type FinancialRestrictionInput struct {
	ScopeType     string
	ScopeID       string
	State         string
	Reason        string
	ActorUserID   string
	CorrelationID string
	MetadataJSON  string
	EffectiveAt   time.Time
}

type FinancialRestrictionResult struct {
	ID            string
	ScopeType     string
	ScopeID       string
	State         string
	Reason        string
	Effects       map[string]any
	CorrelationID string
	UpdatedAt     time.Time
}

type FinancialPostureResult struct {
	State                  string
	Reason                 string
	Effects                map[string]any
	Restriction            *FinancialRestrictionResult
	AffectedAllocationIDs  []string
	AffectedAppInstanceIDs []string
	SelectedAction         string
	BalanceMinor           *int64
	CorrelationID          *string
	UpdatedAt              *time.Time
}

type FinancialRestrictionStore interface {
	QueryRow(ctx context.Context, sql string, args ...any) pgx.Row
}

type LinkProviderCustomerInput struct {
	OrgID              string
	Provider           string
	ProviderCustomerID string
	Source             string
	IsDefault          bool
	CreatedByUserID    string
}

type ProviderCustomer struct {
	ID                 string
	OrgID              string
	Provider           string
	ProviderCustomerID string
	Status             string
	IsDefault          bool
	Source             string
	CreatedAt          time.Time
	UpdatedAt          time.Time
}

type ProviderCustomerStore interface {
	Exec(ctx context.Context, sql string, arguments ...any) (pgconn.CommandTag, error)
	QueryRow(ctx context.Context, sql string, args ...any) pgx.Row
}

type BudgetPostureFilters struct {
	ScopeType string
	ProjectID string
}

type BudgetPostureEvent struct {
	ID            string
	ThresholdKey  string
	PeriodStart   time.Time
	PeriodEnd     time.Time
	SpentMinor    int64
	BudgetMinor   int64
	Currency      string
	PercentUsed   int64
	Status        string
	FirstSeenAt   time.Time
	LastSeenAt    time.Time
	SeenCount     int
	CorrelationID *string
}

type BudgetPostureItem struct {
	ID               string
	OrgID            string
	ProjectID        *string
	ScopeType        string
	DisplayName      string
	Period           string
	AmountMinor      int64
	Currency         string
	ThresholdPercent int
	EnforcementMode  string
	Active           bool
	StartsAt         time.Time
	EndsAt           *time.Time
	LatestEvent      *BudgetPostureEvent
	CreatedAt        time.Time
	UpdatedAt        time.Time
}

type BudgetThresholdScanInput struct {
	Now           time.Time
	CorrelationID string
}

type BudgetThresholdScanResult struct {
	CheckedAt     time.Time
	PoliciesSeen  int
	EventsWritten int
}

type BudgetDecisionInput struct {
	OrgID               string
	ProjectID           string
	ProposedAmountMinor int64
	Currency            string
	Now                 time.Time
}

type BudgetDecisionItem struct {
	BudgetPolicyID      string
	ScopeType           string
	ProjectID           *string
	DisplayName         string
	EnforcementMode     string
	Decision            string
	Reason              string
	PeriodStart         time.Time
	PeriodEnd           time.Time
	SpentMinor          int64
	ProposedAmountMinor int64
	ProjectedSpendMinor int64
	BudgetMinor         int64
	Currency            string
	ThresholdPercent    int
	PercentUsedBefore   int64
	PercentUsedAfter    int64
}

type BudgetDecisionResult struct {
	Decision string
	Items    []BudgetDecisionItem
}

type GenerateDraftInvoicesInput struct {
	PeriodStart   time.Time
	PeriodEnd     time.Time
	CorrelationID string
	Limit         int
}

type GenerateDraftInvoicesResult struct {
	PeriodStart     time.Time
	PeriodEnd       time.Time
	InvoicesCreated int
	LinesInvoiced   int
}

type InvoiceFilters struct {
	Cursor   string
	PageSize int
	Status   string
}

type InvoiceSummary struct {
	ID                      string
	OrgID                   string
	PeriodStart             time.Time
	PeriodEnd               time.Time
	Status                  string
	TotalMinor              int64
	Currency                string
	TaxTotalMinor           int64
	TaxJurisdiction         *string
	TaxTreatment            string
	SellerTaxRegistration   *string
	CustomerTaxRegistration *string
	TaxSnapshotJSON         string
	IssuedAt                *time.Time
	DueAt                   *time.Time
	FinalizedAt             *time.Time
	VoidedAt                *time.Time
	CreatedAt               time.Time
}

type InvoiceLine struct {
	ID                  string
	LineType            string
	Description         string
	AmountMinor         int64
	Currency            string
	RatedUsageLineID    *string
	LedgerEntryID       *string
	PaymentSessionID    *string
	TaxCategory         *string
	TaxRateBPS          *int
	TaxJurisdiction     *string
	TaxSubjectLineID    *string
	TaxExemptReason     *string
	ReverseChargeReason *string
	TaxEvidenceJSON     string
	CreatedAt           time.Time
}

type InvoiceDetail struct {
	InvoiceSummary
	Lines []InvoiceLine
}

type RatingInput struct {
	UsageRecordID       string
	UsageSource         string
	UsageUnit           string
	BillFrom            time.Time
	BillTo              time.Time
	UnitPriceMinor      int64
	Units               int64
	Currency            string
	PricingSource       string
	PricingPlanID       *string
	PricingPlanVersion  *string
	PricingSnapshotJSON string
}

type RatedUsageLine struct {
	RatingKey           string
	UsageRecordID       string
	UsageSource         string
	UsageUnit           string
	BillFrom            time.Time
	BillTo              time.Time
	UnitQuantityMillis  int64
	UnitPriceMinor      int64
	Units               int64
	AmountMinor         int64
	Currency            string
	PricingSource       string
	PricingPlanID       *string
	PricingPlanVersion  *string
	PricingSnapshotJSON string
}

type RatedUsageFilters struct {
	Cursor        string
	PageSize      int
	UsageRecordID string
}

type RatedUsageEvidenceLine struct {
	ID                  string
	UsageRecordID       string
	OrgID               *string
	ProjectID           *string
	RequestedByUserID   string
	UsageSource         string
	UsageUnit           string
	BillFrom            time.Time
	BillTo              time.Time
	UnitQuantityMillis  int64
	UnitPriceMinor      int64
	Units               int64
	AmountMinor         int64
	Currency            string
	PricingSource       string
	PricingPlanID       *string
	PricingPlanVersion  *string
	PricingSnapshotJSON string
	FXSnapshotJSON      *string
	RatingKey           string
	LedgerEntryID       *string
	InvoiceLineID       *string
	InvoiceID           *string
	CreatedAt           time.Time
}

type ShadowRatingInput struct {
	UsageRecordIDs      []string
	UnitPriceMinor      int64
	Currency            string
	PricingSource       string
	PricingPlanID       *string
	PricingPlanVersion  *string
	PricingSnapshotJSON string
}

type ShadowRatingLine struct {
	UsageRecordID             string
	ExistingRatedAmountMinor  int64
	CandidateRatedAmountMinor int64
	DeltaAmountMinor          int64
	CandidateRatingKey        string
	UsageSource               string
	UsageUnit                 string
	BillFrom                  time.Time
	BillTo                    time.Time
	UnitQuantityMillis        int64
	UnitPriceMinor            int64
	Units                     int64
	Currency                  string
	PricingSource             string
	PricingPlanID             *string
	PricingPlanVersion        *string
	PricingSnapshotJSON       string
}

type ShadowRatingResult struct {
	Lines                    []ShadowRatingLine
	ExistingRatedTotalMinor  int64
	CandidateRatedTotalMinor int64
	DeltaTotalMinor          int64
	Currency                 string
	LedgerWrites             bool
	RatedUsageWrites         bool
}

type RatedUsageLineInsertInput struct {
	Line      RatedUsageLine
	OrgID     string
	ProjectID string
	UserID    string
}

type LedgerPostingInput struct {
	RatedUsageLineID string
	OrgID            string
	ProjectID        string
	UserID           string
	AmountMinor      int64
	Currency         string
	ReferenceType    string
	ReferenceID      string
	MetadataJSON     string
}

type PostingStore interface {
	Exec(ctx context.Context, sql string, arguments ...any) (pgconn.CommandTag, error)
	QueryRow(ctx context.Context, sql string, args ...any) pgx.Row
}

type ManagedIngressUsageInput struct {
	OrgID                       string
	ProjectID                   string
	AppInstanceID               string
	RequestedByID               string
	RequestedByUserID           string
	RequestedByServiceAccountID string
	ActorType                   string
	ActorID                     string
	RouteID                     string
	EndpointName                string
	RouteFamily                 string
	ClientAuthMode              string
	ProxyPoolID                 string
	StartTime                   time.Time
	Duration                    time.Duration
	ResponseBytes               int64
	StatusCode                  int
	CorrelationID               string
}
