package api

import (
	"time"

	"code.justin.tv/feeds/feeds-common/entity"
)

// ExtractMessageRequest is the body for the POST /v1/maap/extraction/extract endpoint
type ExtractMessageRequest struct {
	// SenderID is the user sending the message.
	SenderID string `json:"sender_id"`
	// MessageText is the message body.
	MessageText string `json:"message_text"`
	// ContainerOwner is the entity that owns the container the message will be
	// published to, if any.
	// For example, chatrooms have owners, but whispers do not.
	ContainerOwner *entity.Entity `json:"container_owner_id"`

	// Optional arguments:
	Namespace string `json:"namespace"`
	// Max allowed character length in the message text before truncation.
	MaxCharacterLength *int `json:"max_character_length"`
	// Enforcement Rules to apply to this extraction
	EnforcementRules []string `json:"enforcement_rules"`
	// OmitDefaultEnforcements allows you to omit default enforcement rules
	OmitDefaultEnforcements bool `json:"override_all_enforcement_rules"`
	// AlwaysReturn says that even if a rule fails, we should still give back the full response
	AlwaysReturn bool `json:"always_return"`
}

// ExtractMessageResponse is the response for the POST /v1/maap/extraction/extract endpoint
type ExtractMessageResponse struct {
	Container MessageContainer `json:"container"`
	Risk      MessageRisk      `json:"risk"`
	Content   MessageContent   `json:"content"`
	Sender    MessageSender    `json:"sender"`
}

// EnforceMessageRequest is the body for the POST /v2/maap/messages/enforce endpoint
type EnforceMessageRequest struct {
	// SenderID is the user sending the message.
	SenderID string `json:"sender_id"`
	// MessageText is the message body.
	MessageText string `json:"message_text"`
	// ContainerOwner is the entity that owns the container the message will be
	// published to, if any.
	// For example, chatrooms have owners, but whispers do not.
	ContainerOwner *entity.Entity `json:"container_owner_id"`
	// EnforcementRules defines which enforcement rules to run on this message.
	EnforcementRules EnforcementRuleset `json:"enforcement_rules"`
	// EnforcementConfig lets you tune various enforcement rules with additional parameters
	EnforcementConfig EnforcementConfiguration `json:"enforcement_configuration"`

	// MaxCharacterLength, if set, will truncate the message text.
	// Defaults to 1000 runes (not bytes).
	MaxCharacterLength *int `json:"max_character_length"`
	// SkipExtraction sets whether the client does not require parsed metadata from the message text.
	// Clients that only care about enforcement checks should set this to true
	SkipExtraction bool `json:"skip_extraction"`
}

// EnforceMessageResponse is the POST'd response for /v2/maap/extraction/enforce endpoint
type EnforceMessageResponse struct {
	ExtractProperties `json:"extract"`
	EnforceProperties `json:"enforce"`
}

// ListMessagesRequest is the body for the POST /v1/maap/messages/list endpoint.
type ListMessagesRequest struct {
	ContainerID   string `json:"container_id"`
	Namespace     string `json:"namespace"`
	Limit         int    `json:"limit"`
	Cursor        string `json:"cursor"`
	SortAscending bool   `json:"sort_ascending"`
	// If set, the History field will be populated in the response messages with a list of edits and deletes.
	// This should only be used for moderation purposes, and should not be exposed to regular users.
	IncludeHistory          bool `json:"include_history"`
	ReturnOnlyPendingReview bool `json:"return_only_pending_review"`
}

// ListMessagesResponse is the response for the POST /v1/maap/messages/list endpoint.
type ListMessagesResponse struct {
	Results         []MessageResult `json:"results"`
	HasPreviousPage bool            `json:"has_previous_page"`
	HasNextPage     bool            `json:"has_next_page"`
}

// ListMessagesBySenderRequest is the body for the POST /v1/maap/messages/list_by_sender endpoint.
type ListMessagesBySenderRequest struct {
	SenderID       string        `json:"sender_id" validate:"nonzero"`
	ContainerOwner entity.Entity `json:"owner_id" validate:"nonzero"`
	Limit          int           `json:"limit" validate:"min=1,max=100"`
	Cursor         string        `json:"cursor"`
	SortAscending  bool          `json:"sort_ascending"`
}

// ListMessagesBySenderResponse is the response for the POST /v1/maap/messages/list_by_sender endpoint.
type ListMessagesBySenderResponse struct {
	Results         []MessageResult `json:"results"`
	HasPreviousPage bool            `json:"has_previous_page"`
	HasNextPage     bool            `json:"has_next_page"`
}

