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 ProductService interface {
	CreateProduct(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateProductRequest) *contract.Response
	UpdateProduct(ctx context.Context, id uuid.UUID, req *contract.UpdateProductRequest) *contract.Response
	DeleteProduct(ctx context.Context, id uuid.UUID) *contract.Response
	GetProductByID(ctx context.Context, id uuid.UUID) *contract.Response
	ListProducts(ctx context.Context, req *contract.ListProductsRequest) *contract.Response
}

type ProductServiceImpl struct {
	productProcessor processor.ProductProcessor
}

func NewProductService(productProcessor processor.ProductProcessor) *ProductServiceImpl {
	return &ProductServiceImpl{
		productProcessor: productProcessor,
	}
}

func (s *ProductServiceImpl) CreateProduct(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateProductRequest) *contract.Response {
	modelReq := transformer.CreateProductRequestToModel(apctx, req)

	productResponse, err := s.productProcessor.CreateProduct(ctx, modelReq)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponse := transformer.ProductModelResponseToResponse(productResponse)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *ProductServiceImpl) UpdateProduct(ctx context.Context, id uuid.UUID, req *contract.UpdateProductRequest) *contract.Response {
	modelReq := transformer.UpdateProductRequestToModel(req)

	productResponse, err := s.productProcessor.UpdateProduct(ctx, id, modelReq)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponse := transformer.ProductModelResponseToResponse(productResponse)
	return contract.BuildSuccessResponse(contractResponse)
}

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

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

func (s *ProductServiceImpl) GetProductByID(ctx context.Context, id uuid.UUID) *contract.Response {
	productResponse, err := s.productProcessor.GetProductByID(ctx, id)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponse := transformer.ProductModelResponseToResponse(productResponse)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *ProductServiceImpl) ListProducts(ctx context.Context, req *contract.ListProductsRequest) *contract.Response {
	// Build filters
	filters := make(map[string]interface{})
	if req.OrganizationID != nil {
		filters["organization_id"] = *req.OrganizationID
	}
	if req.CategoryID != nil {
		filters["category_id"] = *req.CategoryID
	}
	if req.BusinessType != "" {
		filters["business_type"] = req.BusinessType
	}
	if req.IsActive != nil {
		filters["is_active"] = *req.IsActive
	}
	if req.Search != "" {
		filters["search"] = req.Search
	}
	if req.MinPrice != nil {
		filters["price_min"] = *req.MinPrice
	}
	if req.MaxPrice != nil {
		filters["price_max"] = *req.MaxPrice
	}

	products, totalCount, err := s.productProcessor.ListProducts(ctx, filters, req.Page, req.Limit)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	// Convert to contract responses
	contractResponses := transformer.ProductsToResponses(products)

	// Calculate total pages
	totalPages := totalCount / req.Limit
	if totalCount%req.Limit > 0 {
		totalPages++
	}

	listResponse := &contract.ListProductsResponse{
		Products:   contractResponses,
		TotalCount: totalCount,
		Page:       req.Page,
		Limit:      req.Limit,
		TotalPages: totalPages,
	}

	return contract.BuildSuccessResponse(listResponse)
}
