// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.27.0
// source: users.sql

package db

import (
	"context"

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

const bumpEmailVerificationAttempts = `-- name: BumpEmailVerificationAttempts :exec
UPDATE email_verification_codes
SET attempts = attempts + 1, updated_at = now()
WHERE email = $1 AND purpose = $2
`

type BumpEmailVerificationAttemptsParams struct {
	Email   string `json:"email"`
	Purpose string `json:"purpose"`
}

func (q *Queries) BumpEmailVerificationAttempts(ctx context.Context, arg BumpEmailVerificationAttemptsParams) error {
	_, err := q.db.Exec(ctx, bumpEmailVerificationAttempts, arg.Email, arg.Purpose)
	return err
}

const countActiveAdmins = `-- name: CountActiveAdmins :one
SELECT count(*) FROM users WHERE role = 'admin' AND is_active = true
`

func (q *Queries) CountActiveAdmins(ctx context.Context) (int64, error) {
	row := q.db.QueryRow(ctx, countActiveAdmins)
	var count int64
	err := row.Scan(&count)
	return count, err
}

const countUsers = `-- name: CountUsers :one
SELECT count(*) FROM users
WHERE ($1::text = '' OR name ILIKE '%' || $1::text || '%' OR email ILIKE '%' || $1::text || '%')
  AND ($2::text = '' OR role::text = $2::text)
`

type CountUsersParams struct {
	Column1 string `json:"column_1"`
	Column2 string `json:"column_2"`
}

func (q *Queries) CountUsers(ctx context.Context, arg CountUsersParams) (int64, error) {
	row := q.db.QueryRow(ctx, countUsers, arg.Column1, arg.Column2)
	var count int64
	err := row.Scan(&count)
	return count, err
}

const countUsersInStores = `-- name: CountUsersInStores :one
SELECT count(*)
FROM users u
WHERE EXISTS (SELECT 1 FROM store_users su WHERE su.user_id = u.id AND su.store_id = ANY($1::bigint[]))
  AND (cardinality($3::text[]) = 0 OR u.role::text = ANY($3::text[]) OR u.id = $4)
  AND ($2::text = '' OR u.name ILIKE '%' || $2::text || '%' OR u.email ILIKE '%' || $2::text || '%')
`

type CountUsersInStoresParams struct {
	Column1 []int64  `json:"column_1"`
	Column2 string   `json:"column_2"`
	Column3 []string `json:"column_3"`
	ID      int64    `json:"id"`
}

func (q *Queries) CountUsersInStores(ctx context.Context, arg CountUsersInStoresParams) (int64, error) {
	row := q.db.QueryRow(ctx, countUsersInStores,
		arg.Column1,
		arg.Column2,
		arg.Column3,
		arg.ID,
	)
	var count int64
	err := row.Scan(&count)
	return count, err
}

const createEcommerceUser = `-- name: CreateEcommerceUser :one
INSERT INTO users (name, email, password, role, permissions, is_active, application_access, created_at, updated_at)
VALUES ($1, $2, $3, 'buyer', NULL, true, 'ecommerce', now(), now())
RETURNING id, name, email, email_verified_at, password, role, permissions,
       is_active, last_login_at, avatar, created_at, updated_at
`

type CreateEcommerceUserParams struct {
	Name     string `json:"name"`
	Email    string `json:"email"`
	Password string `json:"password"`
}

type CreateEcommerceUserRow struct {
	ID              int64              `json:"id"`
	Name            string             `json:"name"`
	Email           string             `json:"email"`
	EmailVerifiedAt pgtype.Timestamptz `json:"email_verified_at"`
	Password        string             `json:"password"`
	Role            string             `json:"role"`
	Permissions     []byte             `json:"permissions"`
	IsActive        bool               `json:"is_active"`
	LastLoginAt     pgtype.Timestamptz `json:"last_login_at"`
	Avatar          pgtype.Text        `json:"avatar"`
	CreatedAt       pgtype.Timestamptz `json:"created_at"`
	UpdatedAt       pgtype.Timestamptz `json:"updated_at"`
}

// Self-service storefront signup: always a buyer scoped to the e-commerce app,
// active immediately (no approval queue yet).
func (q *Queries) CreateEcommerceUser(ctx context.Context, arg CreateEcommerceUserParams) (CreateEcommerceUserRow, error) {
	row := q.db.QueryRow(ctx, createEcommerceUser, arg.Name, arg.Email, arg.Password)
	var i CreateEcommerceUserRow
	err := row.Scan(
		&i.ID,
		&i.Name,
		&i.Email,
		&i.EmailVerifiedAt,
		&i.Password,
		&i.Role,
		&i.Permissions,
		&i.IsActive,
		&i.LastLoginAt,
		&i.Avatar,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const createUser = `-- name: CreateUser :one
INSERT INTO users (name, email, password, role, permissions, is_active, email_verified_at, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, now(), now(), now())
RETURNING id, name, email, email_verified_at, password, role, permissions,
       is_active, last_login_at, avatar, created_at, updated_at
`

type CreateUserParams struct {
	Name        string `json:"name"`
	Email       string `json:"email"`
	Password    string `json:"password"`
	Role        string `json:"role"`
	Permissions []byte `json:"permissions"`
	IsActive    bool   `json:"is_active"`
}

type CreateUserRow struct {
	ID              int64              `json:"id"`
	Name            string             `json:"name"`
	Email           string             `json:"email"`
	EmailVerifiedAt pgtype.Timestamptz `json:"email_verified_at"`
	Password        string             `json:"password"`
	Role            string             `json:"role"`
	Permissions     []byte             `json:"permissions"`
	IsActive        bool               `json:"is_active"`
	LastLoginAt     pgtype.Timestamptz `json:"last_login_at"`
	Avatar          pgtype.Text        `json:"avatar"`
	CreatedAt       pgtype.Timestamptz `json:"created_at"`
	UpdatedAt       pgtype.Timestamptz `json:"updated_at"`
}

func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (CreateUserRow, error) {
	row := q.db.QueryRow(ctx, createUser,
		arg.Name,
		arg.Email,
		arg.Password,
		arg.Role,
		arg.Permissions,
		arg.IsActive,
	)
	var i CreateUserRow
	err := row.Scan(
		&i.ID,
		&i.Name,
		&i.Email,
		&i.EmailVerifiedAt,
		&i.Password,
		&i.Role,
		&i.Permissions,
		&i.IsActive,
		&i.LastLoginAt,
		&i.Avatar,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const deleteEmailVerificationCode = `-- name: DeleteEmailVerificationCode :exec
DELETE FROM email_verification_codes
WHERE email = $1 AND purpose = $2
`

type DeleteEmailVerificationCodeParams struct {
	Email   string `json:"email"`
	Purpose string `json:"purpose"`
}

func (q *Queries) DeleteEmailVerificationCode(ctx context.Context, arg DeleteEmailVerificationCodeParams) error {
	_, err := q.db.Exec(ctx, deleteEmailVerificationCode, arg.Email, arg.Purpose)
	return err
}

const deletePasswordResetToken = `-- name: DeletePasswordResetToken :exec
DELETE FROM password_reset_tokens WHERE email = $1
`

func (q *Queries) DeletePasswordResetToken(ctx context.Context, email string) error {
	_, err := q.db.Exec(ctx, deletePasswordResetToken, email)
	return err
}

const deleteToken = `-- name: DeleteToken :execrows
DELETE FROM personal_access_tokens WHERE id = $1
`

// :execrows, not :exec: single-token sibling of DeleteTokensByUser, so a
// revocation that matched no row is visible. internal/auth/repository.go
// DeleteToken warns on a zero count (a repeat logout legitimately deletes 0).
func (q *Queries) DeleteToken(ctx context.Context, id int64) (int64, error) {
	result, err := q.db.Exec(ctx, deleteToken, id)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const deleteTokensByUser = `-- name: DeleteTokensByUser :execrows
DELETE FROM personal_access_tokens WHERE tokenable_type = 'App\Models\User' AND tokenable_id = $1
`

func (q *Queries) DeleteTokensByUser(ctx context.Context, tokenableID int64) (int64, error) {
	result, err := q.db.Exec(ctx, deleteTokensByUser, tokenableID)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const deleteUser = `-- name: DeleteUser :execrows
DELETE FROM users WHERE id = $1
`

func (q *Queries) DeleteUser(ctx context.Context, id int64) (int64, error) {
	result, err := q.db.Exec(ctx, deleteUser, id)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const getApplicationAccess = `-- name: GetApplicationAccess :one
SELECT application_access FROM users WHERE id = $1
`

// LIVE-AUTHZ AUDIT 2026-08-26: read the materialized application axis
// (migration 000037). 'pos' cannot be expressed by DeriveApplicationAccess,
// which maps every internal role to 'erp'; the repository honors this stored
// value as an operator-assigned override.
func (q *Queries) GetApplicationAccess(ctx context.Context, id int64) (string, error) {
	row := q.db.QueryRow(ctx, getApplicationAccess, id)
	var application_access string
	err := row.Scan(&application_access)
	return application_access, err
}

const getEmailVerificationCode = `-- name: GetEmailVerificationCode :one
SELECT email, purpose, code_hash, attempts, expires_at
FROM email_verification_codes
WHERE email = $1 AND purpose = $2
`

type GetEmailVerificationCodeParams struct {
	Email   string `json:"email"`
	Purpose string `json:"purpose"`
}

type GetEmailVerificationCodeRow struct {
	Email     string             `json:"email"`
	Purpose   string             `json:"purpose"`
	CodeHash  string             `json:"code_hash"`
	Attempts  int32              `json:"attempts"`
	ExpiresAt pgtype.Timestamptz `json:"expires_at"`
}

func (q *Queries) GetEmailVerificationCode(ctx context.Context, arg GetEmailVerificationCodeParams) (GetEmailVerificationCodeRow, error) {
	row := q.db.QueryRow(ctx, getEmailVerificationCode, arg.Email, arg.Purpose)
	var i GetEmailVerificationCodeRow
	err := row.Scan(
		&i.Email,
		&i.Purpose,
		&i.CodeHash,
		&i.Attempts,
		&i.ExpiresAt,
	)
	return i, err
}

const getPasswordResetToken = `-- name: GetPasswordResetToken :one
SELECT email, token, created_at FROM password_reset_tokens
WHERE email = $1 AND created_at > now() - INTERVAL '1 hour'
`

func (q *Queries) GetPasswordResetToken(ctx context.Context, email string) (PasswordResetToken, error) {
	row := q.db.QueryRow(ctx, getPasswordResetToken, email)
	var i PasswordResetToken
	err := row.Scan(&i.Email, &i.Token, &i.CreatedAt)
	return i, err
}

const getSalesUserIDByEmployeeCode = `-- name: GetSalesUserIDByEmployeeCode :one
SELECT u.id FROM users u
JOIN employees e ON e.user_id = u.id
WHERE UPPER(e.employee_number) = UPPER($1)
  AND e.department = 'sales' AND e.is_active AND e.deleted_at IS NULL
  AND u.is_active
LIMIT 1
`

// Referral signup: resolve a public sales code (employees.employee_number)
// to the linked user id. Active sales staff with a user account only.
func (q *Queries) GetSalesUserIDByEmployeeCode(ctx context.Context, upper interface{}) (int64, error) {
	row := q.db.QueryRow(ctx, getSalesUserIDByEmployeeCode, upper)
	var id int64
	err := row.Scan(&id)
	return id, err
}

const getTokenByHash = `-- name: GetTokenByHash :one
SELECT id, tokenable_type, tokenable_id, name, token, abilities,
       last_used_at, expires_at, created_at
FROM personal_access_tokens
WHERE token = $1
`

type GetTokenByHashRow struct {
	ID            int64              `json:"id"`
	TokenableType string             `json:"tokenable_type"`
	TokenableID   int64              `json:"tokenable_id"`
	Name          string             `json:"name"`
	Token         string             `json:"token"`
	Abilities     pgtype.Text        `json:"abilities"`
	LastUsedAt    pgtype.Timestamptz `json:"last_used_at"`
	ExpiresAt     pgtype.Timestamptz `json:"expires_at"`
	CreatedAt     pgtype.Timestamptz `json:"created_at"`
}

func (q *Queries) GetTokenByHash(ctx context.Context, token string) (GetTokenByHashRow, error) {
	row := q.db.QueryRow(ctx, getTokenByHash, token)
	var i GetTokenByHashRow
	err := row.Scan(
		&i.ID,
		&i.TokenableType,
		&i.TokenableID,
		&i.Name,
		&i.Token,
		&i.Abilities,
		&i.LastUsedAt,
		&i.ExpiresAt,
		&i.CreatedAt,
	)
	return i, err
}

const getUserByEmail = `-- name: GetUserByEmail :one
SELECT id, name, email, email_verified_at, password, role, permissions,
       is_active, last_login_at, avatar, created_at, updated_at
FROM users
WHERE email = $1
`

type GetUserByEmailRow struct {
	ID              int64              `json:"id"`
	Name            string             `json:"name"`
	Email           string             `json:"email"`
	EmailVerifiedAt pgtype.Timestamptz `json:"email_verified_at"`
	Password        string             `json:"password"`
	Role            string             `json:"role"`
	Permissions     []byte             `json:"permissions"`
	IsActive        bool               `json:"is_active"`
	LastLoginAt     pgtype.Timestamptz `json:"last_login_at"`
	Avatar          pgtype.Text        `json:"avatar"`
	CreatedAt       pgtype.Timestamptz `json:"created_at"`
	UpdatedAt       pgtype.Timestamptz `json:"updated_at"`
}

func (q *Queries) GetUserByEmail(ctx context.Context, email string) (GetUserByEmailRow, error) {
	row := q.db.QueryRow(ctx, getUserByEmail, email)
	var i GetUserByEmailRow
	err := row.Scan(
		&i.ID,
		&i.Name,
		&i.Email,
		&i.EmailVerifiedAt,
		&i.Password,
		&i.Role,
		&i.Permissions,
		&i.IsActive,
		&i.LastLoginAt,
		&i.Avatar,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const getUserByID = `-- name: GetUserByID :one
SELECT id, name, email, email_verified_at, password, role, permissions,
       is_active, last_login_at, avatar, created_at, updated_at
FROM users
WHERE id = $1
`

type GetUserByIDRow struct {
	ID              int64              `json:"id"`
	Name            string             `json:"name"`
	Email           string             `json:"email"`
	EmailVerifiedAt pgtype.Timestamptz `json:"email_verified_at"`
	Password        string             `json:"password"`
	Role            string             `json:"role"`
	Permissions     []byte             `json:"permissions"`
	IsActive        bool               `json:"is_active"`
	LastLoginAt     pgtype.Timestamptz `json:"last_login_at"`
	Avatar          pgtype.Text        `json:"avatar"`
	CreatedAt       pgtype.Timestamptz `json:"created_at"`
	UpdatedAt       pgtype.Timestamptz `json:"updated_at"`
}

func (q *Queries) GetUserByID(ctx context.Context, id int64) (GetUserByIDRow, error) {
	row := q.db.QueryRow(ctx, getUserByID, id)
	var i GetUserByIDRow
	err := row.Scan(
		&i.ID,
		&i.Name,
		&i.Email,
		&i.EmailVerifiedAt,
		&i.Password,
		&i.Role,
		&i.Permissions,
		&i.IsActive,
		&i.LastLoginAt,
		&i.Avatar,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const insertToken = `-- name: InsertToken :one
INSERT INTO personal_access_tokens
    (tokenable_type, tokenable_id, name, token, abilities, expires_at)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id
`

type InsertTokenParams struct {
	TokenableType string             `json:"tokenable_type"`
	TokenableID   int64              `json:"tokenable_id"`
	Name          string             `json:"name"`
	Token         string             `json:"token"`
	Abilities     pgtype.Text        `json:"abilities"`
	ExpiresAt     pgtype.Timestamptz `json:"expires_at"`
}

func (q *Queries) InsertToken(ctx context.Context, arg InsertTokenParams) (int64, error) {
	row := q.db.QueryRow(ctx, insertToken,
		arg.TokenableType,
		arg.TokenableID,
		arg.Name,
		arg.Token,
		arg.Abilities,
		arg.ExpiresAt,
	)
	var id int64
	err := row.Scan(&id)
	return id, err
}

const listUsers = `-- name: ListUsers :many
SELECT id, name, email, email_verified_at, password, role, permissions,
       is_active, last_login_at, avatar, created_at, updated_at
FROM users
WHERE ($1::text = '' OR name ILIKE '%' || $1::text || '%' OR email ILIKE '%' || $1::text || '%')
  AND ($4::text = '' OR role::text = $4::text)
ORDER BY created_at DESC, id DESC
LIMIT $2 OFFSET $3
`

type ListUsersParams struct {
	Column1 string `json:"column_1"`
	Limit   int32  `json:"limit"`
	Offset  int32  `json:"offset"`
	Column4 string `json:"column_4"`
}

type ListUsersRow struct {
	ID              int64              `json:"id"`
	Name            string             `json:"name"`
	Email           string             `json:"email"`
	EmailVerifiedAt pgtype.Timestamptz `json:"email_verified_at"`
	Password        string             `json:"password"`
	Role            string             `json:"role"`
	Permissions     []byte             `json:"permissions"`
	IsActive        bool               `json:"is_active"`
	LastLoginAt     pgtype.Timestamptz `json:"last_login_at"`
	Avatar          pgtype.Text        `json:"avatar"`
	CreatedAt       pgtype.Timestamptz `json:"created_at"`
	UpdatedAt       pgtype.Timestamptz `json:"updated_at"`
}

func (q *Queries) ListUsers(ctx context.Context, arg ListUsersParams) ([]ListUsersRow, error) {
	rows, err := q.db.Query(ctx, listUsers,
		arg.Column1,
		arg.Limit,
		arg.Offset,
		arg.Column4,
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListUsersRow
	for rows.Next() {
		var i ListUsersRow
		if err := rows.Scan(
			&i.ID,
			&i.Name,
			&i.Email,
			&i.EmailVerifiedAt,
			&i.Password,
			&i.Role,
			&i.Permissions,
			&i.IsActive,
			&i.LastLoginAt,
			&i.Avatar,
			&i.CreatedAt,
			&i.UpdatedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listUsersInStores = `-- name: ListUsersInStores :many
SELECT u.id, u.name, u.email, u.email_verified_at, u.password, u.role, u.permissions,
       u.is_active, u.last_login_at, u.avatar, u.created_at, u.updated_at
FROM users u
WHERE EXISTS (SELECT 1 FROM store_users su WHERE su.user_id = u.id AND su.store_id = ANY($1::bigint[]))
  AND (cardinality($5::text[]) = 0 OR u.role::text = ANY($5::text[]) OR u.id = $6)
  AND ($2::text = '' OR u.name ILIKE '%' || $2::text || '%' OR u.email ILIKE '%' || $2::text || '%')
ORDER BY u.created_at DESC, u.id DESC
LIMIT $3 OFFSET $4
`

type ListUsersInStoresParams struct {
	Column1 []int64  `json:"column_1"`
	Column2 string   `json:"column_2"`
	Limit   int32    `json:"limit"`
	Offset  int32    `json:"offset"`
	Column5 []string `json:"column_5"`
	ID      int64    `json:"id"`
}

type ListUsersInStoresRow struct {
	ID              int64              `json:"id"`
	Name            string             `json:"name"`
	Email           string             `json:"email"`
	EmailVerifiedAt pgtype.Timestamptz `json:"email_verified_at"`
	Password        string             `json:"password"`
	Role            string             `json:"role"`
	Permissions     []byte             `json:"permissions"`
	IsActive        bool               `json:"is_active"`
	LastLoginAt     pgtype.Timestamptz `json:"last_login_at"`
	Avatar          pgtype.Text        `json:"avatar"`
	CreatedAt       pgtype.Timestamptz `json:"created_at"`
	UpdatedAt       pgtype.Timestamptz `json:"updated_at"`
}

// Users belonging to the given tenant store(s) (store_users), further limited to
// roles the caller may manage ($5) plus the caller themselves ($6). Used to
// scope the ERP user list for a kepala toko to the cashier accounts of their
// own outlet (never other managers or admins bound to the same store).
func (q *Queries) ListUsersInStores(ctx context.Context, arg ListUsersInStoresParams) ([]ListUsersInStoresRow, error) {
	rows, err := q.db.Query(ctx, listUsersInStores,
		arg.Column1,
		arg.Column2,
		arg.Limit,
		arg.Offset,
		arg.Column5,
		arg.ID,
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListUsersInStoresRow
	for rows.Next() {
		var i ListUsersInStoresRow
		if err := rows.Scan(
			&i.ID,
			&i.Name,
			&i.Email,
			&i.EmailVerifiedAt,
			&i.Password,
			&i.Role,
			&i.Permissions,
			&i.IsActive,
			&i.LastLoginAt,
			&i.Avatar,
			&i.CreatedAt,
			&i.UpdatedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const markEmailVerified = `-- name: MarkEmailVerified :exec
UPDATE users SET email_verified_at = now(), updated_at = now()
WHERE email = $1
`

func (q *Queries) MarkEmailVerified(ctx context.Context, email string) error {
	_, err := q.db.Exec(ctx, markEmailVerified, email)
	return err
}

const setUserActive = `-- name: SetUserActive :execrows
UPDATE users SET is_active = $2, updated_at = now() WHERE id = $1
`

type SetUserActiveParams struct {
	ID       int64 `json:"id"`
	IsActive bool  `json:"is_active"`
}

// :execrows, not :exec: the row count is the only proof a deactivation landed.
// internal/system/repository.go SetUserActive refuses to report a write that
// matched no user row.
func (q *Queries) SetUserActive(ctx context.Context, arg SetUserActiveParams) (int64, error) {
	result, err := q.db.Exec(ctx, setUserActive, arg.ID, arg.IsActive)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const setUserApplicationAccess = `-- name: SetUserApplicationAccess :execrows
UPDATE users SET application_access = $1 WHERE id = $2
`

type SetUserApplicationAccessParams struct {
	ApplicationAccess string `json:"application_access"`
	ID                int64  `json:"id"`
}

// Promotes the users.application_access write off a raw Exec onto the generated
// layer (:execrows so the row count survives). It must be checked, not merely
// issued: this column is the shell a user is allowed to enter, and
// internal/system/repository.go setApplicationAccess rolls the surrounding
// transaction back when it matches no row.
func (q *Queries) SetUserApplicationAccess(ctx context.Context, arg SetUserApplicationAccessParams) (int64, error) {
	result, err := q.db.Exec(ctx, setUserApplicationAccess, arg.ApplicationAccess, arg.ID)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const setUserPassword = `-- name: SetUserPassword :execrows
UPDATE users SET password = $2, updated_at = now() WHERE id = $1
`

type SetUserPasswordParams struct {
	ID       int64  `json:"id"`
	Password string `json:"password"`
}

// Admin password reset (000151): overwrites the hash directly. The caller
// (partners.Service.ResetCustomerPassword) is the authenticated authority —
// no current-password check — and MUST revoke the user's bearer tokens
// afterwards so an existing session cannot outlive the credential change.
func (q *Queries) SetUserPassword(ctx context.Context, arg SetUserPasswordParams) (int64, error) {
	result, err := q.db.Exec(ctx, setUserPassword, arg.ID, arg.Password)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const touchLastUsed = `-- name: TouchLastUsed :exec
UPDATE personal_access_tokens SET last_used_at = $1 WHERE id = $2
`

type TouchLastUsedParams struct {
	LastUsedAt pgtype.Timestamptz `json:"last_used_at"`
	ID         int64              `json:"id"`
}

func (q *Queries) TouchLastUsed(ctx context.Context, arg TouchLastUsedParams) error {
	_, err := q.db.Exec(ctx, touchLastUsed, arg.LastUsedAt, arg.ID)
	return err
}

const updateLastLogin = `-- name: UpdateLastLogin :exec
UPDATE users
SET last_login_at = $2
WHERE id = $1
  AND (last_login_at IS NULL OR last_login_at < $2::timestamptz - interval '1 hour')
`

type UpdateLastLoginParams struct {
	ID          int64              `json:"id"`
	LastLoginAt pgtype.Timestamptz `json:"last_login_at"`
}

func (q *Queries) UpdateLastLogin(ctx context.Context, arg UpdateLastLoginParams) error {
	_, err := q.db.Exec(ctx, updateLastLogin, arg.ID, arg.LastLoginAt)
	return err
}

const updateProfile = `-- name: UpdateProfile :execrows
UPDATE users
SET name = COALESCE($2::text, name),
    email = COALESCE($3::text, email),
    password = COALESCE($4::text, password),
    updated_at = now()
WHERE id = $1
`

type UpdateProfileParams struct {
	ID       int64       `json:"id"`
	Name     pgtype.Text `json:"name"`
	Email    pgtype.Text `json:"email"`
	Password pgtype.Text `json:"password"`
}

func (q *Queries) UpdateProfile(ctx context.Context, arg UpdateProfileParams) (int64, error) {
	result, err := q.db.Exec(ctx, updateProfile,
		arg.ID,
		arg.Name,
		arg.Email,
		arg.Password,
	)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const updateUser = `-- name: UpdateUser :one
UPDATE users
SET name = $2,
    email = $3,
    role = $4,
    permissions = COALESCE($5, permissions),
    is_active = COALESCE($6, is_active),
    password = COALESCE($7::text, password),
    updated_at = now()
WHERE id = $1
RETURNING id, name, email, email_verified_at, password, role, permissions,
       is_active, last_login_at, avatar, created_at, updated_at
`

type UpdateUserParams struct {
	ID          int64       `json:"id"`
	Name        string      `json:"name"`
	Email       string      `json:"email"`
	Role        string      `json:"role"`
	Permissions []byte      `json:"permissions"`
	IsActive    bool        `json:"is_active"`
	Password    pgtype.Text `json:"password"`
}

type UpdateUserRow struct {
	ID              int64              `json:"id"`
	Name            string             `json:"name"`
	Email           string             `json:"email"`
	EmailVerifiedAt pgtype.Timestamptz `json:"email_verified_at"`
	Password        string             `json:"password"`
	Role            string             `json:"role"`
	Permissions     []byte             `json:"permissions"`
	IsActive        bool               `json:"is_active"`
	LastLoginAt     pgtype.Timestamptz `json:"last_login_at"`
	Avatar          pgtype.Text        `json:"avatar"`
	CreatedAt       pgtype.Timestamptz `json:"created_at"`
	UpdatedAt       pgtype.Timestamptz `json:"updated_at"`
}

func (q *Queries) UpdateUser(ctx context.Context, arg UpdateUserParams) (UpdateUserRow, error) {
	row := q.db.QueryRow(ctx, updateUser,
		arg.ID,
		arg.Name,
		arg.Email,
		arg.Role,
		arg.Permissions,
		arg.IsActive,
		arg.Password,
	)
	var i UpdateUserRow
	err := row.Scan(
		&i.ID,
		&i.Name,
		&i.Email,
		&i.EmailVerifiedAt,
		&i.Password,
		&i.Role,
		&i.Permissions,
		&i.IsActive,
		&i.LastLoginAt,
		&i.Avatar,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const upsertEmailVerificationCode = `-- name: UpsertEmailVerificationCode :exec
INSERT INTO email_verification_codes (email, purpose, code_hash, attempts, expires_at)
VALUES ($1, $2, $3, 0, now() + INTERVAL '10 minutes')
ON CONFLICT (email, purpose) DO UPDATE
SET code_hash = EXCLUDED.code_hash,
    attempts = 0,
    expires_at = EXCLUDED.expires_at,
    updated_at = now()
`

type UpsertEmailVerificationCodeParams struct {
	Email    string `json:"email"`
	Purpose  string `json:"purpose"`
	CodeHash string `json:"code_hash"`
}

// Email verification (000152): a resend replaces the code and resets the
// attempt counter (one row per email+purpose, PK enforces it).
func (q *Queries) UpsertEmailVerificationCode(ctx context.Context, arg UpsertEmailVerificationCodeParams) error {
	_, err := q.db.Exec(ctx, upsertEmailVerificationCode, arg.Email, arg.Purpose, arg.CodeHash)
	return err
}

const upsertPasswordResetToken = `-- name: UpsertPasswordResetToken :exec
INSERT INTO password_reset_tokens (email, token, created_at)
VALUES ($1, $2, now())
ON CONFLICT (email) DO UPDATE SET token = EXCLUDED.token, created_at = now()
`

type UpsertPasswordResetTokenParams struct {
	Email string `json:"email"`
	Token string `json:"token"`
}

func (q *Queries) UpsertPasswordResetToken(ctx context.Context, arg UpsertPasswordResetTokenParams) error {
	_, err := q.db.Exec(ctx, upsertPasswordResetToken, arg.Email, arg.Token)
	return err
}

const userByResetToken = `-- name: UserByResetToken :one
SELECT u.id, u.name, u.email, u.email_verified_at, u.password, u.remember_token, u.role, u.application_access, u.permissions, u.is_active, u.last_login_at, u.avatar, u.created_at, u.updated_at FROM users u
JOIN password_reset_tokens t ON t.email = u.email
WHERE t.token = $1 AND t.created_at > now() - INTERVAL '1 hour'
LIMIT 1
`

func (q *Queries) UserByResetToken(ctx context.Context, token string) (User, error) {
	row := q.db.QueryRow(ctx, userByResetToken, token)
	var i User
	err := row.Scan(
		&i.ID,
		&i.Name,
		&i.Email,
		&i.EmailVerifiedAt,
		&i.Password,
		&i.RememberToken,
		&i.Role,
		&i.ApplicationAccess,
		&i.Permissions,
		&i.IsActive,
		&i.LastLoginAt,
		&i.Avatar,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const userInStores = `-- name: UserInStores :one
SELECT EXISTS (SELECT 1 FROM store_users WHERE user_id = $1 AND store_id = ANY($2::bigint[]))
`

type UserInStoresParams struct {
	UserID  int64   `json:"user_id"`
	Column2 []int64 `json:"column_2"`
}

func (q *Queries) UserInStores(ctx context.Context, arg UserInStoresParams) (bool, error) {
	row := q.db.QueryRow(ctx, userInStores, arg.UserID, arg.Column2)
	var exists bool
	err := row.Scan(&exists)
	return exists, err
}