// GetMessageRequest is the body for the POST /v1/maap/messages/get endpoint.
type GetMessageRequest struct {
	Namespace string `json:"namespace"`
	MessageID string `json:"message_id"`
	// If set, the History field will be populated in the response with a list of edits and deletes.
	// This should only be used for moderation purposes, and should not be exposed to regular users.
	IncludeHistory bool `json:"include_history"`
}

// GetMessageResponse is the response for the POST /v1/maap/messages/get endpoint.
type GetMessageResponse struct {
	Message Message `json:"message"`
}

// CreateMessageRequest is the body for the POST /v1/maap/messages/create endpoint.
type CreateMessageRequest struct {
	ContainerID string         `json:"container_id"`
	Namespace   string         `json:"namespace"`
	Content     MessageContent `json:"content"`
	Sender      MessageSender  `json:"sender"`
	BitsAmount  int            `json:"bits_amount"`
	Databag     Databag        `json:"databag"`

	// OrderByKey is an optional string that will be used for sorting/indexing
	// in the backend datastore. If not set, OrderByKey will default to the
	// message creation time in Unix nanoseconds.
	//
	// NOTE: It is the caller's responsibility to ensure this string is natively
	// sortable. For example, numbers are NOT sortable unless they are left-padded
	// to the same length (example: "400" > "1000", but "0400" < "1000").
	OrderByKey *string `json:"order_by_key"`
}

// CreateMessageResponse is the response for the POST /v1/maap/messages/create endpoint.
type CreateMessageResponse GetMessageResponse

// EditMessageRequest is the body for the POST /v1/maap/messages/edit endpoint.
type EditMessageRequest struct {
	MessageID string         `json:"message_id"`
	Namespace string         `json:"namespace"`
	EditorID  string         `json:"editor_id"`
	Content   MessageContent `json:"content"`
	// DoNotUpdateTimestamp is a parameter that should only be set by
	// internal services. When true, the message will be edited
	// but its timestamp will not be updated, nor a MessageChange saved.
	DoNotUpdateTimestamp bool `json:"do_not_update_timestamp"`
}

// EditMessageResponse is the response for the POST /v1/maap/messages/edit endpoint.
type EditMessageResponse GetMessageResponse

// DeleteMessageRequest is the body for the POST /v1/maap/messages/delete endpoint.
type DeleteMessageRequest struct {
	MessageID string `json:"message_id"`
	Namespace string `json:"namespace"`
	DeleterID string `json:"deleter_id"`
}

// DeleteMessageResponse is the response for the POST /v1/maap/messages/delete endpoint.
type DeleteMessageResponse GetMessageResponse

// ApproveMessageRequest is the body for the POST /v1/maap/messages/approve endpoint.
type ApproveMessageRequest struct {
	MessageID   string `json:"message_id"`
	ContainerID string `json:"container_id"`
	Namespace   string `json:"namespace"`
	ApproverID  string `json:"approver_id"`
}

// ApproveMessageResponse is the response for the POST /v1/maap/messages/approve endpoint.
type ApproveMessageResponse GetMessageResponse

// RejectMessageRequest is the body for the POST /v1/maap/messages/reject endpoint.
type RejectMessageRequest struct {
	MessageID  string `json:"message_id"`
	Namespace  string `json:"namespace"`
	RejecterID string `json:"rejecter_id"`
}

// RejectMessageResponse is the response for the POST /v1/maap/messages/reject endpoint.
type RejectMessageResponse GetMessageResponse

// BulkUpdateMessagesRequest is the body for the POST /v1/maap/messages/bulk_update endpoint.
type BulkUpdateMessagesRequest struct {
	UpdaterID   string   `json:"updater_id" validate:"nonzero"`
	MessageIDs  []string `json:"message_ids" validate:"min=1,max=1000"`
	IsPublished *bool    `json:"is_published"`
}

// BulkUpdateMessagesResponse is the response for the POST /v1/maap/messages/bulk_update endpoint.
type BulkUpdateMessagesResponse struct {
	UnprocessedMessageIDs []string `json:"unprocessed_message_ids"`
	Errors                []string `json:"errors"`
}

// ListContainersByOwnerRequest is the body for the POST /v1/maap/containers/list endpoint.
type ListContainersByOwnerRequest struct {
	Namespace      string        `json:"namespace"`
	ContainerOwner entity.Entity `json:"owner_id"`
	Limit          int           `json:"limit"`
	Cursor         string        `json:"cursor"`
}

// ListContainersByOwnerResponse is the body for the POST /v1/maap/containers/list endpoint.
type ListContainersByOwnerResponse struct {
	Containers []Container `json:"containers"`
	Cursor     string      `json:"cursor"`
}

