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

package database

import (
	"context"
	"net/netip"

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

const CleanupExpiredSessions = `-- name: CleanupExpiredSessions :exec
DELETE FROM user_sessions
WHERE expires_at < CURRENT_TIMESTAMP
    OR last_activity_at < CURRENT_TIMESTAMP - INTERVAL '7 days'
`

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

const CleanupExpiredTokens = `-- name: CleanupExpiredTokens :exec
DELETE FROM refresh_tokens
WHERE expires_at < CURRENT_TIMESTAMP
    OR (revoked = TRUE AND revoked_at < CURRENT_TIMESTAMP - INTERVAL '30 days')
`

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

const CreateRefreshToken = `-- name: CreateRefreshToken :one

INSERT INTO refresh_tokens (
    user_id,
    token,
    expires_at,
    user_agent,
    ip_address
) VALUES (
    $1,
    $2,
    $3,
    $4,
    $5
) RETURNING id, user_id, token, expires_at, user_agent, ip_address, revoked, revoked_at, created_at
`

type CreateRefreshTokenParams struct {
	UserID    int64              `json:"user_id"`
	Token     string             `json:"token"`
	ExpiresAt pgtype.Timestamptz `json:"expires_at"`
	UserAgent pgtype.Text        `json:"user_agent"`
	IpAddress *netip.Addr        `json:"ip_address"`
}

// ============================================================================
// Refresh Tokens
// ============================================================================
func (q *Queries) CreateRefreshToken(ctx context.Context, arg CreateRefreshTokenParams) (RefreshToken, error) {
	row := q.db.QueryRow(ctx, CreateRefreshToken,
		arg.UserID,
		arg.Token,
		arg.ExpiresAt,
		arg.UserAgent,
		arg.IpAddress,
	)
	var i RefreshToken
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.Token,
		&i.ExpiresAt,
		&i.UserAgent,
		&i.IpAddress,
		&i.Revoked,
		&i.RevokedAt,
		&i.CreatedAt,
	)
	return i, err
}

const CreateUser = `-- name: CreateUser :one


INSERT INTO users (
    email,
    phone,
    password_hash,
    first_name,
    last_name,
    location,
    address,
    city
) VALUES (
    $1,
    $2,
    $3,
    $4,
    $5,
    ST_SetSRID(ST_MakePoint($6, $7), 4326)::geography,
    $8,
    $9
) RETURNING
    id,
    email,
    phone,
    password_hash,
    first_name,
    last_name,
    avatar_url,
    ST_Y(location::geometry) as latitude,
    ST_X(location::geometry) as longitude,
    address,
    city,
    volunteer_rating,
    completed_requests_count,
    is_verified,
    is_blocked,
    email_verified,
    created_at,
    updated_at,
    last_login_at,
    deleted_at
`

type CreateUserParams struct {
	Email         string      `json:"email"`
	Phone         pgtype.Text `json:"phone"`
	PasswordHash  string      `json:"password_hash"`
	FirstName     string      `json:"first_name"`
	LastName      string      `json:"last_name"`
	StMakepoint   interface{} `json:"st_makepoint"`
	StMakepoint_2 interface{} `json:"st_makepoint_2"`
	Address       pgtype.Text `json:"address"`
	City          pgtype.Text `json:"city"`
}

type CreateUserRow struct {
	ID                     int64              `json:"id"`
	Email                  string             `json:"email"`
	Phone                  pgtype.Text        `json:"phone"`
	PasswordHash           string             `json:"password_hash"`
	FirstName              string             `json:"first_name"`
	LastName               string             `json:"last_name"`
	AvatarUrl              pgtype.Text        `json:"avatar_url"`
	Latitude               interface{}        `json:"latitude"`
	Longitude              interface{}        `json:"longitude"`
	Address                pgtype.Text        `json:"address"`
	City                   pgtype.Text        `json:"city"`
	VolunteerRating        pgtype.Numeric     `json:"volunteer_rating"`
	CompletedRequestsCount pgtype.Int4        `json:"completed_requests_count"`
	IsVerified             pgtype.Bool        `json:"is_verified"`
	IsBlocked              pgtype.Bool        `json:"is_blocked"`
	EmailVerified          pgtype.Bool        `json:"email_verified"`
	CreatedAt              pgtype.Timestamptz `json:"created_at"`
	UpdatedAt              pgtype.Timestamptz `json:"updated_at"`
	LastLoginAt            pgtype.Timestamptz `json:"last_login_at"`
	DeletedAt              pgtype.Timestamptz `json:"deleted_at"`
}

