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

package database

import (
	"context"
	"database/sql"
	"time"
)

const createSession = `-- name: CreateSession :one
INSERT INTO session (id, user_id, expires_at)
VALUES (?, ?, ?)
RETURNING id, user_id, expires_at, created_at
`

type CreateSessionParams struct {
	ID        string    `json:"id"`
	UserID    string    `json:"user_id"`
	ExpiresAt time.Time `json:"expires_at"`
}

func (q *Queries) CreateSession(ctx context.Context, arg CreateSessionParams) (Session, error) {
	row := q.db.QueryRowContext(ctx, createSession, arg.ID, arg.UserID, arg.ExpiresAt)
	var i Session
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.ExpiresAt,
		&i.CreatedAt,
	)
	return i, err
}

const createUser = `-- name: CreateUser :one
INSERT INTO user (id, username, password_hash)
VALUES (?, ?, ?)
RETURNING id, username, password_hash, created_at
`

type CreateUserParams struct {
	ID           string `json:"id"`
	Username     string `json:"username"`
	PasswordHash string `json:"password_hash"`
}

func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, error) {
	row := q.db.QueryRowContext(ctx, createUser, arg.ID, arg.Username, arg.PasswordHash)
	var i User
	err := row.Scan(
		&i.ID,
		&i.Username,
		&i.PasswordHash,
		&i.CreatedAt,
	)
	return i, err
}

const deleteSession = `-- name: DeleteSession :exec
DELETE FROM session WHERE id = ?
`

func (q *Queries) DeleteSession(ctx context.Context, id string) error {
	_, err := q.db.ExecContext(ctx, deleteSession, id)
	return err
}

const deleteUserSessions = `-- name: DeleteUserSessions :exec
DELETE FROM session WHERE user_id = ?
`

func (q *Queries) DeleteUserSessions(ctx context.Context, userID string) error {
	_, err := q.db.ExecContext(ctx, deleteUserSessions, userID)
	return err
}

const deleteWatchListEntry = `-- name: DeleteWatchListEntry :exec
DELETE FROM watch_list_entry
WHERE user_id = ? AND anime_id = ?
`

type DeleteWatchListEntryParams struct {
	UserID  string `json:"user_id"`
	AnimeID int64  `json:"anime_id"`
}

func (q *Queries) DeleteWatchListEntry(ctx context.Context, arg DeleteWatchListEntryParams) error {
	_, err := q.db.ExecContext(ctx, deleteWatchListEntry, arg.UserID, arg.AnimeID)
	return err
}

const getAnime = `-- name: GetAnime :one
SELECT id, title_original, image_url, created_at, title_english, title_japanese, airing FROM anime WHERE id = ? LIMIT 1
`

func (q *Queries) GetAnime(ctx context.Context, id int64) (Anime, error) {
	row := q.db.QueryRowContext(ctx, getAnime, id)
	var i Anime
	err := row.Scan(
		&i.ID,
		&i.TitleOriginal,
		&i.ImageUrl,
		&i.CreatedAt,
		&i.TitleEnglish,
		&i.TitleJapanese,
		&i.Airing,
	)
	return i, err
}

const getSession = `-- name: GetSession :one
SELECT id, user_id, expires_at, created_at FROM session WHERE id = ? LIMIT 1
`

func (q *Queries) GetSession(ctx context.Context, id string) (Session, error) {
	row := q.db.QueryRowContext(ctx, getSession, id)
	var i Session
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.ExpiresAt,
		&i.CreatedAt,
	)
	return i, err
}

const getUser = `-- name: GetUser :one
SELECT id, username, password_hash, created_at FROM user WHERE id = ? LIMIT 1
`

func (q *Queries) GetUser(ctx context.Context, id string) (User, error) {
	row := q.db.QueryRowContext(ctx, getUser, id)
	var i User
	err := row.Scan(
		&i.ID,
		&i.Username,
		&i.PasswordHash,
		&i.CreatedAt,
	)
	return i, err
}

