package repository

import (
	"context"
	"fmt"
	"git.gocasts.ir/ebhomengo/niki/domain/shoppingbasket/entity"
	"git.gocasts.ir/ebhomengo/niki/types"
	"time"
)

type Config struct {
	CacheKartKeyPrefix string        `koanf:"cache_kart_key_prefix"`
	CacheTTL           time.Duration `koanf:"cache_ttl"`

	MysqlTTL time.Duration `koanf:"mysql_ttl"`
}

type Repo struct {
	db    DB
	cache Cache
}

func New(db DB, cache Cache) Repo {
	return Repo{db: db, cache: cache}
}

func op(s string) string {
	return fmt.Sprintf("shoppingbasketapp-repository-", s)
}

func (r Repo) AddItem(ctx context.Context, userID types.ID, item entity.Item) error {
	if err := r.db.addToBasket(ctx, userID, item); err != nil {
		return err
	}

	cart, err := r.db.getCart(ctx, nil, FindCartByUserIDQuery, userID)
	if err != nil {
		return err
	}

	return r.cache.upsertCart(ctx, cart)
}

func (r Repo) GetCart(ctx context.Context, userID types.ID) (entity.Cart, error) {
	cart, err := r.cache.getCart(ctx, userID)
	if err != nil {
		return entity.Cart{}, err
	}

	if cart.ID < 1 || len(cart.Items) < 1 {
		c, err := r.db.getCart(ctx, nil, FindCartByUserIDQuery, userID)
		if err != nil {
			return entity.Cart{}, err
		}

		if c.ID < 1 {
			return entity.Cart{}, nil
		}

		if err := r.cache.upsertCart(ctx, c); err != nil {
			return entity.Cart{}, err
		}

		return c, nil
	}

	return cart, nil
}

func (r Repo) UpdateQuantity(ctx context.Context, cartID, itemID types.ID, quantity int) error {

	cart, err := r.db.getCart(ctx, nil, FindCartByIDQuery, cartID)
	if err != nil {
		return err
	}

	for i, item := range cart.Items {
		if item.ID == itemID {
			cart.Items[i].Quantity = quantity
			item.Quantity = quantity
			if err := r.db.updateQuantity(ctx, nil, item); err != nil {
				return err
			}
		}
	}

	return r.cache.upsertCart(ctx, cart)
}

func (r Repo) UpdateStatus(ctx context.Context, cartID types.ID, status entity.CartStatus) error {
	if err := r.db.updateCartStatus(ctx, nil, cartID, status); err != nil {
		return err
	}

	cart, err := r.db.getCart(ctx, nil, FindCartByIDQuery, cartID)
	if err != nil {
		return err
	}

	return r.cache.upsertCart(ctx, cart)
}

func (r Repo) DeleteItem(ctx context.Context, cartID, itemID types.ID) error {
	if err := r.db.deleteItem(ctx, nil, cartID, itemID); err != nil {
		return err
	}

	c, err := r.db.getCart(ctx, nil, FindCartByIDQuery, cartID)
	if err != nil {
		return err
	}

	return r.cache.upsertCart(ctx, c)
}

func (r Repo) DeleteCart(ctx context.Context, cartID, userID types.ID) error {

	if err := r.db.deleteCart(ctx, cartID, userID); err != nil {
		return err
	}

	return r.cache.deleteCart(ctx, userID)
}