// Фаза 1A: Аутентификация (КРИТИЧНО)
// Запросы для регистрации, входа и управления токенами
// ============================================================================
// Пользователи
// ============================================================================
func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (CreateUserRow, error) {
	row := q.db.QueryRow(ctx, CreateUser,
		arg.Email,
		arg.Phone,
		arg.PasswordHash,
		arg.FirstName,
		arg.LastName,
		arg.StMakepoint,
		arg.StMakepoint_2,
		arg.Address,
		arg.City,
	)
	var i CreateUserRow
	err := row.Scan(
		&i.ID,
		&i.Email,
		&i.Phone,
		&i.PasswordHash,
		&i.FirstName,
		&i.LastName,
		&i.AvatarUrl,
		&i.Latitude,
		&i.Longitude,
		&i.Address,
		&i.City,
		&i.VolunteerRating,
		&i.CompletedRequestsCount,
		&i.IsVerified,
		&i.IsBlocked,
		&i.EmailVerified,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.LastLoginAt,
		&i.DeletedAt,
	)
	return i, err
}

const CreateUserSession = `-- name: CreateUserSession :one

INSERT INTO user_sessions (
    user_id,
    session_token,
    refresh_token_id,
    expires_at,
    user_agent,
    ip_address,
    device_info
) VALUES (
    $1,
    $2,
    $3,
    $4,
    $5,
    $6,
    $7
) RETURNING id, user_id, session_token, refresh_token_id, expires_at, last_activity_at, user_agent, ip_address, device_info, created_at
`

type CreateUserSessionParams struct {
	UserID         int64              `json:"user_id"`
	SessionToken   string             `json:"session_token"`
	RefreshTokenID pgtype.Int8        `json:"refresh_token_id"`
	ExpiresAt      pgtype.Timestamptz `json:"expires_at"`
	UserAgent      pgtype.Text        `json:"user_agent"`
	IpAddress      *netip.Addr        `json:"ip_address"`
	DeviceInfo     []byte             `json:"device_info"`
}

// ============================================================================
// User Sessions
// ============================================================================
func (q *Queries) CreateUserSession(ctx context.Context, arg CreateUserSessionParams) (UserSession, error) {
	row := q.db.QueryRow(ctx, CreateUserSession,
		arg.UserID,
		arg.SessionToken,
		arg.RefreshTokenID,
		arg.ExpiresAt,
		arg.UserAgent,
		arg.IpAddress,
		arg.DeviceInfo,
	)
	var i UserSession
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.SessionToken,
		&i.RefreshTokenID,
		&i.ExpiresAt,
		&i.LastActivityAt,
		&i.UserAgent,
		&i.IpAddress,
		&i.DeviceInfo,
		&i.CreatedAt,
	)
	return i, err
}

const EmailExists = `-- name: EmailExists :one
SELECT EXISTS(
    SELECT 1 FROM users
    WHERE email = $1 AND deleted_at IS NULL
)
`

func (q *Queries) EmailExists(ctx context.Context, email string) (bool, error) {
	row := q.db.QueryRow(ctx, EmailExists, email)
	var exists bool
	err := row.Scan(&exists)
	return exists, err
}

const GetRefreshToken = `-- name: GetRefreshToken :one
SELECT id, user_id, token, expires_at, user_agent, ip_address, revoked, revoked_at, created_at FROM refresh_tokens
WHERE token = $1
    AND revoked = FALSE
    AND expires_at > CURRENT_TIMESTAMP
`

func (q *Queries) GetRefreshToken(ctx context.Context, token string) (RefreshToken, error) {
	row := q.db.QueryRow(ctx, GetRefreshToken, token)
	var i RefreshToken
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.Token,
		&i.ExpiresAt,
		&i.UserAgent,
		&i.IpAddress,
		&i.Revoked,
		&i.RevokedAt,
		&i.CreatedAt,
	)
	return i, err
}

const GetUserByEmail = `-- name: GetUserByEmail :one
SELECT
    id,
    email,
    phone,
    password_hash,
    first_name,
    last_name,
    avatar_url,
    ST_Y(location::geometry) as latitude,
    ST_X(location::geometry) as longitude,
    address,
    city,
    volunteer_rating,
    completed_requests_count,
    is_verified,
    is_blocked,
    email_verified,
    created_at,
    updated_at,
    last_login_at,
    deleted_at
FROM users
WHERE email = $1 AND deleted_at IS NULL
`

