package service

import (
	"context"

	"apskel-pos-be/internal/appcontext"
	"apskel-pos-be/internal/constants"
	"apskel-pos-be/internal/contract"
	"apskel-pos-be/internal/processor"
	"apskel-pos-be/internal/transformer"

	"github.com/google/uuid"
)

type ProductVariantService interface {
	CreateProductVariant(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateProductVariantRequest) *contract.Response
	UpdateProductVariant(ctx context.Context, id uuid.UUID, req *contract.UpdateProductVariantRequest) *contract.Response
	DeleteProductVariant(ctx context.Context, id uuid.UUID) *contract.Response
	GetProductVariantByID(ctx context.Context, id uuid.UUID) *contract.Response
	GetProductVariantsByProductID(ctx context.Context, productID uuid.UUID) *contract.Response
}

type ProductVariantServiceImpl struct {
	productVariantProcessor processor.ProductVariantProcessor
}

func NewProductVariantService(productVariantProcessor processor.ProductVariantProcessor) *ProductVariantServiceImpl {
	return &ProductVariantServiceImpl{
		productVariantProcessor: productVariantProcessor,
	}
}

func (s *ProductVariantServiceImpl) CreateProductVariant(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateProductVariantRequest) *contract.Response {
	modelReq := transformer.CreateProductVariantRequestToModel(req)

	variantResponse, err := s.productVariantProcessor.CreateProductVariant(ctx, modelReq)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductVariantServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponse := transformer.ProductVariantModelResponseToResponse(variantResponse)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *ProductVariantServiceImpl) UpdateProductVariant(ctx context.Context, id uuid.UUID, req *contract.UpdateProductVariantRequest) *contract.Response {
	modelReq := transformer.UpdateProductVariantRequestToModel(req)

	variantResponse, err := s.productVariantProcessor.UpdateProductVariant(ctx, id, modelReq)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductVariantServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponse := transformer.ProductVariantModelResponseToResponse(variantResponse)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *ProductVariantServiceImpl) DeleteProductVariant(ctx context.Context, id uuid.UUID) *contract.Response {
	err := s.productVariantProcessor.DeleteProductVariant(ctx, id)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductVariantServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	return contract.BuildSuccessResponse(map[string]interface{}{
		"message": "Product variant deleted successfully",
	})
}

func (s *ProductVariantServiceImpl) GetProductVariantByID(ctx context.Context, id uuid.UUID) *contract.Response {
	variantResponse, err := s.productVariantProcessor.GetProductVariantByID(ctx, id)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductVariantServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponse := transformer.ProductVariantModelResponseToResponse(variantResponse)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *ProductVariantServiceImpl) GetProductVariantsByProductID(ctx context.Context, productID uuid.UUID) *contract.Response {
	variants, err := s.productVariantProcessor.GetProductVariantsByProductID(ctx, productID)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductVariantServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponses := transformer.ProductVariantsToResponses(variants)
	return contract.BuildSuccessResponse(contractResponses)
}
