package repositories

import (
	"gorm.io/gorm"
	"strconv"

	"git.dynamicdiscord.de/kalipso/zineshop/models"
)

type OrderRepository interface {
	Create(models.Order) (models.Order, error)
	GetAll() ([]models.Order, error)
	GetById(string) (models.Order, error)
	GetBySession(string) (models.Order, error)
	GetByToken(string) (models.Order, error)
	Update(models.Order) (models.Order, error)
	DeleteById(string) error
	DeleteByToken(string) error
}

type GORMOrderRepository struct {
	DB *gorm.DB
}

func NewGORMOrderRepository(db *gorm.DB) OrderRepository {
	return &GORMOrderRepository{
		DB: db,
	}
}

func (r *GORMOrderRepository) Create(order models.Order) (models.Order, error) {
	//Omit the shopitem so it is not created again in db leading to unique constain fails
	result := r.DB.Omit("CartItems").Create(&order)
	if result.Error != nil {
		return models.Order{}, result.Error
	}

	return order, nil
}

func (r *GORMOrderRepository) GetAll() ([]models.Order, error) {
	var orders []models.Order
	result := r.DB.Preload("CartItems").Find(&orders)

	return orders, result.Error
}

func (t *GORMOrderRepository) GetById(id string) (models.Order, error) {
	orderId, err := strconv.Atoi(id)

	if err != nil {
		return models.Order{}, err
	}

	var order models.Order
	result := t.DB.Preload("CartItems").First(&order, uint(orderId))

	if result.Error != nil {
		return models.Order{}, result.Error
	}

	return order, nil
}

func (r *GORMOrderRepository) GetBySession(sessionId string) (models.Order, error) {
	var orders models.Order
	result := r.DB.Preload("CartItems").Preload("CartItems.ShopItem").Preload("CartItems.ItemVariant").Where("session_id = ?", sessionId).First(&orders)

	return orders, result.Error

}

func (r *GORMOrderRepository) GetByToken(token string) (models.Order, error) {
	var orders models.Order
	result := r.DB.Preload("CartItems").Preload("CartItems.ShopItem").Preload("CartItems.ItemVariant").Where("token = ?", token).First(&orders)

	return orders, result.Error
}

func (r *GORMOrderRepository) Update(order models.Order) (models.Order, error) {
	result := r.DB.Save(&order)
	if result.Error != nil {
		return models.Order{}, result.Error
	}

	return order, nil
}

func (r *GORMOrderRepository) DeleteById(id string) error {
	orderId, err := strconv.Atoi(id)

	if err != nil {
		return err
	}

	result := r.DB.Delete(&models.Order{}, orderId)
	return result.Error
}

func (r *GORMOrderRepository) DeleteByToken(token string) error {
	result := r.DB.Where("token = ?", token).Delete(&models.Order{})
	return result.Error
}
