// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.30.0
// source: messages.sql

package dbgen

import (
	"context"
	"database/sql"
)

const createMessage = `-- name: CreateMessage :one
INSERT INTO messages (channel_id, user_id, content, reply_to) VALUES (?, ?, ?, ?)
RETURNING id, channel_id, user_id, content, reply_to, edited_at, deleted, pinned, timestamp,
          mentions_everyone
`

type CreateMessageParams struct {
	ChannelID int64  `json:"channelId"`
	UserID    int64  `json:"userId"`
	Content   string `json:"content"`
	ReplyTo   *int64 `json:"replyTo"`
}

func (q *Queries) CreateMessage(ctx context.Context, arg CreateMessageParams) (Message, error) {
	row := q.db.QueryRowContext(ctx, createMessage,
		arg.ChannelID,
		arg.UserID,
		arg.Content,
		arg.ReplyTo,
	)
	var i Message
	err := row.Scan(
		&i.ID,
		&i.ChannelID,
		&i.UserID,
		&i.Content,
		&i.ReplyTo,
		&i.EditedAt,
		&i.Deleted,
		&i.Pinned,
		&i.Timestamp,
		&i.MentionsEveryone,
	)
	return i, err
}

const editMessageContent = `-- name: EditMessageContent :one
UPDATE messages SET content = ?, edited_at = datetime('now') WHERE id = ?
RETURNING id, channel_id, user_id, content, reply_to, edited_at, deleted, pinned, timestamp,
          mentions_everyone
`

type EditMessageContentParams struct {
	Content string `json:"content"`
	ID      int64  `json:"id"`
}

func (q *Queries) EditMessageContent(ctx context.Context, arg EditMessageContentParams) (Message, error) {
	row := q.db.QueryRowContext(ctx, editMessageContent, arg.Content, arg.ID)
	var i Message
	err := row.Scan(
		&i.ID,
		&i.ChannelID,
		&i.UserID,
		&i.Content,
		&i.ReplyTo,
		&i.EditedAt,
		&i.Deleted,
		&i.Pinned,
		&i.Timestamp,
		&i.MentionsEveryone,
	)
	return i, err
}

const getChannelUnreadCounts = `-- name: GetChannelUnreadCounts :many
SELECT c.id,
       (SELECT COALESCE(MAX(m.id), 0) FROM messages m
         WHERE m.channel_id = c.id AND m.deleted = 0) AS last_msg_id,
       (SELECT COUNT(*) FROM messages m
         WHERE m.channel_id = c.id AND m.deleted = 0
           AND m.id > COALESCE((SELECT rs.last_message_id FROM read_states rs
                                 WHERE rs.channel_id = c.id AND rs.user_id = ?), 0)) AS unread,
       COALESCE((SELECT rs.mention_count FROM read_states rs
                  WHERE rs.channel_id = c.id AND rs.user_id = ?), 0) AS mentions
FROM channels c
WHERE c.type IN ('text', 'announcement')
   OR (c.type = 'dm' AND EXISTS (SELECT 1 FROM dm_participants dp
                                  WHERE dp.channel_id = c.id AND dp.user_id = ?))
`

type GetChannelUnreadCountsParams struct {
	UserID   int64 `json:"userId"`
	UserID_2 int64 `json:"userId2"`
	UserID_3 int64 `json:"userId3"`
}

type GetChannelUnreadCountsRow struct {
	ID        int64       `json:"id"`
	LastMsgID interface{} `json:"lastMsgId"`
	Unread    int64       `json:"unread"`
	Mentions  interface{} `json:"mentions"`
}

