package service

import (
	"apskel-pos-be/internal/appcontext"
	"context"

	"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 VendorService interface {
	CreateVendor(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateVendorRequest) *contract.Response
	UpdateVendor(ctx context.Context, apctx *appcontext.ContextInfo, id uuid.UUID, req *contract.UpdateVendorRequest) *contract.Response
	DeleteVendor(ctx context.Context, apctx *appcontext.ContextInfo, id uuid.UUID) *contract.Response
	GetVendorByID(ctx context.Context, apctx *appcontext.ContextInfo, id uuid.UUID) *contract.Response
	ListVendors(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.ListVendorsRequest) *contract.Response
	GetActiveVendors(ctx context.Context, apctx *appcontext.ContextInfo) *contract.Response
}

type VendorServiceImpl struct {
	vendorProcessor processor.VendorProcessor
}

func NewVendorService(vendorProcessor processor.VendorProcessor) *VendorServiceImpl {
	return &VendorServiceImpl{
		vendorProcessor: vendorProcessor,
	}
}

func (s *VendorServiceImpl) CreateVendor(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateVendorRequest) *contract.Response {
	modelReq := transformer.CreateVendorRequestToModel(req)

	vendorResponse, err := s.vendorProcessor.CreateVendor(ctx, apctx.OrganizationID, modelReq)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.VendorServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponse := transformer.VendorModelResponseToResponse(vendorResponse)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *VendorServiceImpl) UpdateVendor(ctx context.Context, apctx *appcontext.ContextInfo, id uuid.UUID, req *contract.UpdateVendorRequest) *contract.Response {
	modelReq := transformer.UpdateVendorRequestToModel(req)

	vendorResponse, err := s.vendorProcessor.UpdateVendor(ctx, id, apctx.OrganizationID, modelReq)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.VendorServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponse := transformer.VendorModelResponseToResponse(vendorResponse)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *VendorServiceImpl) DeleteVendor(ctx context.Context, apctx *appcontext.ContextInfo, id uuid.UUID) *contract.Response {
	err := s.vendorProcessor.DeleteVendor(ctx, id, apctx.OrganizationID)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.VendorServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

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

func (s *VendorServiceImpl) GetVendorByID(ctx context.Context, apctx *appcontext.ContextInfo, id uuid.UUID) *contract.Response {
	vendorResponse, err := s.vendorProcessor.GetVendorByID(ctx, id, apctx.OrganizationID)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.VendorServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponse := transformer.VendorModelResponseToResponse(vendorResponse)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *VendorServiceImpl) ListVendors(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.ListVendorsRequest) *contract.Response {
	modelReq := transformer.ListVendorsRequestToModel(req)

	filters := make(map[string]interface{})
	if modelReq.Search != "" {
		filters["search"] = modelReq.Search
	}
	if modelReq.IsActive != nil {
		filters["is_active"] = *modelReq.IsActive
	}

	vendors, totalPages, err := s.vendorProcessor.ListVendors(ctx, apctx.OrganizationID, filters, modelReq.Page, modelReq.Limit)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.VendorServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponses := transformer.VendorModelResponsesToResponses(vendors)

	response := contract.ListVendorsResponse{
		Vendors:    contractResponses,
		TotalCount: len(contractResponses),
		Page:       modelReq.Page,
		Limit:      modelReq.Limit,
		TotalPages: totalPages,
	}

	return contract.BuildSuccessResponse(response)
}

func (s *VendorServiceImpl) GetActiveVendors(ctx context.Context, apctx *appcontext.ContextInfo) *contract.Response {
	vendorResponses, err := s.vendorProcessor.GetActiveVendors(ctx, apctx.OrganizationID)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.VendorServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponses := transformer.VendorModelResponsesToResponses(vendorResponses)
	return contract.BuildSuccessResponse(contractResponses)
}
