package service

import (
	"context"

	"apskel-pos-be/internal/appcontext"
	"apskel-pos-be/internal/contract"
	"apskel-pos-be/internal/mappers"
	"apskel-pos-be/internal/processor"

	"github.com/google/uuid"
)

type PaymentMethodService interface {
	CreatePaymentMethod(ctx context.Context, contextInfo *appcontext.ContextInfo, req *contract.CreatePaymentMethodRequest) *contract.Response
	GetPaymentMethodByID(ctx context.Context, id uuid.UUID) *contract.Response
	ListPaymentMethods(ctx context.Context, req *contract.ListPaymentMethodsRequest) *contract.Response
	UpdatePaymentMethod(ctx context.Context, id uuid.UUID, req *contract.UpdatePaymentMethodRequest) *contract.Response
	DeletePaymentMethod(ctx context.Context, id uuid.UUID) *contract.Response
	GetActivePaymentMethodsByOrganization(ctx context.Context, organizationID uuid.UUID) *contract.Response
}

type PaymentMethodServiceImpl struct {
	paymentMethodProcessor processor.PaymentMethodProcessor
}

func NewPaymentMethodService(paymentMethodProcessor processor.PaymentMethodProcessor) PaymentMethodService {
	return &PaymentMethodServiceImpl{
		paymentMethodProcessor: paymentMethodProcessor,
	}
}

func (s *PaymentMethodServiceImpl) CreatePaymentMethod(ctx context.Context, contextInfo *appcontext.ContextInfo, req *contract.CreatePaymentMethodRequest) *contract.Response {
	modelReq := mappers.CreatePaymentMethodContractToModel(req)
	if modelReq.OrganizationID == uuid.Nil && contextInfo != nil {
		modelReq.OrganizationID = contextInfo.OrganizationID
	}

	response, err := s.paymentMethodProcessor.CreatePaymentMethod(ctx, modelReq)
	if err != nil {
		return contract.BuildErrorResponse([]*contract.ResponseError{
			contract.NewResponseError("PAYMENT_METHOD_CREATE_ERROR", "payment_method", err.Error()),
		})
	}

	contractResponse := mappers.PaymentMethodResponseToContract(response)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *PaymentMethodServiceImpl) GetPaymentMethodByID(ctx context.Context, id uuid.UUID) *contract.Response {
	response, err := s.paymentMethodProcessor.GetPaymentMethodByID(ctx, id)
	if err != nil {
		return contract.BuildErrorResponse([]*contract.ResponseError{
			contract.NewResponseError("PAYMENT_METHOD_NOT_FOUND", "payment_method", err.Error()),
		})
	}

	contractResponse := mappers.PaymentMethodResponseToContract(response)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *PaymentMethodServiceImpl) ListPaymentMethods(ctx context.Context, req *contract.ListPaymentMethodsRequest) *contract.Response {
	// Convert contract to model
	modelReq := mappers.ListPaymentMethodsContractToModel(req)

	// Process request
	response, err := s.paymentMethodProcessor.ListPaymentMethods(ctx, modelReq)
	if err != nil {
		return contract.BuildErrorResponse([]*contract.ResponseError{
			contract.NewResponseError("PAYMENT_METHOD_LIST_ERROR", "payment_method", err.Error()),
		})
	}

	// Convert model to contract
	contractResponse := mappers.ListPaymentMethodsResponseToContract(response)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *PaymentMethodServiceImpl) UpdatePaymentMethod(ctx context.Context, id uuid.UUID, req *contract.UpdatePaymentMethodRequest) *contract.Response {
	// Convert contract to model
	modelReq := mappers.UpdatePaymentMethodContractToModel(req)

	// Process request
	response, err := s.paymentMethodProcessor.UpdatePaymentMethod(ctx, id, modelReq)
	if err != nil {
		return contract.BuildErrorResponse([]*contract.ResponseError{
			contract.NewResponseError("PAYMENT_METHOD_UPDATE_ERROR", "payment_method", err.Error()),
		})
	}

	// Convert model to contract
	contractResponse := mappers.PaymentMethodResponseToContract(response)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *PaymentMethodServiceImpl) DeletePaymentMethod(ctx context.Context, id uuid.UUID) *contract.Response {
	err := s.paymentMethodProcessor.DeletePaymentMethod(ctx, id)
	if err != nil {
		return contract.BuildErrorResponse([]*contract.ResponseError{
			contract.NewResponseError("PAYMENT_METHOD_DELETE_ERROR", "payment_method", err.Error()),
		})
	}

	return contract.BuildSuccessResponse(map[string]string{"message": "Payment method deleted successfully"})
}

func (s *PaymentMethodServiceImpl) GetActivePaymentMethodsByOrganization(ctx context.Context, organizationID uuid.UUID) *contract.Response {
	responses, err := s.paymentMethodProcessor.GetActivePaymentMethodsByOrganization(ctx, organizationID)
	if err != nil {
		return contract.BuildErrorResponse([]*contract.ResponseError{
			contract.NewResponseError("PAYMENT_METHOD_LIST_ERROR", "payment_method", err.Error()),
		})
	}

	// Convert models to contracts
	contractResponses := make([]contract.PaymentMethodResponse, len(responses))
	for i, response := range responses {
		contractResponse := mappers.PaymentMethodResponseToContract(&response)
		if contractResponse != nil {
			contractResponses[i] = *contractResponse
		}
	}

	return contract.BuildSuccessResponse(contractResponses)
}