func (q *Queries) GetChannelUnreadCounts(ctx context.Context, arg GetChannelUnreadCountsParams) ([]GetChannelUnreadCountsRow, error) {
	rows, err := q.db.QueryContext(ctx, getChannelUnreadCounts, arg.UserID, arg.UserID_2, arg.UserID_3)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []GetChannelUnreadCountsRow{}
	for rows.Next() {
		var i GetChannelUnreadCountsRow
		if err := rows.Scan(
			&i.ID,
			&i.LastMsgID,
			&i.Unread,
			&i.Mentions,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Close(); err != nil {
		return nil, err
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getLatestMessageID = `-- name: GetLatestMessageID :one
SELECT COALESCE(MAX(id), 0) FROM messages WHERE channel_id = ? AND deleted = 0
`

func (q *Queries) GetLatestMessageID(ctx context.Context, channelID int64) (interface{}, error) {
	row := q.db.QueryRowContext(ctx, getLatestMessageID, channelID)
	var coalesce interface{}
	err := row.Scan(&coalesce)
	return coalesce, err
}

const getMessage = `-- name: GetMessage :one
SELECT id, channel_id, user_id, content, reply_to, edited_at, deleted, pinned, timestamp,
       mentions_everyone
FROM messages WHERE id = ?
`

func (q *Queries) GetMessage(ctx context.Context, id int64) (Message, error) {
	row := q.db.QueryRowContext(ctx, getMessage, id)
	var i Message
	err := row.Scan(
		&i.ID,
		&i.ChannelID,
		&i.UserID,
		&i.Content,
		&i.ReplyTo,
		&i.EditedAt,
		&i.Deleted,
		&i.Pinned,
		&i.Timestamp,
		&i.MentionsEveryone,
	)
	return i, err
}

const getMessagesForAPI = `-- name: GetMessagesForAPI :many
SELECT m.id, m.channel_id, m.user_id, u.username, u.avatar,
       m.content, m.reply_to, m.edited_at, m.deleted, m.pinned, m.timestamp
FROM messages m JOIN users u ON m.user_id = u.id
WHERE m.channel_id = ? AND m.deleted = 0
ORDER BY m.id DESC LIMIT ?
`

type GetMessagesForAPIParams struct {
	ChannelID int64 `json:"channelId"`
	Limit     int64 `json:"limit"`
}

type GetMessagesForAPIRow struct {
	ID        int64   `json:"id"`
	ChannelID int64   `json:"channelId"`
	UserID    int64   `json:"userId"`
	Username  string  `json:"username"`
	Avatar    *string `json:"avatar"`
	Content   string  `json:"content"`
	ReplyTo   *int64  `json:"replyTo"`
	EditedAt  *string `json:"editedAt"`
	Deleted   int64   `json:"deleted"`
	Pinned    int64   `json:"pinned"`
	Timestamp string  `json:"timestamp"`
}

func (q *Queries) GetMessagesForAPI(ctx context.Context, arg GetMessagesForAPIParams) ([]GetMessagesForAPIRow, error) {
	rows, err := q.db.QueryContext(ctx, getMessagesForAPI, arg.ChannelID, arg.Limit)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []GetMessagesForAPIRow{}
	for rows.Next() {
		var i GetMessagesForAPIRow
		if err := rows.Scan(
			&i.ID,
			&i.ChannelID,
			&i.UserID,
			&i.Username,
			&i.Avatar,
			&i.Content,
			&i.ReplyTo,
			&i.EditedAt,
			&i.Deleted,
			&i.Pinned,
			&i.Timestamp,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Close(); err != nil {
		return nil, err
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const setMessagePinned = `-- name: SetMessagePinned :execresult
UPDATE messages SET pinned = ? WHERE id = ? AND deleted = 0
`

type SetMessagePinnedParams struct {
	Pinned int64 `json:"pinned"`
	ID     int64 `json:"id"`
}

func (q *Queries) SetMessagePinned(ctx context.Context, arg SetMessagePinnedParams) (sql.Result, error) {
	return q.db.ExecContext(ctx, setMessagePinned, arg.Pinned, arg.ID)
}

const softDeleteMessage = `-- name: SoftDeleteMessage :exec
UPDATE messages SET deleted = 1 WHERE id = ?
`

func (q *Queries) SoftDeleteMessage(ctx context.Context, id int64) error {
	_, err := q.db.ExecContext(ctx, softDeleteMessage, id)
	return err
}

const updateReadState = `-- name: UpdateReadState :exec
INSERT INTO read_states (user_id, channel_id, last_message_id, mention_count)
VALUES (?, ?, ?, 0)
ON CONFLICT(user_id, channel_id) DO UPDATE SET
    last_message_id = excluded.last_message_id,
    mention_count = 0
`

type UpdateReadStateParams struct {
	UserID        int64 `json:"userId"`
	ChannelID     int64 `json:"channelId"`
	LastMessageID int64 `json:"lastMessageId"`
}

// Marking a channel read also clears its mention badge: channel_focus is the
// only caller, and a focused channel has no outstanding mentions by definition.
func (q *Queries) UpdateReadState(ctx context.Context, arg UpdateReadStateParams) error {
	_, err := q.db.ExecContext(ctx, updateReadState, arg.UserID, arg.ChannelID, arg.LastMessageID)
	return err
}
