package repo

import (
	"58team_blog/internal/domain/entities"
	"58team_blog/internal/infrastructure/db"

	"github.com/google/uuid"
	"github.com/jmoiron/sqlx"
)

type UserRepository struct {
	conn *db.Database
}

func CreateUserRepository(conn *db.Database) UserRepository {
	return UserRepository{
		conn: conn,
	}
}

func (r *UserRepository) Create(entity *entities.User) (*entities.User, error) {
	query := "INSERT INTO " + entities.UserTable + "(id, username, password) VALUES (:id, :username, :password)"
	_, err := r.conn.Conn.NamedExec(query, entity)

	if err != nil {
		return nil, err
	}

	return entity, nil
}

func (r *UserRepository) FindById(id uuid.UUID) (*entities.User, error) {
	var entity *entities.User

	query := "SELECT * FROM " + entities.UserTable + " WHERE id=?"
	query, arg, err := sqlx.In(query, id)
	if err != nil {
		return nil, err
	}

	query = r.conn.Conn.Rebind(query)
	err = r.conn.Conn.Get(entity, query, arg...)

	return entity, err
}

func (r *UserRepository) FindByName(username string) (*entities.User, error) {
	var entity *entities.User

	query := "SELECT * FROM " + entities.UserTable + " WHERE username=?"
	query, arg, err := sqlx.In(query, username)
	if err != nil {
		return nil, err
	}

	query = r.conn.Conn.Rebind(query)
	err = r.conn.Conn.Get(entity, query, arg...)

	return entity, err
}

func (r *UserRepository) GetAll() ([]*entities.User, error) {
	var entity_list []*entities.User

	query := "SELECT * FROM " + entities.UserTable
	err := r.conn.Conn.Select(entity_list, query)
	if err != nil {
		return nil, err
	}

	return entity_list, nil
}

func (r *UserRepository) Update(user *entities.User) error {
	query := "UPDATE " + entities.UserTable + " SET username=:username, password=:password WHERE id=:id"

	_, err := r.conn.Conn.NamedExec(query, user)

	return err
}

func (r *UserRepository) Delete(id uuid.UUID) error {
	query := "DELETE FROM " + entities.UserTable + " WHERE id=?"

	query, arg, err := sqlx.In(query, id)
	if err != nil {
		return err
	}

	query = r.conn.Conn.Rebind(query)
	_, err = r.conn.Conn.Exec(query, arg...)

	return err
}
