package dto

import (
	"encoding/json"
	"time"
)

// AppNotificationTargetRequest selects either one Human DM or an existing
// App-bound scope. Exactly one of MemberID and ScopeID is used according to
// Kind.
type AppNotificationTargetRequest struct {
	Kind     string `json:"kind"`
	MemberID string `json:"memberId,omitempty"`
	ScopeID  string `json:"scopeId,omitempty"`
}

// AppNotificationBusinessObjectRequest associates a notification with an
// owning-domain object and the version used to render it.
type AppNotificationBusinessObjectRequest struct {
	Namespace string `json:"namespace"`
	Type      string `json:"type"`
	ID        string `json:"id"`
	Version   int64  `json:"version"`
	URL       string `json:"url,omitempty"`
}

// AppNotificationRecipientBasisRequest identifies the typed owning-domain
// fact that authorizes a Human DM recipient.
type AppNotificationRecipientBasisRequest struct {
	Kind string `json:"kind"`
	Ref  string `json:"ref"`
}

// AppNotificationActorRefRequest records a verified business-source actor.
// Ingress authentication supplies the execution actor independently.
type AppNotificationActorRefRequest struct {
	Type string `json:"type"`
	ID   string `json:"id"`
}

// AppNotificationContentRequest carries either an ordinary message body or an
// interactive-card payload. Card remains raw JSON so registered components can
// evolve without the transport DTO becoming a second card schema.
type AppNotificationContentRequest struct {
	Kind          string          `json:"kind"`
	Text          string          `json:"text,omitempty"`
	FallbackText  string          `json:"fallbackText,omitempty"`
	Card          json.RawMessage `json:"card,omitempty"`
	AttachmentIDs []string        `json:"attachmentIds,omitempty"`
	Metadata      map[string]any  `json:"metadata,omitempty"`
}

// AppNotificationCreateRequest is shared by runtime and trusted-internal
// ingress after each adapter has authenticated its execution principal.
type AppNotificationCreateRequest struct {
	ClientNotificationID string                                `json:"clientNotificationId"`
	Target               AppNotificationTargetRequest          `json:"target"`
	Content              AppNotificationContentRequest         `json:"content"`
	BusinessObject       *AppNotificationBusinessObjectRequest `json:"businessObject,omitempty"`
	RecipientBasis       *AppNotificationRecipientBasisRequest `json:"recipientBasis,omitempty"`
	CausedByActor        *AppNotificationActorRefRequest       `json:"causedByActor,omitempty"`
	ExpiresAt            *time.Time                            `json:"expiresAt,omitempty"`
	CorrelationID        string                                `json:"correlationId,omitempty"`
}

// AppNotificationMutationRequest updates the visible projection while keeping
// the notification message identity stable.
type AppNotificationMutationRequest struct {
	ExpectedRevision       int64                           `json:"expectedRevision"`
	ClientMutationID       string                          `json:"clientMutationId"`
	Content                *AppNotificationContentRequest  `json:"content,omitempty"`
	BusinessObjectVersion  *int64                          `json:"businessObjectVersion,omitempty"`
	CausedByActor          *AppNotificationActorRefRequest `json:"causedByActor,omitempty"`
	CorrelationID          string                          `json:"correlationId,omitempty"`
	ServiceEventDeliveryID string                          `json:"serviceEventDeliveryId,omitempty"`
	AttemptID              string                          `json:"attemptId,omitempty"`
}

// AppNotificationWithdrawRequest closes the visible message and its actions.
type AppNotificationWithdrawRequest struct {
	ExpectedRevision       int64                           `json:"expectedRevision"`
	ClientMutationID       string                          `json:"clientMutationId"`
	Reason                 string                          `json:"reason"`
	CausedByActor          *AppNotificationActorRefRequest `json:"causedByActor,omitempty"`
	CorrelationID          string                          `json:"correlationId,omitempty"`
	ServiceEventDeliveryID string                          `json:"serviceEventDeliveryId,omitempty"`
	AttemptID              string                          `json:"attemptId,omitempty"`
}

// AppNotificationActionRequest invokes one callback action from the current
// card revision as the authenticated Human member.
type AppNotificationActionRequest struct {
	CardRevision   int64          `json:"cardRevision"`
	ClientActionID string         `json:"clientActionId"`
	Input          map[string]any `json:"input,omitempty"`
}

// AppNotificationResponse is the canonical notification resource projection.
type AppNotificationResponse struct {
	Accepted             bool       `json:"accepted"`
	AlreadyCreated       bool       `json:"alreadyCreated,omitempty"`
	AlreadyApplied       bool       `json:"alreadyApplied,omitempty"`
	NotificationID       string     `json:"notificationId"`
	NotificationRevision int64      `json:"notificationRevision"`
	MessageID            string     `json:"messageId"`
	ScopeID              string     `json:"scopeId"`
	MessageSeq           int64      `json:"messageSeq"`
	Status               string     `json:"status"`
	ContentKind          string     `json:"contentKind"`
	CorrelationID        string     `json:"correlationId"`
	ExpiresAt            *time.Time `json:"expiresAt,omitempty"`
	ResolvedAt           *time.Time `json:"resolvedAt,omitempty"`
	WithdrawnAt          *time.Time `json:"withdrawnAt,omitempty"`
	CreatedAt            time.Time  `json:"createdAt"`
	UpdatedAt            time.Time  `json:"updatedAt"`
}

// AppNotificationActionResponse returns the durable invocation and delivery
// refs plus the authoritative notification/card revision.
type AppNotificationActionResponse struct {
	Accepted               bool   `json:"accepted"`
	AlreadyAccepted        bool   `json:"alreadyAccepted,omitempty"`
	ActionInvocationID     string `json:"actionInvocationId"`
	ServiceEventDeliveryID string `json:"serviceEventDeliveryId"`
	NotificationID         string `json:"notificationId"`
	MessageID              string `json:"messageId"`
	CardRevision           int64  `json:"cardRevision"`
	NotificationRevision   int64  `json:"notificationRevision"`
	State                  string `json:"state"`
	CorrelationID          string `json:"correlationId"`
}

// AppNotificationCardResponse is the current Human-readable projection for
// an interactive-card message.
type AppNotificationCardResponse struct {
	NotificationID       string          `json:"notificationId"`
	NotificationRevision int64           `json:"notificationRevision"`
	NotificationStatus   string          `json:"notificationStatus"`
	MessageID            string          `json:"messageId"`
	ScopeID              string          `json:"scopeId"`
	SchemaVersion        string          `json:"schemaVersion"`
	CardRevision         int64           `json:"cardRevision"`
	RenderPayload        json.RawMessage `json:"renderPayload"`
	State                string          `json:"state"`
	ExpiresAt            *time.Time      `json:"expiresAt,omitempty"`
	CreatedAt            time.Time       `json:"createdAt"`
	UpdatedAt            time.Time       `json:"updatedAt"`
}
