package postgresql

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

	"github.com/lib/pq"
)

func (db *DatabasePostgreSQL) GetAllHamsters(cageID string) ([]*model.Hamster, error) {
	q := `
		SELECT id, created_at, updated_at, name, number, sexe, age, father_id, mother_id, hunger_level, thirst_level, weight, height, alive, sold, golden, gestation, gestation_period, gestation_cooldown, gestation_father_id, cage_id
		FROM hamster h
		JOIN cage c ON h.cage_id = c.id
		WHERE c.id=$1 and g.id=$2
	`
	rows, err := db.session.Query(q, cageID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	hamsters := make([]*model.Hamster, 0)
	for rows.Next() {
		hamster := model.Hamster{
			Mother:          &model.Hamster{},
			Father:          &model.Hamster{},
			GestationFather: &model.Hamster{},
			Cage:            &model.Cage{},
		}
		err := rows.Scan(&hamster.ID, &hamster.CreatedAt,
			&hamster.UpdatedAt, &hamster.Name,
			&hamster.Number, &hamster.Sexe,
			&hamster.Age, &hamster.Father.ID,
			&hamster.Mother.ID, &hamster.HungerLevel,
			&hamster.ThirstLevel, &hamster.Weight,
			&hamster.Height, &hamster.Alive,
			&hamster.Sold, &hamster.Golden, &hamster.Gestation,
			&hamster.GestationPeriod, &hamster.GestationCooldown,
			&hamster.GestationFather.ID, &hamster.Cage.ID)
		if err != nil {
			return nil, err
		}
		hamsters = append(hamsters, &hamster)
	}
	return hamsters, nil
}

func (db *DatabasePostgreSQL) GetHamsterByID(id, cageID string) (*model.Hamster, error) {
	q := `
		SELECT id, created_at, updated_at, name, number, sexe, age, father_id, mother_id, hunger_level, thirst_level, weight, height, alive, sold, golden, gestation, gestation_period, gestation_cooldown, gestation_father_id, cage_id
		FROM hamster h
		JOIN cage c ON h.cage_id = c.id
		WHERE h.id=$1 and c.id=$2 and g.id=$3
	`
	row := db.session.QueryRow(q, id, cageID)

	hamster := model.Hamster{
		Mother:          &model.Hamster{},
		Father:          &model.Hamster{},
		GestationFather: &model.Hamster{},
		Cage:            &model.Cage{},
	}
	err := row.Scan(&hamster.ID, &hamster.CreatedAt,
		&hamster.UpdatedAt, &hamster.Name,
		&hamster.Number, &hamster.Sexe,
		&hamster.Age, &hamster.Father.ID,
		&hamster.Mother.ID, &hamster.HungerLevel,
		&hamster.ThirstLevel, &hamster.Weight,
		&hamster.Height, &hamster.Alive,
		&hamster.Sold, &hamster.Golden, &hamster.Gestation,
		&hamster.GestationPeriod, &hamster.GestationCooldown,
		&hamster.GestationFather.ID, &hamster.Cage.ID)

	if errPq, ok := err.(*pq.Error); ok {
		return nil, handlePgError(errPq)
	}
	if err == sql.ErrNoRows {
		return nil, dao.NewDAOError(dao.ErrTypeNotFound, err)
	}
	return &hamster, err
}

func (db *DatabasePostgreSQL) CreateHamster(hamster *model.Hamster) error {
	q := `
		INSERT INTO public.Hamster
			(name, number, sexe, age, father_id, mother_id, hunger_level, thirst_level, weight, height, alive, sold, golden, gestation, gestation_period, gestation_cooldown, gestation_father_id,cage_id)
		VALUES
			($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
		RETURNING id, created_at
	`

	err := db.session.
		QueryRow(q, &hamster.Name,
			&hamster.Number, &hamster.Sexe,
			&hamster.Age, &hamster.Father.ID,
			&hamster.Mother.ID, &hamster.HungerLevel,
			&hamster.ThirstLevel, &hamster.Weight,
			&hamster.Height, &hamster.Alive,
			&hamster.Sold, &hamster.Golden, &hamster.Gestation,
			&hamster.GestationPeriod, &hamster.GestationCooldown,
			&hamster.GestationFather.ID, &hamster.Cage.ID).
		Scan(&hamster.ID, &hamster.CreatedAt)
	if errPq, ok := err.(*pq.Error); ok {
		return handlePgError(errPq)
	}
	return err
}

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

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

func (db *DatabasePostgreSQL) UpdateHamster(hamster *model.Hamster) error {
	return nil
}
