// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.31.1
// source: invitation.sql

package db

import (
	"context"

	"github.com/jackc/pgx/v5/pgtype"
)

const acceptInvitation = `-- name: AcceptInvitation :one
UPDATE workspace_invitation
SET status = 'accepted', updated_at = now()
WHERE id = $1 AND status = 'pending'
RETURNING id, workspace_id, inviter_id, invitee_email, invitee_user_id, role, status, created_at, updated_at, expires_at, invite_code
`

func (q *Queries) AcceptInvitation(ctx context.Context, id pgtype.UUID) (WorkspaceInvitation, error) {
	row := q.db.QueryRow(ctx, acceptInvitation, id)
	var i WorkspaceInvitation
	err := row.Scan(
		&i.ID,
		&i.WorkspaceID,
		&i.InviterID,
		&i.InviteeEmail,
		&i.InviteeUserID,
		&i.Role,
		&i.Status,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.ExpiresAt,
		&i.InviteCode,
	)
	return i, err
}

const createInvitation = `-- name: CreateInvitation :one
INSERT INTO workspace_invitation (workspace_id, inviter_id, invitee_email, invitee_user_id, role)
VALUES ($1, $2, $3, $4, $5)
RETURNING id, workspace_id, inviter_id, invitee_email, invitee_user_id, role, status, created_at, updated_at, expires_at, invite_code
`

type CreateInvitationParams struct {
	WorkspaceID   pgtype.UUID `json:"workspace_id"`
	InviterID     pgtype.UUID `json:"inviter_id"`
	InviteeEmail  string      `json:"invitee_email"`
	InviteeUserID pgtype.UUID `json:"invitee_user_id"`
	Role          string      `json:"role"`
}

func (q *Queries) CreateInvitation(ctx context.Context, arg CreateInvitationParams) (WorkspaceInvitation, error) {
	row := q.db.QueryRow(ctx, createInvitation,
		arg.WorkspaceID,
		arg.InviterID,
		arg.InviteeEmail,
		arg.InviteeUserID,
		arg.Role,
	)
	var i WorkspaceInvitation
	err := row.Scan(
		&i.ID,
		&i.WorkspaceID,
		&i.InviterID,
		&i.InviteeEmail,
		&i.InviteeUserID,
		&i.Role,
		&i.Status,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.ExpiresAt,
		&i.InviteCode,
	)
	return i, err
}

const declineInvitation = `-- name: DeclineInvitation :one
UPDATE workspace_invitation
SET status = 'declined', updated_at = now()
WHERE id = $1 AND status = 'pending'
RETURNING id, workspace_id, inviter_id, invitee_email, invitee_user_id, role, status, created_at, updated_at, expires_at, invite_code
`

func (q *Queries) DeclineInvitation(ctx context.Context, id pgtype.UUID) (WorkspaceInvitation, error) {
	row := q.db.QueryRow(ctx, declineInvitation, id)
	var i WorkspaceInvitation
	err := row.Scan(
		&i.ID,
		&i.WorkspaceID,
		&i.InviterID,
		&i.InviteeEmail,
		&i.InviteeUserID,
		&i.Role,
		&i.Status,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.ExpiresAt,
		&i.InviteCode,
	)
	return i, err
}

const expireStalePendingInvitations = `-- name: ExpireStalePendingInvitations :exec
UPDATE workspace_invitation
SET status = 'expired', updated_at = now()
WHERE workspace_id = $1
  AND invitee_email = $2
  AND status = 'pending'
  AND expires_at <= now()
`

type ExpireStalePendingInvitationsParams struct {
	WorkspaceID  pgtype.UUID `json:"workspace_id"`
	InviteeEmail string      `json:"invitee_email"`
}

// Mark any past-due pending invitations for (workspace_id, invitee_email) as expired,
// so the next CreateInvitation does not collide with the partial unique index
// idx_invitation_unique_pending (which is WHERE status = 'pending' and cannot
// itself reference now() in its predicate).
func (q *Queries) ExpireStalePendingInvitations(ctx context.Context, arg ExpireStalePendingInvitationsParams) error {
	_, err := q.db.Exec(ctx, expireStalePendingInvitations, arg.WorkspaceID, arg.InviteeEmail)
	return err
}

const getInvitation = `-- name: GetInvitation :one
SELECT id, workspace_id, inviter_id, invitee_email, invitee_user_id, role, status, created_at, updated_at, expires_at, invite_code FROM workspace_invitation
WHERE id = $1
`

