package mappers

import (
	"apskel-pos-be/internal/constants"
	"apskel-pos-be/internal/contract"
	"apskel-pos-be/internal/entities"
	"apskel-pos-be/internal/models"
)

func CreatePaymentMethodRequestToEntity(req *models.CreatePaymentMethodRequest) *entities.PaymentMethod {
	paymentMethod := &entities.PaymentMethod{
		OrganizationID: req.OrganizationID,
		Name:           req.Name,
		Type:           entities.PaymentMethodType(req.Type),
		Processor:      req.Processor,
		Configuration:  entities.Metadata(req.Configuration),
		IsActive:       true, // Default to active
	}

	if req.IsActive != nil {
		paymentMethod.IsActive = *req.IsActive
	}

	return paymentMethod
}

func UpdatePaymentMethodEntityFromRequest(entity *entities.PaymentMethod, req *models.UpdatePaymentMethodRequest) {
	if req.Name != nil {
		entity.Name = *req.Name
	}
	if req.Type != nil {
		entity.Type = entities.PaymentMethodType(*req.Type)
	}
	if req.Processor != nil {
		entity.Processor = req.Processor
	}
	if req.Configuration != nil {
		entity.Configuration = entities.Metadata(req.Configuration)
	}
	if req.IsActive != nil {
		entity.IsActive = *req.IsActive
	}
}

func PaymentMethodEntityToResponse(entity *entities.PaymentMethod) *models.PaymentMethodResponse {
	if entity == nil {
		return nil
	}

	return &models.PaymentMethodResponse{
		ID:             entity.ID,
		OrganizationID: entity.OrganizationID,
		Name:           entity.Name,
		Type:           constants.PaymentMethodType(entity.Type),
		Processor:      entity.Processor,
		Configuration:  map[string]interface{}(entity.Configuration),
		IsActive:       entity.IsActive,
		CreatedAt:      entity.CreatedAt,
		UpdatedAt:      entity.UpdatedAt,
	}
}

func PaymentMethodEntityToModel(entity *entities.PaymentMethod) *models.PaymentMethod {
	if entity == nil {
		return nil
	}

	return &models.PaymentMethod{
		ID:             entity.ID,
		OrganizationID: entity.OrganizationID,
		Name:           entity.Name,
		Type:           constants.PaymentMethodType(entity.Type),
		Processor:      entity.Processor,
		Configuration:  map[string]interface{}(entity.Configuration),
		IsActive:       entity.IsActive,
		CreatedAt:      entity.CreatedAt,
		UpdatedAt:      entity.UpdatedAt,
	}
}

func PaymentMethodModelToEntity(model *models.PaymentMethod) *entities.PaymentMethod {
	if model == nil {
		return nil
	}

	return &entities.PaymentMethod{
		ID:             model.ID,
		OrganizationID: model.OrganizationID,
		Name:           model.Name,
		Type:           entities.PaymentMethodType(model.Type),
		Processor:      model.Processor,
		Configuration:  entities.Metadata(model.Configuration),
		IsActive:       model.IsActive,
		CreatedAt:      model.CreatedAt,
		UpdatedAt:      model.UpdatedAt,
	}
}

// Contract to Model mappers
func CreatePaymentMethodContractToModel(req *contract.CreatePaymentMethodRequest) *models.CreatePaymentMethodRequest {
	return &models.CreatePaymentMethodRequest{
		OrganizationID: req.OrganizationID,
		OutletID:       req.OutletID,
		Name:           req.Name,
		Type:           constants.PaymentMethodType(req.Type),
		Processor:      req.Processor,
		Configuration:  req.Configuration,
		IsActive:       req.IsActive,
	}
}

func UpdatePaymentMethodContractToModel(req *contract.UpdatePaymentMethodRequest) *models.UpdatePaymentMethodRequest {
	var paymentMethodType *constants.PaymentMethodType
	if req.Type != nil {
		pmt := constants.PaymentMethodType(*req.Type)
		paymentMethodType = &pmt
	}

	return &models.UpdatePaymentMethodRequest{
		Name:          req.Name,
		Type:          paymentMethodType,
		Processor:     req.Processor,
		Configuration: req.Configuration,
		IsActive:      req.IsActive,
	}
}

func ListPaymentMethodsContractToModel(req *contract.ListPaymentMethodsRequest) *models.ListPaymentMethodsRequest {
	var paymentMethodType *constants.PaymentMethodType
	if req.Type != nil {
		pmt := constants.PaymentMethodType(*req.Type)
		paymentMethodType = &pmt
	}

	return &models.ListPaymentMethodsRequest{
		OrganizationID: req.OrganizationID,
		Type:           paymentMethodType,
		IsActive:       req.IsActive,
		Search:         req.Search,
		Page:           req.Page,
		Limit:          req.Limit,
	}
}

// Model to Contract mappers
func PaymentMethodResponseToContract(response *models.PaymentMethodResponse) *contract.PaymentMethodResponse {
	if response == nil {
		return nil
	}

	return &contract.PaymentMethodResponse{
		ID:             response.ID,
		OrganizationID: response.OrganizationID,
		Name:           response.Name,
		Type:           string(response.Type),
		Processor:      response.Processor,
		Configuration:  response.Configuration,
		IsActive:       response.IsActive,
		CreatedAt:      response.CreatedAt,
		UpdatedAt:      response.UpdatedAt,
	}
}

func ListPaymentMethodsResponseToContract(response *models.ListPaymentMethodsResponse) *contract.ListPaymentMethodsResponse {
	paymentMethods := make([]contract.PaymentMethodResponse, len(response.PaymentMethods))
	for i, pm := range response.PaymentMethods {
		contractPM := PaymentMethodResponseToContract(&pm)
		if contractPM != nil {
			paymentMethods[i] = *contractPM
		}
	}

	return &contract.ListPaymentMethodsResponse{
		PaymentMethods: paymentMethods,
		TotalCount:     response.TotalCount,
		Page:           response.Page,
		Limit:          response.Limit,
		TotalPages:     response.TotalPages,
	}
}