const getUserByUsername = `-- name: GetUserByUsername :one
SELECT id, username, password_hash, created_at FROM user WHERE username = ? LIMIT 1
`

func (q *Queries) GetUserByUsername(ctx context.Context, username string) (User, error) {
	row := q.db.QueryRowContext(ctx, getUserByUsername, username)
	var i User
	err := row.Scan(
		&i.ID,
		&i.Username,
		&i.PasswordHash,
		&i.CreatedAt,
	)
	return i, err
}

const getUserWatchList = `-- name: GetUserWatchList :many
SELECT 
    e.id, e.user_id, e.anime_id, e.status, e.created_at, e.updated_at, e.current_episode, e.last_episode_at,
    a.title_original,
    a.title_english,
    a.title_japanese,
    a.image_url,
    a.airing
FROM watch_list_entry e
JOIN anime a ON e.anime_id = a.id
WHERE e.user_id = ?
ORDER BY e.updated_at DESC
`

type GetUserWatchListRow struct {
	ID             string         `json:"id"`
	UserID         string         `json:"user_id"`
	AnimeID        int64          `json:"anime_id"`
	Status         string         `json:"status"`
	CreatedAt      time.Time      `json:"created_at"`
	UpdatedAt      time.Time      `json:"updated_at"`
	CurrentEpisode sql.NullInt64  `json:"current_episode"`
	LastEpisodeAt  sql.NullTime   `json:"last_episode_at"`
	TitleOriginal  string         `json:"title_original"`
	TitleEnglish   sql.NullString `json:"title_english"`
	TitleJapanese  sql.NullString `json:"title_japanese"`
	ImageUrl       string         `json:"image_url"`
	Airing         sql.NullBool   `json:"airing"`
}

