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 CategoryService interface {
	CreateCategory(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateCategoryRequest) *contract.Response
	UpdateCategory(ctx context.Context, id uuid.UUID, req *contract.UpdateCategoryRequest) *contract.Response
	DeleteCategory(ctx context.Context, id uuid.UUID) *contract.Response
	GetCategoryByID(ctx context.Context, id uuid.UUID) *contract.Response
	ListCategories(ctx context.Context, req *contract.ListCategoriesRequest) *contract.Response
}

type CategoryServiceImpl struct {
	categoryProcessor processor.CategoryProcessor
}

func NewCategoryService(categoryProcessor processor.CategoryProcessor) *CategoryServiceImpl {
	return &CategoryServiceImpl{
		categoryProcessor: categoryProcessor,
	}
}

func (s *CategoryServiceImpl) CreateCategory(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateCategoryRequest) *contract.Response {
	modelReq := transformer.CreateCategoryRequestToModel(apctx, req)

	categoryResponse, err := s.categoryProcessor.CreateCategory(ctx, modelReq)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CategoryServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponse := transformer.CategoryModelResponseToResponse(categoryResponse)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *CategoryServiceImpl) UpdateCategory(ctx context.Context, id uuid.UUID, req *contract.UpdateCategoryRequest) *contract.Response {
	modelReq := transformer.UpdateCategoryRequestToModel(req)

	categoryResponse, err := s.categoryProcessor.UpdateCategory(ctx, id, modelReq)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CategoryServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponse := transformer.CategoryModelResponseToResponse(categoryResponse)
	return contract.BuildSuccessResponse(contractResponse)
}

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

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

func (s *CategoryServiceImpl) GetCategoryByID(ctx context.Context, id uuid.UUID) *contract.Response {
	categoryResponse, err := s.categoryProcessor.GetCategoryByID(ctx, id)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CategoryServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponse := transformer.CategoryModelResponseToResponse(categoryResponse)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *CategoryServiceImpl) ListCategories(ctx context.Context, req *contract.ListCategoriesRequest) *contract.Response {
	// Build filters
	filters := make(map[string]interface{})
	if req.OrganizationID != nil {
		filters["organization_id"] = *req.OrganizationID
	}
	if req.BusinessType != "" {
		filters["business_type"] = req.BusinessType
	}
	if req.Search != "" {
		filters["search"] = req.Search
	}

	categories, totalCount, err := s.categoryProcessor.ListCategories(ctx, filters, req.Page, req.Limit)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CategoryServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	// Convert to contract responses
	contractResponses := transformer.CategoriesToResponses(categories)

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

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

	return contract.BuildSuccessResponse(listResponse)
}
