package postgresql

import (
	"database/sql"
	"hamster-tycoon/storage/dao"
	"hamster-tycoon/storage/model"

	"github.com/lib/pq"
)

func (db *DatabasePostgreSQL) GetAllUsers() ([]*model.User, error) {
	q := `
		SELECT u.id, u.created_at, u.updated_at, u.nickname
		FROM public.user u
	`
	rows, err := db.session.Query(q)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	us := make([]*model.User, 0)
	for rows.Next() {
		u := model.User{}
		err := rows.Scan(&u.ID, &u.CreatedAt, &u.UpdatedAt, &u.Nickname)
		if err != nil {
			return nil, err
		}
		us = append(us, &u)
	}
	return us, nil
}

func (db *DatabasePostgreSQL) GetUsersByID(id string) (*model.User, error) {
	q := `
		SELECT u.id, u.created_at, u.updated_at, u.nickname
		FROM public.user u
		WHERE u.id = $1
	`
	row := db.session.QueryRow(q, id)

	u := model.User{}
	err := row.Scan(&u.ID, &u.CreatedAt, &u.UpdatedAt, &u.Nickname)
	if errPq, ok := err.(*pq.Error); ok {
		return nil, handlePgError(errPq)
	}
	if err == sql.ErrNoRows {
		return nil, dao.NewDAOError(dao.ErrTypeNotFound, err)
	}
	return &u, err
}

func (db *DatabasePostgreSQL) CreateUser(user *model.User) error {
	q := `
		INSERT INTO public.user
			(nickname, google_id)
		VALUES
			($1, $2)
		RETURNING id, created_at
	`

	err := db.session.
		QueryRow(q, user.Nickname, user.GoogleID).
		Scan(&user.ID, &user.CreatedAt)
	if errPq, ok := err.(*pq.Error); ok {
		return handlePgError(errPq)
	}
	return err
}

func (db *DatabasePostgreSQL) DeleteUser(id string) error {
	q := `
		DELETE FROM public.user
		WHERE id = $1
	`

	_, err := db.session.Exec(q, id)
	if errPq, ok := err.(*pq.Error); ok {
		return handlePgError(errPq)
	}
	return err
}

func (db *DatabasePostgreSQL) UpdateUser(user *model.User) error {
	return nil
}

func (db *DatabasePostgreSQL) GetUsersByGoogleID(id string) (*model.User, error) {
	q := `
		SELECT u.id, u.created_at, u.updated_at, u.nickname, u.google_id
		FROM public.user u
		WHERE u.google_id = $1
	`
	row := db.session.QueryRow(q, id)

	u := model.User{}
	err := row.Scan(&u.ID, &u.CreatedAt, &u.UpdatedAt, &u.Nickname, &u.GoogleID)
	if errPq, ok := err.(*pq.Error); ok {
		return nil, handlePgError(errPq)
	}
	if err == sql.ErrNoRows {
		return nil, dao.NewDAOError(dao.ErrTypeNotFound, err)
	}
	return &u, err
}
