package types

// InsufficientNetPolicy indicates how to handle insufficient net funds for fees.
type InsufficientNetPolicy string

const (
	InsufficientNetUnspecified  InsufficientNetPolicy = "UNSPECIFIED"
	InsufficientNetBlockPosting InsufficientNetPolicy = "BLOCK_POSTING"
	InsufficientNetSweepOrgCash InsufficientNetPolicy = "SWEEP_ORG_CASH"
	InsufficientNetInvoiceLater InsufficientNetPolicy = "INVOICE_LATER"
)

// FeePolicy captures optional fee policy overrides.
type FeePolicy struct {
	InsufficientNet InsufficientNetPolicy `bson:"insufficientNet,omitempty" json:"insufficientNet,omitempty"`
}

// EntrySide captures debit/credit semantics for fee lines.
type EntrySide string

const (
	EntrySideUnspecified EntrySide = "UNSPECIFIED"
	EntrySideDebit       EntrySide = "DEBIT"
	EntrySideCredit      EntrySide = "CREDIT"
)

// PostingLineType captures the semantic type of a fee line.
type PostingLineType string

const (
	PostingLineTypeUnspecified PostingLineType = "UNSPECIFIED"
	PostingLineTypeFee         PostingLineType = "FEE"
	PostingLineTypeTax         PostingLineType = "TAX"
	PostingLineTypeSpread      PostingLineType = "SPREAD"
	PostingLineTypeReversal    PostingLineType = "REVERSAL"
)

// RoundingMode captures rounding behavior for fee rules.
type RoundingMode string

const (
	RoundingModeUnspecified RoundingMode = "UNSPECIFIED"
	RoundingModeHalfEven    RoundingMode = "HALF_EVEN"
	RoundingModeHalfUp      RoundingMode = "HALF_UP"
	RoundingModeDown        RoundingMode = "DOWN"
)

// FeeLine stores derived fee posting data.
type FeeLine struct {
	LedgerAccountRef string            `bson:"ledgerAccountRef,omitempty" json:"ledgerAccountRef,omitempty"`
	Money            *Money            `bson:"money,omitempty" json:"money,omitempty"`
	LineType         PostingLineType   `bson:"lineType,omitempty" json:"lineType,omitempty"`
	Side             EntrySide         `bson:"side,omitempty" json:"side,omitempty"`
	Meta             map[string]string `bson:"meta,omitempty" json:"meta,omitempty"`
}

func (l *FeeLine) GetMoney() *Money {
	if l == nil {
		return nil
	}
	return l.Money
}

func (l *FeeLine) GetSide() EntrySide {
	if l == nil {
		return EntrySideUnspecified
	}
	return l.Side
}

func (l *FeeLine) GetLineType() PostingLineType {
	if l == nil {
		return PostingLineTypeUnspecified
	}
	return l.LineType
}

func (l *FeeLine) GetLedgerAccountRef() string {
	if l == nil {
		return ""
	}
	return l.LedgerAccountRef
}

// AppliedRule stores fee rule audit data.
type AppliedRule struct {
	RuleID      string            `bson:"ruleId,omitempty" json:"ruleId,omitempty"`
	RuleVersion string            `bson:"ruleVersion,omitempty" json:"ruleVersion,omitempty"`
	Formula     string            `bson:"formula,omitempty" json:"formula,omitempty"`
	Rounding    RoundingMode      `bson:"rounding,omitempty" json:"rounding,omitempty"`
	TaxCode     string            `bson:"taxCode,omitempty" json:"taxCode,omitempty"`
	TaxRate     string            `bson:"taxRate,omitempty" json:"taxRate,omitempty"`
	Parameters  map[string]string `bson:"parameters,omitempty" json:"parameters,omitempty"`
}
