// Package notify 定义通知模块的领域类型与 Notifier 接口契约。
//
// 本文件仅做类型与接口声明，不包含任何具体投递实现。各类通道（dummy /
// email / webhook / IM 等）的真实发送逻辑由独立子包提供，并通过实现
// Notifier 接口接入到通知服务的多通道分发流程。Channel 与 Severity 使用
// 字符串别名作为枚举载体，便于直接落库与日志输出，同时仍保留类型安全。
package notify

import (
	"context"
	"time"

	"github.com/google/uuid"
)

// Channel 标识一条通知所走的投递通道。值与运行时配置/数据库中存储的字符串
// 表示一致，新增通道时在此追加常量并实现对应的 Notifier。
type Channel string

const (
	// ChannelDummy 仅用于本地与测试环境，不做任何真实外发。
	ChannelDummy Channel = "dummy"
	// ChannelEmail 通过 SMTP 或邮件服务商投递邮件。
	ChannelEmail Channel = "email"
	// ChannelWebhook 通过 HTTP 调用外部 webhook 投递。
	ChannelWebhook Channel = "webhook"
	// ChannelIM 通过即时通信服务（如企业 IM）投递。
	ChannelIM Channel = "im"
)

// Severity 表示通知的重要级别。取值与 notifications 表中的 severity 列字符串
// 对齐，避免在持久化与传输层做额外映射。
type Severity string

const (
	// SeverityInfo 为常规提示，不要求用户立即处理。
	SeverityInfo Severity = "info"
	// SeverityWarning 表示需要用户关注但尚未失败的状况。
	SeverityWarning Severity = "warning"
	// SeverityError 表示已经发生失败或风险事件，需用户尽快处理。
	SeverityError Severity = "error"
)

// Message 是跨通道传递的通知载荷。各 Notifier 实现按需读取字段，未消费的
// 字段（例如纯 IM 通知的 Link）应保持为零值而非占位字符串，以便日志与审计
// 区分缺省与显式空。Metadata 仅存放结构化的扩展字段，不承载敏感原文。
type Message struct {
	ID        uuid.UUID
	UserID    uuid.UUID
	Topic     string
	Severity  Severity
	Title     string
	Body      string
	Link      string
	Metadata  map[string]any
	// ReadAt 表示该通知的已读时间。nil 表示未读，非 nil 表示用户已读的时刻。
	ReadAt    *time.Time
	CreatedAt time.Time
}

// Notifier 是单一投递通道的统一契约。Name 返回该实现对应的 Channel，便于
// 上层根据配置路由消息；Send 必须是同步语义——返回 nil 视为投递成功，否则
// 由上层决定是否重试或记录失败。实现需要尊重 ctx 的取消与超时。
type Notifier interface {
	Name() Channel
	Send(ctx context.Context, msg Message) error
}
