package model

import (
	"time"

	"github.com/tech/sendico/pkg/db/storable"
	"github.com/tech/sendico/pkg/model"
	"go.mongodb.org/mongo-driver/v2/bson"
)

const (
	FeePlansCollection = "fee_plans"
)

// Trigger represents the event that causes a fee rule to apply.
type Trigger string

const (
	TriggerUnspecified  Trigger = "unspecified"
	TriggerCapture      Trigger = "capture"
	TriggerRefund       Trigger = "refund"
	TriggerDispute      Trigger = "dispute"
	TriggerPayout       Trigger = "payout"
	TriggerFXConversion Trigger = "fx_conversion"
)

// FeePlan describes a collection of fee rules for an organisation.
type FeePlan struct {
	storable.Base     `bson:",inline" json:",inline"`
	model.Describable `bson:",inline" json:",inline"`

	OrganizationRef *bson.ObjectID    `bson:"organizationRef,omitempty" json:"organizationRef,omitempty"`
	Active          bool              `bson:"active"                    json:"active"`
	EffectiveFrom   time.Time         `bson:"effectiveFrom"             json:"effectiveFrom"`
	EffectiveTo     *time.Time        `bson:"effectiveTo,omitempty"     json:"effectiveTo,omitempty"`
	Rules           []FeeRule         `bson:"rules,omitempty"           json:"rules,omitempty"`
	Metadata        map[string]string `bson:"metadata,omitempty"        json:"metadata,omitempty"`
}

// Collection implements storable.Storable.
func (*FeePlan) Collection() string {
	return FeePlansCollection
}

// FeeRule represents a single pricing rule within a plan.
type FeeRule struct {
	RuleID           string            `bson:"ruleId"                     json:"ruleId"`
	Trigger          Trigger           `bson:"trigger"                    json:"trigger"`
	Priority         int               `bson:"priority"                   json:"priority"`
	Percentage       string            `bson:"percentage,omitempty"       json:"percentage,omitempty"`
	FixedAmount      string            `bson:"fixedAmount,omitempty"      json:"fixedAmount,omitempty"`
	Currency         string            `bson:"currency,omitempty"         json:"currency,omitempty"`
	MinimumAmount    string            `bson:"minimumAmount,omitempty"    json:"minimumAmount,omitempty"`
	MaximumAmount    string            `bson:"maximumAmount,omitempty"    json:"maximumAmount,omitempty"`
	AppliesTo        map[string]string `bson:"appliesTo,omitempty"        json:"appliesTo,omitempty"`
	Formula          string            `bson:"formula,omitempty"          json:"formula,omitempty"`
	Metadata         map[string]string `bson:"metadata,omitempty"         json:"metadata,omitempty"`
	LedgerAccountRef string            `bson:"ledgerAccountRef,omitempty" json:"ledgerAccountRef,omitempty"`
	LineType         string            `bson:"lineType,omitempty"         json:"lineType,omitempty"`
	EntrySide        string            `bson:"entrySide,omitempty"        json:"entrySide,omitempty"`
	Rounding         string            `bson:"rounding,omitempty"         json:"rounding,omitempty"`
	EffectiveFrom    time.Time         `bson:"effectiveFrom"              json:"effectiveFrom"`
	EffectiveTo      *time.Time        `bson:"effectiveTo,omitempty"      json:"effectiveTo,omitempty"`
}
