package service

import (
	"context"
	"git.gocasts.ir/ebhomengo/niki/domain/shoppingbasket/entity"
	"git.gocasts.ir/ebhomengo/niki/pkg/logger"
	richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
	"git.gocasts.ir/ebhomengo/niki/types"
	"time"
)

type Repository interface {
	AddItem(ctx context.Context, userID types.ID, item entity.Item) error
	GetCart(ctx context.Context, userID types.ID) (entity.Cart, error)
	DeleteItem(ctx context.Context, userID, productID types.ID) error
	UpdateQuantity(ctx context.Context, userID, productID types.ID, quantity int) error
	DeleteCart(ctx context.Context, userID types.ID) error
}

type Service struct {
	validate Validate
	repo     Repository
}

func New(val Validate, repo Repository) Service {
	return Service{validate: val, repo: repo}
}

func (s Service) AddToBasket(ctx context.Context, req AddToCartRequest) error {
	const op = "shoppingbasketapp.service.AddToBasket"

	if err := s.validate.ValidateAddToCart(req); err != nil {
		logger.L().Error("shoppingbasket-service-AddToBasket", "error", err)
		return err
	}

	return s.repo.AddItem(ctx, req.UserID, entity.Item{
		ProductID: req.ProductID,
		Quantity:  req.Quantity,
		Price:     req.Price,
		Name:      req.Name,
		AddedAt:   time.Now().UnixNano(),
	})
}

func (s Service) GetCart(ctx context.Context, userID types.ID) (GetCartResponse, error) {
	const op = "shoppingbasketapp.service.GetCart"
	if userID < 1 {
		logger.L().Error("shoppingbasket-service-GetCart", "error", "user id must be greater than 1")
		return GetCartResponse{}, richerror.New(op).WithKind(richerror.KindInvalid).WithMessage("invalid user id")
	}

	res, err := s.repo.GetCart(ctx, userID)
	if err != nil {
		logger.L().Error("shoppingbasket-service-GetCart", "error", err)
		return GetCartResponse{}, richerror.New(op).WithErr(err)
	}

	return GetCartResponse{
		UserID:     res.UserID,
		Items:      res.Items,
		TotalPrice: res.TotalPrice,
		CreatedAt:  res.CreatedAt,
		ExpireAt:   res.ExpireAt,
	}, nil
}

func (s Service) RemoveFromCart(ctx context.Context, req RemoveFromCartRequest) error {
	const op = "shoppingbaskerapp.service.RemoveFromCart"

	if err := s.validate.ValidateRemoveFromCart(req); err != nil {
		logger.L().Error("shoppingbasket-service-RemoveFromCart", "error", err)
		return err
	}

	return s.repo.DeleteItem(ctx, req.UserID, req.ProductID)
}

func (s Service) UpdateQuantity(ctx context.Context, req UpdateQuantityRequest) error {
	const op = "shoppingbaskerapp.service.UpdateQuantity"

	if err := s.validate.ValidateUpdateQuantity(req); err != nil {
		logger.L().Error("shoppingbasket-service-UpdateQuantity", "error", err)
		return err
	}

	if req.Quantity == 0 {
		return s.repo.DeleteItem(ctx, req.UserID, req.ProductID)
	}

	return s.repo.UpdateQuantity(ctx, req.UserID, req.ProductID, req.Quantity)
}

func (s Service) ClearCart(ctx context.Context, userID types.ID) error {
	const op = "shoppingbaskerapp.service.ClearCart"

	if userID < 1 {
		logger.L().Error("shoppingbasket-service-ClearCart", "error", "user id must be greater than 1")
		return richerror.New(op).WithKind(richerror.KindInvalid).
			WithMessage("invalid user id")
	}

	return s.repo.DeleteCart(ctx, userID)
}