func (q *Queries) GetInvitation(ctx context.Context, id pgtype.UUID) (WorkspaceInvitation, error) {
	row := q.db.QueryRow(ctx, getInvitation, id)
	var i WorkspaceInvitation
	err := row.Scan(
		&i.ID,
		&i.WorkspaceID,
		&i.InviterID,
		&i.InviteeEmail,
		&i.InviteeUserID,
		&i.Role,
		&i.Status,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.ExpiresAt,
		&i.InviteCode,
	)
	return i, err
}

const getPendingInvitationByEmail = `-- name: GetPendingInvitationByEmail :one
SELECT id, workspace_id, inviter_id, invitee_email, invitee_user_id, role, status, created_at, updated_at, expires_at, invite_code FROM workspace_invitation
WHERE workspace_id = $1 AND invitee_email = $2 AND status = 'pending' AND expires_at > now()
`

type GetPendingInvitationByEmailParams struct {
	WorkspaceID  pgtype.UUID `json:"workspace_id"`
	InviteeEmail string      `json:"invitee_email"`
}

func (q *Queries) GetPendingInvitationByEmail(ctx context.Context, arg GetPendingInvitationByEmailParams) (WorkspaceInvitation, error) {
	row := q.db.QueryRow(ctx, getPendingInvitationByEmail, arg.WorkspaceID, arg.InviteeEmail)
	var i WorkspaceInvitation
	err := row.Scan(
		&i.ID,
		&i.WorkspaceID,
		&i.InviterID,
		&i.InviteeEmail,
		&i.InviteeUserID,
		&i.Role,
		&i.Status,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.ExpiresAt,
		&i.InviteCode,
	)
	return i, err
}

const listPendingInvitationsByWorkspace = `-- name: ListPendingInvitationsByWorkspace :many
SELECT wi.id, wi.workspace_id, wi.inviter_id, wi.invitee_email, wi.invitee_user_id, wi.role, wi.status, wi.created_at, wi.updated_at, wi.expires_at, wi.invite_code,
       u.name  AS inviter_name,
       u.email AS inviter_email
FROM workspace_invitation wi
JOIN "user" u ON u.id = wi.inviter_id
WHERE wi.workspace_id = $1 AND wi.status = 'pending' AND wi.expires_at > now()
ORDER BY wi.created_at DESC
`

type ListPendingInvitationsByWorkspaceRow struct {
	ID            pgtype.UUID        `json:"id"`
	WorkspaceID   pgtype.UUID        `json:"workspace_id"`
	InviterID     pgtype.UUID        `json:"inviter_id"`
	InviteeEmail  string             `json:"invitee_email"`
	InviteeUserID pgtype.UUID        `json:"invitee_user_id"`
	Role          string             `json:"role"`
	Status        string             `json:"status"`
	CreatedAt     pgtype.Timestamptz `json:"created_at"`
	UpdatedAt     pgtype.Timestamptz `json:"updated_at"`
	ExpiresAt     pgtype.Timestamptz `json:"expires_at"`
	InviteCode    pgtype.Text        `json:"invite_code"`
	InviterName   string             `json:"inviter_name"`
	InviterEmail  string             `json:"inviter_email"`
}

