package discovery

import "github.com/tech/sendico/pkg/mservice"

type HealthParams struct {
	IntervalSec int `json:"intervalSec"`
	TimeoutSec  int `json:"timeoutSec"`
}

// CurrencyAmount defines per-transfer min/max for a unit (fiat currency or crypto asset).
// Values are decimals in string form to avoid float issues.
type CurrencyAmount struct {
	Min string `json:"min,omitempty"`
	Max string `json:"max,omitempty"`
}

// CalendarUnit is used for calendar-aligned windows (e.g. 1 calendar month).
type CalendarUnit string

const (
	CalendarUnitUnspecified CalendarUnit = ""
	CalendarUnitHour        CalendarUnit = "hour"
	CalendarUnitDay         CalendarUnit = "day"
	CalendarUnitWeek        CalendarUnit = "week"
	CalendarUnitMonth       CalendarUnit = "month"
)

// CalendarWindow represents a calendar-aligned window.
// Example: {unit:"month", count:1} means "1 calendar month".
type CalendarWindow struct {
	Unit  CalendarUnit `json:"unit"`
	Count int          `json:"count"`
}

// Window is a typed description of a running-limit window.
// Gateways/providers can express windows differently, so we keep:
// - Raw: original provider token/string (optional but recommended)
// and one of the normalized forms:
// - Duration: fixed window expressed as a Go-duration string (e.g. "24h", "168h")
// - Calendar: calendar-aligned window (e.g. 1 month)
// - Named: opaque provider token when you do not want/cannot normalize (e.g. "daily")
type Window struct {
	// Raw may be set alongside the normalized form.
	// Normalized form: exactly one of Duration/Calendar/Named SHOULD be set.
	Raw string `json:"raw,omitempty"`

	// Duration uses Go time.Duration format and MUST NOT use "d".
	// Use "24h", "168h", "720h", etc.
	Duration string          `json:"duration,omitempty"` // e.g. "24h"
	Calendar *CalendarWindow `json:"calendar,omitempty"` // e.g. month x1
	Named    string          `json:"named,omitempty"`    // e.g. "daily"
}

// VolumeLimit is the max total amount allowed within a window.
// Amount is a decimal string in the same unit as the announcement (currency/asset).
type VolumeLimit struct {
	Window Window `json:"window"`
	Max    string `json:"max"`
}

// VelocityLimit is the max number of operations allowed within a window.
type VelocityLimit struct {
	Window Window `json:"window"`
	Max    int    `json:"max"`
}

// CurrencyRunningLimits groups windowed limits.
// Slices are used instead of maps to avoid relying on untyped map keys.
type CurrencyRunningLimits struct {
	Volume   []VolumeLimit   `json:"volume,omitempty"`
	Velocity []VelocityLimit `json:"velocity,omitempty"`
}

// CurrencyLimits combines per-transfer and running limits for a unit.
type CurrencyLimits struct {
	Amount  *CurrencyAmount        `json:"amount,omitempty"`
	Running *CurrencyRunningLimits `json:"running,omitempty"`
}

// Limits is a legacy flat limits shape used by lookup summaries.
// Deprecated: use CurrencyAnnouncement.Limits for announcement payloads.
type Limits struct {
	MinAmount     string            `json:"minAmount,omitempty"`
	MaxAmount     string            `json:"maxAmount,omitempty"`
	VolumeLimit   map[string]string `json:"volumeLimit,omitempty"`
	VelocityLimit map[string]int    `json:"velocityLimit,omitempty"`
}

// CurrencyAnnouncement declares limits for a unit.
// For fiat: Currency is ISO 4217 ("EUR", "USD").
// For crypto: Currency is the ticker ("USDT", "BTC") and you SHOULD also fill Network,
// and for tokens ContractAddress + Decimals.
type CurrencyAnnouncement struct {
	// Unit identity
	Currency        string `json:"currency"`                  // fiat code or crypto ticker
	Network         string `json:"network,omitempty"`         // crypto chain or fiat rail, e.g. "tron", "ethereum", "sepa", "swift", "visa"
	ProviderID      string `json:"providerId,omitempty"`      // specific provider identifier providing currency over network/rail (e.g. "binance", "circle")
	ContractAddress string `json:"contractAddress,omitempty"` // for tokens only
	Decimals        *int   `json:"decimals,omitempty"`        // for crypto/token precision

	// Limits for this unit
	Limits *CurrencyLimits `json:"limits,omitempty"`
}

type Announcement struct {
	ID              string                 `json:"id"`
	InstanceID      string                 `bson:"instanceId" json:"instanceId"`
	Service         mservice.Type          `json:"service"`
	Rail            string                 `json:"rail,omitempty"`
	Operations      []string               `json:"operations,omitempty"`
	Currencies      []CurrencyAnnouncement `json:"currencies,omitempty"`
	InvokeURI       string                 `json:"invokeURI,omitempty"`
	RoutingPriority int                    `json:"routingPriority,omitempty"`
	Version         string                 `json:"version,omitempty"`
	Health          HealthParams           `json:"health,omitempty"`
}

type Heartbeat struct {
	ID         string `json:"id"`
	InstanceID string `json:"instanceId"`
	EntryKey   string `json:"entryKey,omitempty"`
	Status     string `json:"status"`
	TS         int64  `json:"ts"`
}

type RefreshEvent struct {
	InstanceID string `json:"instanceId,omitempty"`
	Service    string `json:"service,omitempty"`
	Rail       string `json:"rail,omitempty"`
	Network    string `json:"network,omitempty"`
	Message    string `json:"message,omitempty"`
}