type GetUserByEmailRow struct {
	ID                     int64              `json:"id"`
	Email                  string             `json:"email"`
	Phone                  pgtype.Text        `json:"phone"`
	PasswordHash           string             `json:"password_hash"`
	FirstName              string             `json:"first_name"`
	LastName               string             `json:"last_name"`
	AvatarUrl              pgtype.Text        `json:"avatar_url"`
	Latitude               interface{}        `json:"latitude"`
	Longitude              interface{}        `json:"longitude"`
	Address                pgtype.Text        `json:"address"`
	City                   pgtype.Text        `json:"city"`
	VolunteerRating        pgtype.Numeric     `json:"volunteer_rating"`
	CompletedRequestsCount pgtype.Int4        `json:"completed_requests_count"`
	IsVerified             pgtype.Bool        `json:"is_verified"`
	IsBlocked              pgtype.Bool        `json:"is_blocked"`
	EmailVerified          pgtype.Bool        `json:"email_verified"`
	CreatedAt              pgtype.Timestamptz `json:"created_at"`
	UpdatedAt              pgtype.Timestamptz `json:"updated_at"`
	LastLoginAt            pgtype.Timestamptz `json:"last_login_at"`
	DeletedAt              pgtype.Timestamptz `json:"deleted_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.Email,
		&i.Phone,
		&i.PasswordHash,
		&i.FirstName,
		&i.LastName,
		&i.AvatarUrl,
		&i.Latitude,
		&i.Longitude,
		&i.Address,
		&i.City,
		&i.VolunteerRating,
		&i.CompletedRequestsCount,
		&i.IsVerified,
		&i.IsBlocked,
		&i.EmailVerified,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.LastLoginAt,
		&i.DeletedAt,
	)
	return i, err
}

const GetUserByID = `-- name: GetUserByID :one
SELECT
    id,
    email,
    phone,
    password_hash,
    first_name,
    last_name,
    avatar_url,
    ST_Y(location::geometry) as latitude,
    ST_X(location::geometry) as longitude,
    address,
    city,
    volunteer_rating,
    completed_requests_count,
    is_verified,
    is_blocked,
    email_verified,
    created_at,
    updated_at,
    last_login_at,
    deleted_at
FROM users
WHERE id = $1 AND deleted_at IS NULL
`

type GetUserByIDRow struct {
	ID                     int64              `json:"id"`
	Email                  string             `json:"email"`
	Phone                  pgtype.Text        `json:"phone"`
	PasswordHash           string             `json:"password_hash"`
	FirstName              string             `json:"first_name"`
	LastName               string             `json:"last_name"`
	AvatarUrl              pgtype.Text        `json:"avatar_url"`
	Latitude               interface{}        `json:"latitude"`
	Longitude              interface{}        `json:"longitude"`
	Address                pgtype.Text        `json:"address"`
	City                   pgtype.Text        `json:"city"`
	VolunteerRating        pgtype.Numeric     `json:"volunteer_rating"`
	CompletedRequestsCount pgtype.Int4        `json:"completed_requests_count"`
	IsVerified             pgtype.Bool        `json:"is_verified"`
	IsBlocked              pgtype.Bool        `json:"is_blocked"`
	EmailVerified          pgtype.Bool        `json:"email_verified"`
	CreatedAt              pgtype.Timestamptz `json:"created_at"`
	UpdatedAt              pgtype.Timestamptz `json:"updated_at"`
	LastLoginAt            pgtype.Timestamptz `json:"last_login_at"`
	DeletedAt              pgtype.Timestamptz `json:"deleted_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.Email,
		&i.Phone,
		&i.PasswordHash,
		&i.FirstName,
		&i.LastName,
		&i.AvatarUrl,
		&i.Latitude,
		&i.Longitude,
		&i.Address,
		&i.City,
		&i.VolunteerRating,
		&i.CompletedRequestsCount,
		&i.IsVerified,
		&i.IsBlocked,
		&i.EmailVerified,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.LastLoginAt,
		&i.DeletedAt,
	)
	return i, err
}

const GetUserSession = `-- name: GetUserSession :one
SELECT id, user_id, session_token, refresh_token_id, expires_at, last_activity_at, user_agent, ip_address, device_info, created_at FROM user_sessions
WHERE session_token = $1
    AND expires_at > CURRENT_TIMESTAMP
`

func (q *Queries) GetUserSession(ctx context.Context, sessionToken string) (UserSession, error) {
	row := q.db.QueryRow(ctx, GetUserSession, sessionToken)
	var i UserSession
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.SessionToken,
		&i.RefreshTokenID,
		&i.ExpiresAt,
		&i.LastActivityAt,
		&i.UserAgent,
		&i.IpAddress,
		&i.DeviceInfo,
		&i.CreatedAt,
	)
	return i, err
}

const InvalidateAllUserSessions = `-- name: InvalidateAllUserSessions :exec
DELETE FROM user_sessions
WHERE user_id = $1
`

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

const InvalidateUserSession = `-- name: InvalidateUserSession :exec
DELETE FROM user_sessions
WHERE id = $1
`

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

const RevokeAllUserTokens = `-- name: RevokeAllUserTokens :exec
UPDATE refresh_tokens
SET revoked = TRUE, revoked_at = CURRENT_TIMESTAMP
WHERE user_id = $1 AND revoked = FALSE
`

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

const RevokeRefreshToken = `-- name: RevokeRefreshToken :exec
UPDATE refresh_tokens
SET revoked = TRUE, revoked_at = CURRENT_TIMESTAMP
WHERE id = $1
`

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

const UpdateLastLogin = `-- name: UpdateLastLogin :exec
UPDATE users
SET last_login_at = CURRENT_TIMESTAMP
WHERE id = $1
`

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

const UpdateSessionActivity = `-- name: UpdateSessionActivity :exec
UPDATE user_sessions
SET last_activity_at = CURRENT_TIMESTAMP
WHERE id = $1
`

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