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

package dbgen

import (
	"context"
)

const closeDM = `-- name: CloseDM :exec
DELETE FROM dm_open_state WHERE user_id = ? AND channel_id = ?
`

type CloseDMParams struct {
	UserID    int64 `json:"userId"`
	ChannelID int64 `json:"channelId"`
}

func (q *Queries) CloseDM(ctx context.Context, arg CloseDMParams) error {
	_, err := q.db.ExecContext(ctx, closeDM, arg.UserID, arg.ChannelID)
	return err
}

const countDMParticipants = `-- name: CountDMParticipants :one
SELECT COUNT(*) FROM dm_participants WHERE channel_id = ?
`

func (q *Queries) CountDMParticipants(ctx context.Context, channelID int64) (int64, error) {
	row := q.db.QueryRowContext(ctx, countDMParticipants, channelID)
	var count int64
	err := row.Scan(&count)
	return count, err
}

const getDMParticipantIDs = `-- name: GetDMParticipantIDs :many
SELECT user_id FROM dm_participants WHERE channel_id = ?
`

func (q *Queries) GetDMParticipantIDs(ctx context.Context, channelID int64) ([]int64, error) {
	rows, err := q.db.QueryContext(ctx, getDMParticipantIDs, channelID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []int64{}
	for rows.Next() {
		var user_id int64
		if err := rows.Scan(&user_id); err != nil {
			return nil, err
		}
		items = append(items, user_id)
	}
	if err := rows.Close(); err != nil {
		return nil, err
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getDMParticipants = `-- name: GetDMParticipants :many
SELECT
    u.id                                      AS id,
    u.username                                AS username,
    COALESCE(u.display_name, '')              AS display_name,
    COALESCE(u.avatar, '')                    AS avatar,
    u.status                                  AS status
FROM dm_participants dp
JOIN users u ON u.id = dp.user_id
WHERE dp.channel_id = ?
ORDER BY u.id ASC
`

type GetDMParticipantsRow struct {
	ID          int64  `json:"id"`
	Username    string `json:"username"`
	DisplayName string `json:"displayName"`
	Avatar      string `json:"avatar"`
	Status      string `json:"status"`
}

func (q *Queries) GetDMParticipants(ctx context.Context, channelID int64) ([]GetDMParticipantsRow, error) {
	rows, err := q.db.QueryContext(ctx, getDMParticipants, channelID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []GetDMParticipantsRow{}
	for rows.Next() {
		var i GetDMParticipantsRow
		if err := rows.Scan(
			&i.ID,
			&i.Username,
			&i.DisplayName,
			&i.Avatar,
			&i.Status,
		); 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 getDMParticipantsForUser = `-- name: GetDMParticipantsForUser :many
SELECT
    dp.channel_id                                 AS channel_id,
    u.id                                          AS id,
    u.username                                    AS username,
    COALESCE(u.display_name, '')                  AS display_name,
    COALESCE(u.avatar, '')                        AS avatar,
    u.status                                      AS status
FROM dm_open_state dos
JOIN dm_participants dp ON dp.channel_id = dos.channel_id
JOIN users u            ON u.id = dp.user_id
WHERE dos.user_id = ?
ORDER BY dp.channel_id ASC, u.id ASC
`

type GetDMParticipantsForUserRow struct {
	ChannelID   int64  `json:"channelId"`
	ID          int64  `json:"id"`
	Username    string `json:"username"`
	DisplayName string `json:"displayName"`
	Avatar      string `json:"avatar"`
	Status      string `json:"status"`
}

// Every participant of every DM the user has open, in one pass. Includes the
// user themselves so a caller can tell "group of three" from "group of three
// others"; the Go layer filters when it needs the others.
func (q *Queries) GetDMParticipantsForUser(ctx context.Context, userID int64) ([]GetDMParticipantsForUserRow, error) {
	rows, err := q.db.QueryContext(ctx, getDMParticipantsForUser, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []GetDMParticipantsForUserRow{}
	for rows.Next() {
		var i GetDMParticipantsForUserRow
		if err := rows.Scan(
			&i.ChannelID,
			&i.ID,
			&i.Username,
			&i.DisplayName,
			&i.Avatar,
			&i.Status,
		); 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 getUserDMChannelIDs = `-- name: GetUserDMChannelIDs :many
SELECT channel_id FROM dm_open_state WHERE user_id = ?
`

func (q *Queries) GetUserDMChannelIDs(ctx context.Context, userID int64) ([]int64, error) {
	rows, err := q.db.QueryContext(ctx, getUserDMChannelIDs, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []int64{}
	for rows.Next() {
		var channel_id int64
		if err := rows.Scan(&channel_id); err != nil {
			return nil, err
		}
		items = append(items, channel_id)
	}
	if err := rows.Close(); err != nil {
		return nil, err
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getUserDMChannels = `-- name: GetUserDMChannels :many
SELECT
    c.id                                          AS channel_id,
    c.name                                        AS name,
    c.is_group                                    AS is_group,
    lm.id                                         AS last_message_id,
    COALESCE(lm.content, '')                      AS last_message,
    COALESCE(lm.timestamp, '')                    AS last_message_at,
    (SELECT COUNT(*) FROM messages mu
      WHERE mu.channel_id = c.id AND mu.deleted = 0
        AND mu.id > COALESCE((SELECT rs.last_message_id FROM read_states rs
                               WHERE rs.channel_id = c.id AND rs.user_id = dos.user_id), 0)
    ) AS unread_count
FROM dm_open_state dos
JOIN channels c          ON c.id = dos.channel_id AND c.type = 'dm'
LEFT JOIN messages lm    ON lm.id = (
    SELECT MAX(id) FROM messages WHERE channel_id = c.id AND deleted = 0
)
WHERE dos.user_id = ?
ORDER BY COALESCE(lm.timestamp, dos.opened_at) DESC
`

type GetUserDMChannelsRow struct {
	ChannelID     int64  `json:"channelId"`
	Name          string `json:"name"`
	IsGroup       int64  `json:"isGroup"`
	LastMessageID *int64 `json:"lastMessageId"`
	LastMessage   string `json:"lastMessage"`
	LastMessageAt string `json:"lastMessageAt"`
	UnreadCount   int64  `json:"unreadCount"`
}

// A DM row carries no recipient any more: dm_participants holds N users, so
// "the other one" is only well defined for a two-person DM. The participant
// set comes from GetDMParticipantsForUser below, one extra query for the whole
// list rather than one per channel, and the Go layer stitches them together.
func (q *Queries) GetUserDMChannels(ctx context.Context, userID int64) ([]GetUserDMChannelsRow, error) {
	rows, err := q.db.QueryContext(ctx, getUserDMChannels, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []GetUserDMChannelsRow{}
	for rows.Next() {
		var i GetUserDMChannelsRow
		if err := rows.Scan(
			&i.ChannelID,
			&i.Name,
			&i.IsGroup,
			&i.LastMessageID,
			&i.LastMessage,
			&i.LastMessageAt,
			&i.UnreadCount,
		); 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 isDMParticipant = `-- name: IsDMParticipant :one
SELECT user_id FROM dm_participants WHERE user_id = ? AND channel_id = ?
`

type IsDMParticipantParams struct {
	UserID    int64 `json:"userId"`
	ChannelID int64 `json:"channelId"`
}

func (q *Queries) IsDMParticipant(ctx context.Context, arg IsDMParticipantParams) (int64, error) {
	row := q.db.QueryRowContext(ctx, isDMParticipant, arg.UserID, arg.ChannelID)
	var user_id int64
	err := row.Scan(&user_id)
	return user_id, err
}

const isGroupDM = `-- name: IsGroupDM :one
SELECT is_group FROM channels WHERE id = ? AND type = 'dm'
`

func (q *Queries) IsGroupDM(ctx context.Context, id int64) (int64, error) {
	row := q.db.QueryRowContext(ctx, isGroupDM, id)
	var is_group int64
	err := row.Scan(&is_group)
	return is_group, err
}

const openDM = `-- name: OpenDM :exec
INSERT OR IGNORE INTO dm_open_state (user_id, channel_id) VALUES (?, ?)
`

type OpenDMParams struct {
	UserID    int64 `json:"userId"`
	ChannelID int64 `json:"channelId"`
}

func (q *Queries) OpenDM(ctx context.Context, arg OpenDMParams) error {
	_, err := q.db.ExecContext(ctx, openDM, arg.UserID, arg.ChannelID)
	return err
}

const removeDMParticipant = `-- name: RemoveDMParticipant :exec
DELETE FROM dm_participants WHERE channel_id = ? AND user_id = ?
`

type RemoveDMParticipantParams struct {
	ChannelID int64 `json:"channelId"`
	UserID    int64 `json:"userId"`
}

func (q *Queries) RemoveDMParticipant(ctx context.Context, arg RemoveDMParticipantParams) error {
	_, err := q.db.ExecContext(ctx, removeDMParticipant, arg.ChannelID, arg.UserID)
	return err
}

const setDMChannelName = `-- name: SetDMChannelName :exec
UPDATE channels SET name = ? WHERE id = ? AND type = 'dm'
`

type SetDMChannelNameParams struct {
	Name string `json:"name"`
	ID   int64  `json:"id"`
}

func (q *Queries) SetDMChannelName(ctx context.Context, arg SetDMChannelNameParams) error {
	_, err := q.db.ExecContext(ctx, setDMChannelName, arg.Name, arg.ID)
	return err
}