func (q *Queries) GetUserWatchList(ctx context.Context, userID string) ([]GetUserWatchListRow, error) {
	rows, err := q.db.QueryContext(ctx, getUserWatchList, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetUserWatchListRow
	for rows.Next() {
		var i GetUserWatchListRow
		if err := rows.Scan(
			&i.ID,
			&i.UserID,
			&i.AnimeID,
			&i.Status,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.CurrentEpisode,
			&i.LastEpisodeAt,
			&i.TitleOriginal,
			&i.TitleEnglish,
			&i.TitleJapanese,
			&i.ImageUrl,
			&i.Airing,
		); 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 getWatchListEntry = `-- name: GetWatchListEntry :one
SELECT id, user_id, anime_id, status, created_at, updated_at, current_episode, last_episode_at FROM watch_list_entry
WHERE user_id = ? AND anime_id = ? LIMIT 1
`

type GetWatchListEntryParams struct {
	UserID  string `json:"user_id"`
	AnimeID int64  `json:"anime_id"`
}

func (q *Queries) GetWatchListEntry(ctx context.Context, arg GetWatchListEntryParams) (WatchListEntry, error) {
	row := q.db.QueryRowContext(ctx, getWatchListEntry, arg.UserID, arg.AnimeID)
	var i WatchListEntry
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.AnimeID,
		&i.Status,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.CurrentEpisode,
		&i.LastEpisodeAt,
	)
	return i, err
}

const getWatchingAnime = `-- name: GetWatchingAnime :many
SELECT 
    e.id, e.user_id, e.anime_id, e.status, e.created_at, e.updated_at, e.current_episode, e.last_episode_at,
    a.title_original,
    a.title_english,
    a.title_japanese,
    a.image_url,
    a.airing
FROM watch_list_entry e
JOIN anime a ON e.anime_id = a.id
WHERE e.user_id = ? AND e.status = 'watching' AND a.airing = 1
ORDER BY e.updated_at DESC
`

type GetWatchingAnimeRow struct {
	ID             string         `json:"id"`
	UserID         string         `json:"user_id"`
	AnimeID        int64          `json:"anime_id"`
	Status         string         `json:"status"`
	CreatedAt      time.Time      `json:"created_at"`
	UpdatedAt      time.Time      `json:"updated_at"`
	CurrentEpisode sql.NullInt64  `json:"current_episode"`
	LastEpisodeAt  sql.NullTime   `json:"last_episode_at"`
	TitleOriginal  string         `json:"title_original"`
	TitleEnglish   sql.NullString `json:"title_english"`
	TitleJapanese  sql.NullString `json:"title_japanese"`
	ImageUrl       string         `json:"image_url"`
	Airing         sql.NullBool   `json:"airing"`
}

func (q *Queries) GetWatchingAnime(ctx context.Context, userID string) ([]GetWatchingAnimeRow, error) {
	rows, err := q.db.QueryContext(ctx, getWatchingAnime, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetWatchingAnimeRow
	for rows.Next() {
		var i GetWatchingAnimeRow
		if err := rows.Scan(
			&i.ID,
			&i.UserID,
			&i.AnimeID,
			&i.Status,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.CurrentEpisode,
			&i.LastEpisodeAt,
			&i.TitleOriginal,
			&i.TitleEnglish,
			&i.TitleJapanese,
			&i.ImageUrl,
			&i.Airing,
		); 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 upsertAnime = `-- name: UpsertAnime :one
INSERT INTO anime (id, title_original, title_english, title_japanese, image_url, airing)
VALUES (?, ?, ?, ?, ?, ?)
ON CONFLICT (id) DO UPDATE SET
    title_original = excluded.title_original,
    title_english = excluded.title_english,
    title_japanese = excluded.title_japanese,
    image_url = excluded.image_url,
    airing = excluded.airing
RETURNING id, title_original, image_url, created_at, title_english, title_japanese, airing
`

type UpsertAnimeParams struct {
	ID            int64          `json:"id"`
	TitleOriginal string         `json:"title_original"`
	TitleEnglish  sql.NullString `json:"title_english"`
	TitleJapanese sql.NullString `json:"title_japanese"`
	ImageUrl      string         `json:"image_url"`
	Airing        sql.NullBool   `json:"airing"`
}

func (q *Queries) UpsertAnime(ctx context.Context, arg UpsertAnimeParams) (Anime, error) {
	row := q.db.QueryRowContext(ctx, upsertAnime,
		arg.ID,
		arg.TitleOriginal,
		arg.TitleEnglish,
		arg.TitleJapanese,
		arg.ImageUrl,
		arg.Airing,
	)
	var i Anime
	err := row.Scan(
		&i.ID,
		&i.TitleOriginal,
		&i.ImageUrl,
		&i.CreatedAt,
		&i.TitleEnglish,
		&i.TitleJapanese,
		&i.Airing,
	)
	return i, err
}

const upsertWatchListEntry = `-- name: UpsertWatchListEntry :one
INSERT INTO watch_list_entry (id, user_id, anime_id, status, current_episode, updated_at)
VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
ON CONFLICT (user_id, anime_id) DO UPDATE SET
    status = excluded.status,
    current_episode = excluded.current_episode,
    updated_at = CURRENT_TIMESTAMP
RETURNING id, user_id, anime_id, status, created_at, updated_at, current_episode, last_episode_at
`

type UpsertWatchListEntryParams struct {
	ID             string        `json:"id"`
	UserID         string        `json:"user_id"`
	AnimeID        int64         `json:"anime_id"`
	Status         string        `json:"status"`
	CurrentEpisode sql.NullInt64 `json:"current_episode"`
}

func (q *Queries) UpsertWatchListEntry(ctx context.Context, arg UpsertWatchListEntryParams) (WatchListEntry, error) {
	row := q.db.QueryRowContext(ctx, upsertWatchListEntry,
		arg.ID,
		arg.UserID,
		arg.AnimeID,
		arg.Status,
		arg.CurrentEpisode,
	)
	var i WatchListEntry
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.AnimeID,
		&i.Status,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.CurrentEpisode,
		&i.LastEpisodeAt,
	)
	return i, err
}