// GetContainerRequest is the body for the POST /v1/maap/containers/get endpoint.
type GetContainerRequest struct {
	ContainerID string `json:"container_id"`
	Namespace   string `json:"namespace"`
}

// GetContainerResponse is the response for the POST /v1/maap/containers/get endpoint.
type GetContainerResponse struct {
	Container Container `json:"container"`
}

// GetContainerByUniqueNameRequest is the body for the POST /v1/maap/containers/get_by_name endpoint.
type GetContainerByUniqueNameRequest struct {
	Namespace  string `json:"namespace"`
	UniqueName string `json:"unique_name"`
}

// GetContainerByUniqueNameResponse is the response for the POST /v1/maap/containers/get_by_name endpoint.
type GetContainerByUniqueNameResponse GetContainerResponse

// CreateContainerRequest is the body for the POST /v1/maap/containers/create endpoint.
type CreateContainerRequest struct {
	Namespace      string         `json:"namespace"`
	UniqueName     string         `json:"unique_name"`
	ContainerOwner *entity.Entity `json:"owner_id"`
	RequireReview  string         `json:"require_review"`
	Databag        Databag        `json:"databag"`
}

// CreateContainerResponse is the response for the POST /v1/maap/containers/create endpoint.
type CreateContainerResponse GetContainerResponse

// DeleteContainerRequest is the body for the POST /v1/maap/containers/delete endpoint.
type DeleteContainerRequest struct {
	Namespace   string `json:"namespace"`
	ContainerID string `json:"container_id"`
}

// DeleteContainerResponse is the response for the POST /v1/maap/containers/delete endpoint.
type DeleteContainerResponse GetContainerResponse

// UpdateContainerRequest is the body for the POST /v1/maap/containers/update endpoint.
type UpdateContainerRequest struct {
	ID             string               `json:"id"`
	Namespace      string               `json:"namespace"`
	UniqueName     *string              `json:"unique_name"`
	ContainerOwner *entity.Entity       `json:"owner_id"`
	RequireReview  *string              `json:"require_review"`
	DatabagUpdates []DatabagFieldUpdate `json:"databag_updates"`
}

// UpdateContainerResponse is the response for the POST /v1/maap/containers/update endpoint.
type UpdateContainerResponse GetContainerResponse

// ListContainerViewsByUserRequest is the body for the POST /v1/maap/container_views/list endpoint.
type ListContainerViewsByUserRequest struct {
	UserID        string `json:"user_id"`
	Namespace     string `json:"namespace"`
	Limit         int    `json:"limit"`
	Cursor        string `json:"cursor"`
	SortAscending bool   `json:"sort_ascending"`
}

// ListContainerViewsByUserResponse is the response for the POST /v1/maap/container_views/list endpoint.
type ListContainerViewsByUserResponse struct {
	ContainerViews []ContainerView `json:"container_views"`
	Cursor         string          `json:"cursor"`
}

// GetContainerViewRequest is the body for the POST /v1/maap/container_views/get endpoint.
type GetContainerViewRequest struct {
	UserID      string `json:"user_id"`
	ContainerID string `json:"container_id"`
	Namespace   string `json:"namespace"`
}

// GetContainerViewResponse is the response for the POST /v1/maap/container_views/get endpoint.
type GetContainerViewResponse struct {
	ContainerView ContainerView `json:"container_view"`
}

// BulkGetContainerViewsRequest is the body for the POST /v1/maap/container_views/bulk_get endpoint.
type BulkGetContainerViewsRequest struct {
	UserID       string   `json:"user_id"`
	ContainerIDs []string `json:"container_ids"`
	Namespace    string   `json:"namespace"`
}

// BulkGetContainerViewsResponse is the response for the POST /v1/maap/container_views/bulk_get endpoint.
type BulkGetContainerViewsResponse struct {
	ContainerViews map[string]ContainerView `json:"container_views"`
}

// UpdateContainerViewRequest is the body for the POST /v1/maap/container_views/update endpoint.
type UpdateContainerViewRequest struct {
	UserID                 string     `json:"user_id"`
	ContainerID            string     `json:"container_id"`
	Namespace              string     `json:"namespace"`
	IsArchived             *bool      `json:"is_archived"`
	IsMuted                *bool      `json:"is_muted"`
	LastReadAt             *time.Time `json:"last_read_at"`
	ResetUnreadNoticeCount bool       `json:"reset_unread_notice_count"`
}

// UpdateContainerViewResponse is the response for the POST /v1/maap/container_views/update endpoint.
type UpdateContainerViewResponse GetContainerViewResponse
