package models

// Quantity is the quantity for a book
type Quantity struct {
	ID       int64 `xorm:"int(11) autoincr not null unique pk"`
	ItemID   int64 `xorm:"int(11) not null"`
	Quantity int64 `xorm:"int(11) not null"`
	Created  int64 `xorm:"created"`
}

// TableName returns the name for the quantites table
func (Quantity) TableName() string {
	return "quantities"
}

// Quantityrelations holds information about wherether the quantity we are currently dealing with is one of a book or an item
// We cannot directly link quantites to items and books because they can have the same id... which is why we need this.
type quantityRelation struct {
	ID      int64 `xorm:"int(11) autoincr not null unique pk"`
	ItemID  int64 `xorm:"int(11) not null"`
	BookID  int64 `xorm:"int(11) not null"`
	Created int64 `xorm:"created"`
}

// TableName returns the name for the quantites table
func (quantityRelation) TableName() string {
	return "quantity_relations"
}

// GetQuantity gets the latest quantity
func GetQuantity(itemID int64) (quantity int64, err error) {

	// Return nothing if we dont have an item
	if itemID == 0 {
		return 0, nil
	}

	// Get the quanitty
	bq := Quantity{ItemID: itemID}
	has, err := x.Desc("id").Get(&bq)
	if err != nil {
		return 0, err
	}

	if has {
		quantity = bq.Quantity
	}

	return quantity, nil
}

// SetQuantity sets the quantity for an item
func SetQuantity(itemID, quantity int64) (err error) {
	// Check if the quantity already exists and only insert it if not
	qty, err := GetQuantity(itemID)
	if err != nil {
		return err
	}

	if qty != quantity {
		q := Quantity{ItemID: itemID, Quantity: quantity}
		_, err = x.Insert(q)
		return err
	}

	return nil
}

// ===== ITEMS =====

// Get item quantity with relation
func (item Item) getQuantity() (quantity int64, err error) {
	qty := Quantity{}
	_, err = x.Table("quantities").
		Select("quantities.id, quantity_relations.item_id, quantities.quantity, quantities.created").
		Join("INNER", "quantity_relations", "quantities.item_id = quantity_relations.id").
		Where("quantity_relations.item_id = ?", item.ID).
		Desc("quantities.created").Get(&qty)

	return qty.Quantity, err
}

// Set item quantity with relation
func (item Item) setQuantity(quantity int64) (err error) {
	// Check if the relation already exists, if not, create a new one
	qty := quantityRelation{ItemID: item.ID}
	exists, err := x.Get(&qty)
	if err != nil {
		return
	}

	if !exists {
		rel := quantityRelation{ItemID: item.ID}
		_, err := x.Insert(&rel)
		if err != nil {
			return err
		}

		qty.ID = rel.ID
	}

	// Insert the new quantity
	return SetQuantity(qty.ID, quantity)
}

// ===== BOOKS =====

// Get book quantity with relation
func (book Book) getQuantity() (quantity int64, err error) {
	qty := Quantity{}
	_, err = x.Table("quantities").
		Select("quantities.id, quantity_relations.item_id, quantities.quantity, quantities.created").
		Join("INNER", "quantity_relations", "quantities.item_id = quantity_relations.id").
		Where("quantity_relations.book_id = ?", book.ID).
		Desc("quantities.created").Get(&qty)

	return qty.Quantity, err
}

// Set book quantity with relation
func (book Book) setQuantity(quantity int64) (err error) {
	// Check if the relation already exists, if not, create a new one
	qty := quantityRelation{BookID: book.ID}
	exists, err := x.Get(&qty)
	if err != nil {
		return
	}

	if !exists {
		rel := quantityRelation{BookID: book.ID}
		_, err := x.Insert(&rel)
		if err != nil {
			return err
		}

		qty.ID = rel.ID
	}

	// Insert the new quantity
	return SetQuantity(qty.ID, quantity)
}
