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

package dbgen

import (
	"context"

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

const CheckPhoneEmailExist = `-- name: CheckPhoneEmailExist :one
SELECT
    EXISTS (
        SELECT 1 FROM users u1 WHERE u1.phone_number = $1
    ) AS phone_exists,
    EXISTS (
        SELECT 1 FROM users u2 WHERE u2.email = $2
    ) AS email_exists
`

type CheckPhoneEmailExistParams struct {
	PhoneNumber pgtype.Text `json:"phone_number"`
	Email       pgtype.Text `json:"email"`
}

type CheckPhoneEmailExistRow struct {
	PhoneExists bool `json:"phone_exists"`
	EmailExists bool `json:"email_exists"`
}

func (q *Queries) CheckPhoneEmailExist(ctx context.Context, arg CheckPhoneEmailExistParams) (CheckPhoneEmailExistRow, error) {
	row := q.db.QueryRow(ctx, CheckPhoneEmailExist, arg.PhoneNumber, arg.Email)
	var i CheckPhoneEmailExistRow
	err := row.Scan(&i.PhoneExists, &i.EmailExists)
	return i, err
}

const CreateGoogleUser = `-- name: CreateGoogleUser :one
INSERT INTO users (
    first_name,
    last_name,
    email,
    google_id,
    google_email_verified,
    role,
    status,
    email_verified,
    profile_picture_url
)
VALUES (
    $1, $2, $3, $4, $5, $6, $7, true, $8
)
RETURNING id, first_name, last_name, gender, birth_day, email, phone_number, role, password, education_level, country, region, knowledge_level, nick_name, occupation, learning_goal, language_goal, language_challange, favourite_topic, initial_assessment_completed, email_verified, phone_verified, status, last_login, profile_completed, profile_picture_url, preferred_language, created_at, updated_at, age_group, google_id, google_email_verified, profile_completion_percentage
`

type CreateGoogleUserParams struct {
	FirstName           pgtype.Text `json:"first_name"`
	LastName            pgtype.Text `json:"last_name"`
	Email               pgtype.Text `json:"email"`
	GoogleID            pgtype.Text `json:"google_id"`
	GoogleEmailVerified pgtype.Bool `json:"google_email_verified"`
	Role                string      `json:"role"`
	Status              string      `json:"status"`
	ProfilePictureUrl   pgtype.Text `json:"profile_picture_url"`
}

func (q *Queries) CreateGoogleUser(ctx context.Context, arg CreateGoogleUserParams) (User, error) {
	row := q.db.QueryRow(ctx, CreateGoogleUser,
		arg.FirstName,
		arg.LastName,
		arg.Email,
		arg.GoogleID,
		arg.GoogleEmailVerified,
		arg.Role,
		arg.Status,
		arg.ProfilePictureUrl,
	)
	var i User
	err := row.Scan(
		&i.ID,
		&i.FirstName,
		&i.LastName,
		&i.Gender,
		&i.BirthDay,
		&i.Email,
		&i.PhoneNumber,
		&i.Role,
		&i.Password,
		&i.EducationLevel,
		&i.Country,
		&i.Region,
		&i.KnowledgeLevel,
		&i.NickName,
		&i.Occupation,
		&i.LearningGoal,
		&i.LanguageGoal,
		&i.LanguageChallange,
		&i.FavouriteTopic,
		&i.InitialAssessmentCompleted,
		&i.EmailVerified,
		&i.PhoneVerified,
		&i.Status,
		&i.LastLogin,
		&i.ProfileCompleted,
		&i.ProfilePictureUrl,
		&i.PreferredLanguage,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.AgeGroup,
		&i.GoogleID,
		&i.GoogleEmailVerified,
		&i.ProfileCompletionPercentage,
	)
	return i, err
}

const CreateUser = `-- name: CreateUser :one
INSERT INTO users (
    first_name,
    last_name,
    gender,
    birth_day,
    email,
    phone_number,
    role,
    password,
    age_group,
    education_level,
    country,
    region,

    nick_name,
    occupation,
    learning_goal,
    language_goal,
    language_challange,
    favourite_topic,

    initial_assessment_completed,
    email_verified,
    phone_verified,
    status,
    profile_completed,
    profile_picture_url,
    preferred_language,
    updated_at
)
VALUES (
    $1,
    $2,
    $3,
    $4,
    $5,
    $6,
    $7,
    $8,
    $9,   -- age_group
    $10,
    $11,
    $12,

    $13,
    $14,
    $15,
    $16,
    $17,
    $18,

    $19,
    $20,
    $21,
    $22,
    $23,
    $24,
    $25,
    CURRENT_TIMESTAMP
)
RETURNING
    id,
    first_name,
    last_name,
    gender,
    birth_day,
    email,
    phone_number,
    role,
    age_group,
    education_level,
    country,
    region,

    nick_name,
    occupation,
    learning_goal,
    language_goal,
    language_challange,
    favourite_topic,

    initial_assessment_completed,
    email_verified,
    phone_verified,
    status,
    profile_completed,
    profile_picture_url,
    preferred_language,
    created_at,
    updated_at
`

type CreateUserParams struct {
	FirstName                  pgtype.Text `json:"first_name"`
	LastName                   pgtype.Text `json:"last_name"`
	Gender                     pgtype.Text `json:"gender"`
	BirthDay                   pgtype.Date `json:"birth_day"`
	Email                      pgtype.Text `json:"email"`
	PhoneNumber                pgtype.Text `json:"phone_number"`
	Role                       string      `json:"role"`
	Password                   []byte      `json:"password"`
	AgeGroup                   pgtype.Text `json:"age_group"`
	EducationLevel             pgtype.Text `json:"education_level"`
	Country                    pgtype.Text `json:"country"`
	Region                     pgtype.Text `json:"region"`
	NickName                   pgtype.Text `json:"nick_name"`
	Occupation                 pgtype.Text `json:"occupation"`
	LearningGoal               pgtype.Text `json:"learning_goal"`
	LanguageGoal               pgtype.Text `json:"language_goal"`
	LanguageChallange          pgtype.Text `json:"language_challange"`
	FavouriteTopic             pgtype.Text `json:"favourite_topic"`
	InitialAssessmentCompleted bool        `json:"initial_assessment_completed"`
	EmailVerified              bool        `json:"email_verified"`
	PhoneVerified              bool        `json:"phone_verified"`
	Status                     string      `json:"status"`
	ProfileCompleted           pgtype.Bool `json:"profile_completed"`
	ProfilePictureUrl          pgtype.Text `json:"profile_picture_url"`
	PreferredLanguage          pgtype.Text `json:"preferred_language"`
}

type CreateUserRow struct {
	ID                         int64              `json:"id"`
	FirstName                  pgtype.Text        `json:"first_name"`
	LastName                   pgtype.Text        `json:"last_name"`
	Gender                     pgtype.Text        `json:"gender"`
	BirthDay                   pgtype.Date        `json:"birth_day"`
	Email                      pgtype.Text        `json:"email"`
	PhoneNumber                pgtype.Text        `json:"phone_number"`
	Role                       string             `json:"role"`
	AgeGroup                   pgtype.Text        `json:"age_group"`
	EducationLevel             pgtype.Text        `json:"education_level"`
	Country                    pgtype.Text        `json:"country"`
	Region                     pgtype.Text        `json:"region"`
	NickName                   pgtype.Text        `json:"nick_name"`
	Occupation                 pgtype.Text        `json:"occupation"`
	LearningGoal               pgtype.Text        `json:"learning_goal"`
	LanguageGoal               pgtype.Text        `json:"language_goal"`
	LanguageChallange          pgtype.Text        `json:"language_challange"`
	FavouriteTopic             pgtype.Text        `json:"favourite_topic"`
	InitialAssessmentCompleted bool               `json:"initial_assessment_completed"`
	EmailVerified              bool               `json:"email_verified"`
	PhoneVerified              bool               `json:"phone_verified"`
	Status                     string             `json:"status"`
	ProfileCompleted           pgtype.Bool        `json:"profile_completed"`
	ProfilePictureUrl          pgtype.Text        `json:"profile_picture_url"`
	PreferredLanguage          pgtype.Text        `json:"preferred_language"`
	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.FirstName,
		arg.LastName,
		arg.Gender,
		arg.BirthDay,
		arg.Email,
		arg.PhoneNumber,
		arg.Role,
		arg.Password,
		arg.AgeGroup,
		arg.EducationLevel,
		arg.Country,
		arg.Region,
		arg.NickName,
		arg.Occupation,
		arg.LearningGoal,
		arg.LanguageGoal,
		arg.LanguageChallange,
		arg.FavouriteTopic,
		arg.InitialAssessmentCompleted,
		arg.EmailVerified,
		arg.PhoneVerified,
		arg.Status,
		arg.ProfileCompleted,
		arg.ProfilePictureUrl,
		arg.PreferredLanguage,
	)
	var i CreateUserRow
	err := row.Scan(
		&i.ID,
		&i.FirstName,
		&i.LastName,
		&i.Gender,
		&i.BirthDay,
		&i.Email,
		&i.PhoneNumber,
		&i.Role,
		&i.AgeGroup,
		&i.EducationLevel,
		&i.Country,
		&i.Region,
		&i.NickName,
		&i.Occupation,
		&i.LearningGoal,
		&i.LanguageGoal,
		&i.LanguageChallange,
		&i.FavouriteTopic,
		&i.InitialAssessmentCompleted,
		&i.EmailVerified,
		&i.PhoneVerified,
		&i.Status,
		&i.ProfileCompleted,
		&i.ProfilePictureUrl,
		&i.PreferredLanguage,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

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

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

const GetAllUsers = `-- name: GetAllUsers :many
SELECT
    COUNT(*) OVER () AS total_count,
    id,
    first_name,
    last_name,
    gender,
    birth_day,
    email,
    phone_number,
    role,
    age_group,
    education_level,
    country,
    region,
    knowledge_level,
    nick_name,
    occupation,
    learning_goal,
    language_goal,
    language_challange,
    favourite_topic,
    initial_assessment_completed,
    email_verified,
    phone_verified,
    status,
    last_login,
    profile_completed,
    profile_picture_url,
    preferred_language,
    created_at,
    updated_at
FROM users
LIMIT $2::INT
OFFSET $1::INT
`

type GetAllUsersParams struct {
	Offset pgtype.Int4 `json:"offset"`
	Limit  pgtype.Int4 `json:"limit"`
}

type GetAllUsersRow struct {
	TotalCount                 int64              `json:"total_count"`
	ID                         int64              `json:"id"`
	FirstName                  pgtype.Text        `json:"first_name"`
	LastName                   pgtype.Text        `json:"last_name"`
	Gender                     pgtype.Text        `json:"gender"`
	BirthDay                   pgtype.Date        `json:"birth_day"`
	Email                      pgtype.Text        `json:"email"`
	PhoneNumber                pgtype.Text        `json:"phone_number"`
	Role                       string             `json:"role"`
	AgeGroup                   pgtype.Text        `json:"age_group"`
	EducationLevel             pgtype.Text        `json:"education_level"`
	Country                    pgtype.Text        `json:"country"`
	Region                     pgtype.Text        `json:"region"`
	KnowledgeLevel             pgtype.Text        `json:"knowledge_level"`
	NickName                   pgtype.Text        `json:"nick_name"`
	Occupation                 pgtype.Text        `json:"occupation"`
	LearningGoal               pgtype.Text        `json:"learning_goal"`
	LanguageGoal               pgtype.Text        `json:"language_goal"`
	LanguageChallange          pgtype.Text        `json:"language_challange"`
	FavouriteTopic             pgtype.Text        `json:"favourite_topic"`
	InitialAssessmentCompleted bool               `json:"initial_assessment_completed"`
	EmailVerified              bool               `json:"email_verified"`
	PhoneVerified              bool               `json:"phone_verified"`
	Status                     string             `json:"status"`
	LastLogin                  pgtype.Timestamptz `json:"last_login"`
	ProfileCompleted           pgtype.Bool        `json:"profile_completed"`
	ProfilePictureUrl          pgtype.Text        `json:"profile_picture_url"`
	PreferredLanguage          pgtype.Text        `json:"preferred_language"`
	CreatedAt                  pgtype.Timestamptz `json:"created_at"`
	UpdatedAt                  pgtype.Timestamptz `json:"updated_at"`
}

func (q *Queries) GetAllUsers(ctx context.Context, arg GetAllUsersParams) ([]GetAllUsersRow, error) {
	rows, err := q.db.Query(ctx, GetAllUsers, arg.Offset, arg.Limit)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetAllUsersRow
	for rows.Next() {
		var i GetAllUsersRow
		if err := rows.Scan(
			&i.TotalCount,
			&i.ID,
			&i.FirstName,
			&i.LastName,
			&i.Gender,
			&i.BirthDay,
			&i.Email,
			&i.PhoneNumber,
			&i.Role,
			&i.AgeGroup,
			&i.EducationLevel,
			&i.Country,
			&i.Region,
			&i.KnowledgeLevel,
			&i.NickName,
			&i.Occupation,
			&i.LearningGoal,
			&i.LanguageGoal,
			&i.LanguageChallange,
			&i.FavouriteTopic,
			&i.InitialAssessmentCompleted,
			&i.EmailVerified,
			&i.PhoneVerified,
			&i.Status,
			&i.LastLogin,
			&i.ProfileCompleted,
			&i.ProfilePictureUrl,
			&i.PreferredLanguage,
			&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 GetProfileCompletionStatus = `-- name: GetProfileCompletionStatus :one
SELECT 
    profile_completed,
    profile_completion_percentage
FROM users
WHERE id = $1
LIMIT 1
`

type GetProfileCompletionStatusRow struct {
	ProfileCompleted            pgtype.Bool `json:"profile_completed"`
	ProfileCompletionPercentage int16       `json:"profile_completion_percentage"`
}

func (q *Queries) GetProfileCompletionStatus(ctx context.Context, id int64) (GetProfileCompletionStatusRow, error) {
	row := q.db.QueryRow(ctx, GetProfileCompletionStatus, id)
	var i GetProfileCompletionStatusRow
	err := row.Scan(&i.ProfileCompleted, &i.ProfileCompletionPercentage)
	return i, err
}

const GetTotalUsers = `-- name: GetTotalUsers :one
SELECT COUNT(*)
FROM users
WHERE (role = $1 OR $1 IS NULL)
`

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

const GetUserByEmailPhone = `-- name: GetUserByEmailPhone :one



SELECT
    id,
    first_name,
    last_name,
    gender,
    birth_day,
    email,
    phone_number,
    role,
    password,
    age_group,
    education_level,
    country,
    region,

    nick_name,
    occupation,
    learning_goal,
    language_goal,
    language_challange,
    favourite_topic,

    email_verified,
    phone_verified,
    status,
    profile_completed,
    last_login,
    profile_picture_url,
    preferred_language,
    created_at,
    updated_at
FROM users
WHERE (email = $1 AND $1 IS NOT NULL)
   OR (phone_number = $2 AND $2 IS NOT NULL)
LIMIT 1
`

type GetUserByEmailPhoneParams struct {
	Email       pgtype.Text `json:"email"`
	PhoneNumber pgtype.Text `json:"phone_number"`
}

type GetUserByEmailPhoneRow struct {
	ID                int64              `json:"id"`
	FirstName         pgtype.Text        `json:"first_name"`
	LastName          pgtype.Text        `json:"last_name"`
	Gender            pgtype.Text        `json:"gender"`
	BirthDay          pgtype.Date        `json:"birth_day"`
	Email             pgtype.Text        `json:"email"`
	PhoneNumber       pgtype.Text        `json:"phone_number"`
	Role              string             `json:"role"`
	Password          []byte             `json:"password"`
	AgeGroup          pgtype.Text        `json:"age_group"`
	EducationLevel    pgtype.Text        `json:"education_level"`
	Country           pgtype.Text        `json:"country"`
	Region            pgtype.Text        `json:"region"`
	NickName          pgtype.Text        `json:"nick_name"`
	Occupation        pgtype.Text        `json:"occupation"`
	LearningGoal      pgtype.Text        `json:"learning_goal"`
	LanguageGoal      pgtype.Text        `json:"language_goal"`
	LanguageChallange pgtype.Text        `json:"language_challange"`
	FavouriteTopic    pgtype.Text        `json:"favourite_topic"`
	EmailVerified     bool               `json:"email_verified"`
	PhoneVerified     bool               `json:"phone_verified"`
	Status            string             `json:"status"`
	ProfileCompleted  pgtype.Bool        `json:"profile_completed"`
	LastLogin         pgtype.Timestamptz `json:"last_login"`
	ProfilePictureUrl pgtype.Text        `json:"profile_picture_url"`
	PreferredLanguage pgtype.Text        `json:"preferred_language"`
	CreatedAt         pgtype.Timestamptz `json:"created_at"`
	UpdatedAt         pgtype.Timestamptz `json:"updated_at"`
}

// -- name: GetUserByUserName :one
// SELECT
//
//	id,
//	first_name,
//	last_name,
//	email,
//	phone_number,
//	role,
//	password,
//	age,
//	education_level,
//	country,
//	region,
//	nick_name,
//	occupation,
//	learning_goal,
//	language_goal,
//	language_challange,
//	favourite_topic,
//	email_verified,
//	phone_verified,
//	status,
//	profile_completed,
//	last_login,
//	profile_picture_url,
//	preferred_language,
//	created_at,
//	updated_at
//
// FROM users
// WHERE user_name = $1 AND $1 IS NOT NULL
// LIMIT 1;
func (q *Queries) GetUserByEmailPhone(ctx context.Context, arg GetUserByEmailPhoneParams) (GetUserByEmailPhoneRow, error) {
	row := q.db.QueryRow(ctx, GetUserByEmailPhone, arg.Email, arg.PhoneNumber)
	var i GetUserByEmailPhoneRow
	err := row.Scan(
		&i.ID,
		&i.FirstName,
		&i.LastName,
		&i.Gender,
		&i.BirthDay,
		&i.Email,
		&i.PhoneNumber,
		&i.Role,
		&i.Password,
		&i.AgeGroup,
		&i.EducationLevel,
		&i.Country,
		&i.Region,
		&i.NickName,
		&i.Occupation,
		&i.LearningGoal,
		&i.LanguageGoal,
		&i.LanguageChallange,
		&i.FavouriteTopic,
		&i.EmailVerified,
		&i.PhoneVerified,
		&i.Status,
		&i.ProfileCompleted,
		&i.LastLogin,
		&i.ProfilePictureUrl,
		&i.PreferredLanguage,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const GetUserByGoogleID = `-- name: GetUserByGoogleID :one
SELECT id, first_name, last_name, gender, birth_day, email, phone_number, role, password, education_level, country, region, knowledge_level, nick_name, occupation, learning_goal, language_goal, language_challange, favourite_topic, initial_assessment_completed, email_verified, phone_verified, status, last_login, profile_completed, profile_picture_url, preferred_language, created_at, updated_at, age_group, google_id, google_email_verified, profile_completion_percentage
FROM users
WHERE google_id = $1
`

func (q *Queries) GetUserByGoogleID(ctx context.Context, googleID pgtype.Text) (User, error) {
	row := q.db.QueryRow(ctx, GetUserByGoogleID, googleID)
	var i User
	err := row.Scan(
		&i.ID,
		&i.FirstName,
		&i.LastName,
		&i.Gender,
		&i.BirthDay,
		&i.Email,
		&i.PhoneNumber,
		&i.Role,
		&i.Password,
		&i.EducationLevel,
		&i.Country,
		&i.Region,
		&i.KnowledgeLevel,
		&i.NickName,
		&i.Occupation,
		&i.LearningGoal,
		&i.LanguageGoal,
		&i.LanguageChallange,
		&i.FavouriteTopic,
		&i.InitialAssessmentCompleted,
		&i.EmailVerified,
		&i.PhoneVerified,
		&i.Status,
		&i.LastLogin,
		&i.ProfileCompleted,
		&i.ProfilePictureUrl,
		&i.PreferredLanguage,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.AgeGroup,
		&i.GoogleID,
		&i.GoogleEmailVerified,
		&i.ProfileCompletionPercentage,
	)
	return i, err
}

const GetUserByID = `-- name: GetUserByID :one
SELECT id, first_name, last_name, gender, birth_day, email, phone_number, role, password, education_level, country, region, knowledge_level, nick_name, occupation, learning_goal, language_goal, language_challange, favourite_topic, initial_assessment_completed, email_verified, phone_verified, status, last_login, profile_completed, profile_picture_url, preferred_language, created_at, updated_at, age_group, google_id, google_email_verified, profile_completion_percentage
FROM users
WHERE id = $1
`

func (q *Queries) GetUserByID(ctx context.Context, id int64) (User, error) {
	row := q.db.QueryRow(ctx, GetUserByID, id)
	var i User
	err := row.Scan(
		&i.ID,
		&i.FirstName,
		&i.LastName,
		&i.Gender,
		&i.BirthDay,
		&i.Email,
		&i.PhoneNumber,
		&i.Role,
		&i.Password,
		&i.EducationLevel,
		&i.Country,
		&i.Region,
		&i.KnowledgeLevel,
		&i.NickName,
		&i.Occupation,
		&i.LearningGoal,
		&i.LanguageGoal,
		&i.LanguageChallange,
		&i.FavouriteTopic,
		&i.InitialAssessmentCompleted,
		&i.EmailVerified,
		&i.PhoneVerified,
		&i.Status,
		&i.LastLogin,
		&i.ProfileCompleted,
		&i.ProfilePictureUrl,
		&i.PreferredLanguage,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.AgeGroup,
		&i.GoogleID,
		&i.GoogleEmailVerified,
		&i.ProfileCompletionPercentage,
	)
	return i, err
}

const IsUserNameUnique = `-- name: IsUserNameUnique :one
SELECT 
    CASE WHEN COUNT(*) = 0 THEN true ELSE false END AS is_unique
FROM users
WHERE id = $1
`

func (q *Queries) IsUserNameUnique(ctx context.Context, id int64) (bool, error) {
	row := q.db.QueryRow(ctx, IsUserNameUnique, id)
	var is_unique bool
	err := row.Scan(&is_unique)
	return is_unique, err
}

const IsUserPending = `-- name: IsUserPending :one
SELECT 
    CASE WHEN status = 'PENDING' THEN true ELSE false END AS is_pending
FROM users
WHERE id = $1
LIMIT 1
`

func (q *Queries) IsUserPending(ctx context.Context, id int64) (bool, error) {
	row := q.db.QueryRow(ctx, IsUserPending, id)
	var is_pending bool
	err := row.Scan(&is_pending)
	return is_pending, err
}

const LinkGoogleAccount = `-- name: LinkGoogleAccount :exec
UPDATE users
SET
    google_id = $2,
    google_email_verified = true,
    updated_at = CURRENT_TIMESTAMP
WHERE id = $1
`

type LinkGoogleAccountParams struct {
	ID       int64       `json:"id"`
	GoogleID pgtype.Text `json:"google_id"`
}

func (q *Queries) LinkGoogleAccount(ctx context.Context, arg LinkGoogleAccountParams) error {
	_, err := q.db.Exec(ctx, LinkGoogleAccount, arg.ID, arg.GoogleID)
	return err
}

const SearchUserByNameOrPhone = `-- name: SearchUserByNameOrPhone :many
SELECT
    id,
    first_name,
    last_name,
    gender,
    birth_day,
    email,
    phone_number,
    role,
    age_group,
    education_level,
    country,
    region,

    nick_name,
    occupation,
    learning_goal,
    language_goal,
    language_challange,
    favourite_topic,

    initial_assessment_completed,
    profile_picture_url,
    preferred_language,
    email_verified,
    phone_verified,
    status,
    profile_completed,
    created_at,
    updated_at
FROM users
WHERE (
        first_name ILIKE '%' || $1 || '%'
     OR last_name  ILIKE '%' || $1 || '%'
     OR phone_number ILIKE '%' || $1 || '%'
     OR email ILIKE '%' || $1 || '%'
    )
  AND (
        role = $2
        OR $2 IS NULL
    )
`

type SearchUserByNameOrPhoneParams struct {
	Column1 pgtype.Text `json:"column_1"`
	Role    pgtype.Text `json:"role"`
}

type SearchUserByNameOrPhoneRow struct {
	ID                         int64              `json:"id"`
	FirstName                  pgtype.Text        `json:"first_name"`
	LastName                   pgtype.Text        `json:"last_name"`
	Gender                     pgtype.Text        `json:"gender"`
	BirthDay                   pgtype.Date        `json:"birth_day"`
	Email                      pgtype.Text        `json:"email"`
	PhoneNumber                pgtype.Text        `json:"phone_number"`
	Role                       string             `json:"role"`
	AgeGroup                   pgtype.Text        `json:"age_group"`
	EducationLevel             pgtype.Text        `json:"education_level"`
	Country                    pgtype.Text        `json:"country"`
	Region                     pgtype.Text        `json:"region"`
	NickName                   pgtype.Text        `json:"nick_name"`
	Occupation                 pgtype.Text        `json:"occupation"`
	LearningGoal               pgtype.Text        `json:"learning_goal"`
	LanguageGoal               pgtype.Text        `json:"language_goal"`
	LanguageChallange          pgtype.Text        `json:"language_challange"`
	FavouriteTopic             pgtype.Text        `json:"favourite_topic"`
	InitialAssessmentCompleted bool               `json:"initial_assessment_completed"`
	ProfilePictureUrl          pgtype.Text        `json:"profile_picture_url"`
	PreferredLanguage          pgtype.Text        `json:"preferred_language"`
	EmailVerified              bool               `json:"email_verified"`
	PhoneVerified              bool               `json:"phone_verified"`
	Status                     string             `json:"status"`
	ProfileCompleted           pgtype.Bool        `json:"profile_completed"`
	CreatedAt                  pgtype.Timestamptz `json:"created_at"`
	UpdatedAt                  pgtype.Timestamptz `json:"updated_at"`
}

func (q *Queries) SearchUserByNameOrPhone(ctx context.Context, arg SearchUserByNameOrPhoneParams) ([]SearchUserByNameOrPhoneRow, error) {
	rows, err := q.db.Query(ctx, SearchUserByNameOrPhone, arg.Column1, arg.Role)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []SearchUserByNameOrPhoneRow
	for rows.Next() {
		var i SearchUserByNameOrPhoneRow
		if err := rows.Scan(
			&i.ID,
			&i.FirstName,
			&i.LastName,
			&i.Gender,
			&i.BirthDay,
			&i.Email,
			&i.PhoneNumber,
			&i.Role,
			&i.AgeGroup,
			&i.EducationLevel,
			&i.Country,
			&i.Region,
			&i.NickName,
			&i.Occupation,
			&i.LearningGoal,
			&i.LanguageGoal,
			&i.LanguageChallange,
			&i.FavouriteTopic,
			&i.InitialAssessmentCompleted,
			&i.ProfilePictureUrl,
			&i.PreferredLanguage,
			&i.EmailVerified,
			&i.PhoneVerified,
			&i.Status,
			&i.ProfileCompleted,
			&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 UpdatePassword = `-- name: UpdatePassword :exec
UPDATE users
SET
    password = $1,
    updated_at = CURRENT_TIMESTAMP
WHERE id = $2
`

type UpdatePasswordParams struct {
	Password []byte `json:"password"`
	ID       int64  `json:"id"`
}

func (q *Queries) UpdatePassword(ctx context.Context, arg UpdatePasswordParams) error {
	_, err := q.db.Exec(ctx, UpdatePassword, arg.Password, arg.ID)
	return err
}

const UpdateUser = `-- name: UpdateUser :exec
UPDATE users
SET
    first_name      = COALESCE($1, first_name),
    last_name       = COALESCE($2, last_name),
    knowledge_level = COALESCE($3, knowledge_level),
    age_group       = COALESCE($4, age_group),
    education_level = COALESCE($5, education_level),
    country         = COALESCE($6, country),
    region          = COALESCE($7, region),
    nick_name       = COALESCE($8, nick_name),
    occupation      = COALESCE($9, occupation),
    learning_goal   = COALESCE($10, learning_goal),
    language_goal   = COALESCE($11, language_goal),
    language_challange = COALESCE($12, language_challange),
    favourite_topic = COALESCE($13, favourite_topic),
    initial_assessment_completed = COALESCE($14, initial_assessment_completed),
    profile_picture_url = COALESCE($15, profile_picture_url),
    preferred_language = COALESCE($16, preferred_language),
    gender       = COALESCE($17, gender),
    birth_day    = COALESCE($18, birth_day),
    updated_at   = CURRENT_TIMESTAMP
WHERE id = $19
`

type UpdateUserParams struct {
	FirstName                  pgtype.Text `json:"first_name"`
	LastName                   pgtype.Text `json:"last_name"`
	KnowledgeLevel             pgtype.Text `json:"knowledge_level"`
	AgeGroup                   pgtype.Text `json:"age_group"`
	EducationLevel             pgtype.Text `json:"education_level"`
	Country                    pgtype.Text `json:"country"`
	Region                     pgtype.Text `json:"region"`
	NickName                   pgtype.Text `json:"nick_name"`
	Occupation                 pgtype.Text `json:"occupation"`
	LearningGoal               pgtype.Text `json:"learning_goal"`
	LanguageGoal               pgtype.Text `json:"language_goal"`
	LanguageChallange          pgtype.Text `json:"language_challange"`
	FavouriteTopic             pgtype.Text `json:"favourite_topic"`
	InitialAssessmentCompleted bool        `json:"initial_assessment_completed"`
	ProfilePictureUrl          pgtype.Text `json:"profile_picture_url"`
	PreferredLanguage          pgtype.Text `json:"preferred_language"`
	Gender                     pgtype.Text `json:"gender"`
	BirthDay                   pgtype.Date `json:"birth_day"`
	ID                         int64       `json:"id"`
}

// Note: profile_completed and profile_completion_percentage are computed by database trigger
func (q *Queries) UpdateUser(ctx context.Context, arg UpdateUserParams) error {
	_, err := q.db.Exec(ctx, UpdateUser,
		arg.FirstName,
		arg.LastName,
		arg.KnowledgeLevel,
		arg.AgeGroup,
		arg.EducationLevel,
		arg.Country,
		arg.Region,
		arg.NickName,
		arg.Occupation,
		arg.LearningGoal,
		arg.LanguageGoal,
		arg.LanguageChallange,
		arg.FavouriteTopic,
		arg.InitialAssessmentCompleted,
		arg.ProfilePictureUrl,
		arg.PreferredLanguage,
		arg.Gender,
		arg.BirthDay,
		arg.ID,
	)
	return err
}

const UpdateUserKnowledgeLevel = `-- name: UpdateUserKnowledgeLevel :exec
UPDATE users
SET
    knowledge_level = $1,
    updated_at = CURRENT_TIMESTAMP
WHERE id = $2
`

type UpdateUserKnowledgeLevelParams struct {
	KnowledgeLevel pgtype.Text `json:"knowledge_level"`
	ID             int64       `json:"id"`
}

func (q *Queries) UpdateUserKnowledgeLevel(ctx context.Context, arg UpdateUserKnowledgeLevelParams) error {
	_, err := q.db.Exec(ctx, UpdateUserKnowledgeLevel, arg.KnowledgeLevel, arg.ID)
	return err
}

const UpdateUserStatus = `-- name: UpdateUserStatus :exec
UPDATE users
SET
    status = $1,
    updated_at = CURRENT_TIMESTAMP
WHERE id = $2
`

type UpdateUserStatusParams struct {
	Status string `json:"status"`
	ID     int64  `json:"id"`
}

func (q *Queries) UpdateUserStatus(ctx context.Context, arg UpdateUserStatusParams) error {
	_, err := q.db.Exec(ctx, UpdateUserStatus, arg.Status, arg.ID)
	return err
}