func (q *Queries) ListPendingInvitationsByWorkspace(ctx context.Context, workspaceID pgtype.UUID) ([]ListPendingInvitationsByWorkspaceRow, error) {
	rows, err := q.db.Query(ctx, listPendingInvitationsByWorkspace, workspaceID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []ListPendingInvitationsByWorkspaceRow{}
	for rows.Next() {
		var i ListPendingInvitationsByWorkspaceRow
		if err := rows.Scan(
			&i.ID,
			&i.WorkspaceID,
			&i.InviterID,
			&i.InviteeEmail,
			&i.InviteeUserID,
			&i.Role,
			&i.Status,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.ExpiresAt,
			&i.InviteCode,
			&i.InviterName,
			&i.InviterEmail,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listPendingInvitationsForUser = `-- name: ListPendingInvitationsForUser :many
SELECT wi.id, wi.workspace_id, wi.inviter_id, wi.invitee_email, wi.invitee_user_id, wi.role, wi.status, wi.created_at, wi.updated_at, wi.expires_at, wi.invite_code,
       w.name AS workspace_name,
       u.name AS inviter_name,
       u.email AS inviter_email
FROM workspace_invitation wi
JOIN workspace w ON w.id = wi.workspace_id
JOIN "user" u ON u.id = wi.inviter_id
WHERE wi.status = 'pending'
  AND (wi.invitee_user_id = $1 OR wi.invitee_email = $2)
  AND wi.expires_at > now()
ORDER BY wi.created_at DESC
`

type ListPendingInvitationsForUserParams struct {
	InviteeUserID pgtype.UUID `json:"invitee_user_id"`
	InviteeEmail  string      `json:"invitee_email"`
}

type ListPendingInvitationsForUserRow struct {
	ID            pgtype.UUID        `json:"id"`
	WorkspaceID   pgtype.UUID        `json:"workspace_id"`
	InviterID     pgtype.UUID        `json:"inviter_id"`
	InviteeEmail  string             `json:"invitee_email"`
	InviteeUserID pgtype.UUID        `json:"invitee_user_id"`
	Role          string             `json:"role"`
	Status        string             `json:"status"`
	CreatedAt     pgtype.Timestamptz `json:"created_at"`
	UpdatedAt     pgtype.Timestamptz `json:"updated_at"`
	ExpiresAt     pgtype.Timestamptz `json:"expires_at"`
	InviteCode    pgtype.Text        `json:"invite_code"`
	WorkspaceName string             `json:"workspace_name"`
	InviterName   string             `json:"inviter_name"`
	InviterEmail  string             `json:"inviter_email"`
}

func (q *Queries) ListPendingInvitationsForUser(ctx context.Context, arg ListPendingInvitationsForUserParams) ([]ListPendingInvitationsForUserRow, error) {
	rows, err := q.db.Query(ctx, listPendingInvitationsForUser, arg.InviteeUserID, arg.InviteeEmail)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []ListPendingInvitationsForUserRow{}
	for rows.Next() {
		var i ListPendingInvitationsForUserRow
		if err := rows.Scan(
			&i.ID,
			&i.WorkspaceID,
			&i.InviterID,
			&i.InviteeEmail,
			&i.InviteeUserID,
			&i.Role,
			&i.Status,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.ExpiresAt,
			&i.InviteCode,
			&i.WorkspaceName,
			&i.InviterName,
			&i.InviterEmail,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const revokeInvitation = `-- name: RevokeInvitation :exec
DELETE FROM workspace_invitation
WHERE id = $1 AND status = 'pending'
`

func (q *Queries) RevokeInvitation(ctx context.Context, id pgtype.UUID) error {
	_, err := q.db.Exec(ctx, revokeInvitation, id)
	return err
}

const createInvitationWithCode = `-- name: CreateInvitationWithCode :one
INSERT INTO workspace_invitation (workspace_id, inviter_id, invitee_email, invitee_user_id, role, invite_code)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id, workspace_id, inviter_id, invitee_email, invitee_user_id, role, status, created_at, updated_at, expires_at, invite_code
`

type CreateInvitationWithCodeParams struct {
	WorkspaceID   pgtype.UUID `json:"workspace_id"`
	InviterID     pgtype.UUID `json:"inviter_id"`
	InviteeEmail  string      `json:"invitee_email"`
	InviteeUserID pgtype.UUID `json:"invitee_user_id"`
	Role          string      `json:"role"`
	InviteCode    pgtype.Text `json:"invite_code"`
}

func (q *Queries) CreateInvitationWithCode(ctx context.Context, arg CreateInvitationWithCodeParams) (WorkspaceInvitation, error) {
	row := q.db.QueryRow(ctx, createInvitationWithCode,
		arg.WorkspaceID,
		arg.InviterID,
		arg.InviteeEmail,
		arg.InviteeUserID,
		arg.Role,
		arg.InviteCode,
	)
	var i WorkspaceInvitation
	err := row.Scan(
		&i.ID,
		&i.WorkspaceID,
		&i.InviterID,
		&i.InviteeEmail,
		&i.InviteeUserID,
		&i.Role,
		&i.Status,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.ExpiresAt,
		&i.InviteCode,
	)
	return i, err
}

const getPendingInvitationByCode = `-- name: GetPendingInvitationByCode :one
SELECT id, workspace_id, inviter_id, invitee_email, invitee_user_id, role, status, created_at, updated_at, expires_at, invite_code FROM workspace_invitation
WHERE invite_code = $1 AND status = 'pending' AND expires_at > now()
`

func (q *Queries) GetPendingInvitationByCode(ctx context.Context, inviteCode string) (WorkspaceInvitation, error) {
	row := q.db.QueryRow(ctx, getPendingInvitationByCode, inviteCode)
	var i WorkspaceInvitation
	err := row.Scan(
		&i.ID,
		&i.WorkspaceID,
		&i.InviterID,
		&i.InviteeEmail,
		&i.InviteeUserID,
		&i.Role,
		&i.Status,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.ExpiresAt,
		&i.InviteCode,
	)
	return i, err
}
