package event

import (
	"encoding/json"
	"time"
)

// Event represents a raw alert instance from alertmanager.
// One row per alert instance (not per group).
type Event struct {
	ID              int64           `db:"id" json:"id" validate:"required"`
	ReceiptID       *int64          `db:"receipt_id" json:"receipt_id,omitempty"`
	InstanceID      *int64          `db:"instance_id" json:"instance_id,omitempty"`
	GroupKey        string          `db:"group_key" json:"group_key" validate:"required"`
	Fingerprint     string          `db:"fingerprint" json:"fingerprint" validate:"required"`
	Status          string          `db:"status" json:"status" validate:"required"` // firing / resolved
	ObservationType string          `db:"observation_type" json:"observation_type" validate:"required"`
	Attrs           json.RawMessage `db:"attrs" json:"attrs" swaggertype:"object" validate:"required"`
	StartsAt        time.Time       `db:"starts_at" json:"starts_at" validate:"required"`
	EndsAt          *time.Time      `db:"ends_at" json:"ends_at,omitempty"`
	ReceivedAt      time.Time       `db:"received_at" json:"received_at" validate:"required"`
	Alertname       string          `db:"alertname" json:"alertname" validate:"required"`
	Classification  string          `db:"classification" json:"classification" validate:"required"`
	ClusterID       string          `db:"cluster_id" json:"cluster_id" validate:"required"`
	TenantID        string          `db:"tenant_id" json:"tenant_id" validate:"required"`
	Region          string          `db:"region" json:"region" validate:"required"`
	BizRegion       string          `db:"biz_region" json:"biz_region" validate:"required"`
	TenantKind      string          `db:"tenant_kind" json:"tenant_kind" validate:"required"`
	CustomerType    string          `db:"customer_type" json:"customer_type" validate:"required"`
}

// EventAttrs contains the business fields stored in the attrs JSON column.
type EventAttrs struct {
	Alertname              string `json:"alertname"`
	Classification         string `json:"classification"`
	OriginalClassification string `json:"original_classification"`
	ClusterID              string `json:"cluster_id"`
	ClusterName            string `json:"cluster_name,omitempty"`
	ClusterVersion         string `json:"cluster_version,omitempty"`
	DeployType             string `json:"deploy_type,omitempty"`
	ClinicURL              string `json:"clinic_url,omitempty"`
	TenantID               string `json:"tenant_id"`
	// TenantName, BizRegion and TenantKind come from the DevOps ops portal
	// (pkg/devops), which owns the commercial view of the account. BizRegion is
	// the sales region — NA, EMEA, APAC — as opposed to Region below, which is
	// the cloud region the alert's own labels carry. TenantKind is `internal`
	// or `external`: ours or a customer's.
	TenantName string `json:"tenant_name,omitempty"`
	BizRegion  string `json:"biz_region,omitempty"`
	TenantKind string `json:"tenant_kind,omitempty"`
	// CustomerType is the account's sales tier (SKA/KA/SMB), which the ops
	// portal calls segmentation. Alertstore's own name for it, and the one its
	// filters have used since the service was designed.
	CustomerType string `json:"customer_type,omitempty"`
	Region       string `json:"region"`
	Component    string `json:"component"`
	// Visibility records who the rule was written for, so a query over the
	// event history can separate what customers were told from what we told
	// ourselves. Empty means internal; see alert.VisibilityExternal.
	Visibility   string            `json:"visibility,omitempty"`
	Labels       map[string]string `json:"labels"`
	Annotations  map[string]string `json:"annotations"`
	GeneratorURL string            `json:"generator_url"`
}

// Notice is what the alert lifecycle knows about one observation that its
// event row does not: which human alert it landed on, if any, and how it
// relates to the occurrence's own history. Both are decided while routing and
// would cost a second lookup to recover, so they travel with the event to
// whoever renders it.
type Notice struct {
	// AlertID names the alert this observation was bound to, empty when it
	// opened none (a logging observation, or one nobody responds to).
	AlertID string
	// Classification is the observation's own, which for a bound alert may
	// differ from the alert's: classification is frozen when an alert is
	// created, and the rules can change under it.
	Classification string
	// ObservationType is first_firing / repeat_firing / resolved — the
	// distinction the alert view deliberately hides.
	ObservationType string
	// MuteRuleID and MuteReason name the active rule that stopped this
	// observation from opening an alert. A page-class observation that opened
	// none is otherwise inexplicable, and a mute rule is almost always why.
	MuteRuleID string
	MuteReason string
}

// ReceiptInfo is delivery-level metadata surfaced only for diagnostics such as
// truncated Alertmanager notifications. It is not alert business context.
type ReceiptInfo struct {
	ID                 int64     `db:"id" json:"id" validate:"required"`
	Receiver           string    `db:"receiver" json:"receiver" validate:"required"`
	GroupKey           string    `db:"group_key" json:"group_key" validate:"required"`
	TruncatedAlerts    int       `db:"truncated_alerts" json:"truncated_alerts" validate:"required"`
	NotificationReason string    `db:"notification_reason" json:"notification_reason" validate:"required"`
	ReceivedAt         time.Time `db:"received_at" json:"received_at" validate:"required"`
}
