package service

import (
	"apskel-pos-be/internal/contract"
	"apskel-pos-be/internal/processor"
	"apskel-pos-be/internal/transformer"
	"context"

	"github.com/google/uuid"
)

type CustomerService interface {
	CreateCustomer(ctx context.Context, req *contract.CreateCustomerRequest, organizationID uuid.UUID) (*contract.CustomerResponse, error)
	GetCustomer(ctx context.Context, customerID, organizationID uuid.UUID) (*contract.CustomerResponse, error)
	ListCustomers(ctx context.Context, query *contract.ListCustomersRequest, organizationID uuid.UUID) (*contract.PaginatedCustomerResponse, error)
	UpdateCustomer(ctx context.Context, customerID, organizationID uuid.UUID, req *contract.UpdateCustomerRequest) (*contract.CustomerResponse, error)
	DeleteCustomer(ctx context.Context, customerID, organizationID uuid.UUID) error
	SetDefaultCustomer(ctx context.Context, customerID, organizationID uuid.UUID) (*contract.CustomerResponse, error)
	GetDefaultCustomer(ctx context.Context, organizationID uuid.UUID) (*contract.CustomerResponse, error)
	EnsureDefaultCustomer(ctx context.Context, organizationID uuid.UUID) (*contract.CustomerResponse, error)
}

type CustomerServiceImpl struct {
	customerProcessor *processor.CustomerProcessor
}

func NewCustomerService(customerProcessor *processor.CustomerProcessor) *CustomerServiceImpl {
	return &CustomerServiceImpl{
		customerProcessor: customerProcessor,
	}
}

func (s *CustomerServiceImpl) CreateCustomer(ctx context.Context, req *contract.CreateCustomerRequest, organizationID uuid.UUID) (*contract.CustomerResponse, error) {
	modelReq := transformer.CreateCustomerRequestToModel(req)

	customerResponse, err := s.customerProcessor.CreateCustomer(ctx, modelReq, organizationID)
	if err != nil {
		return nil, err
	}

	contractResponse := transformer.CustomerModelToResponse(customerResponse)
	return contractResponse, nil
}

func (s *CustomerServiceImpl) GetCustomer(ctx context.Context, customerID, organizationID uuid.UUID) (*contract.CustomerResponse, error) {
	customerResponse, err := s.customerProcessor.GetCustomer(ctx, customerID, organizationID)
	if err != nil {
		return nil, err
	}

	contractResponse := transformer.CustomerModelToResponse(customerResponse)
	return contractResponse, nil
}

func (s *CustomerServiceImpl) ListCustomers(ctx context.Context, query *contract.ListCustomersRequest, organizationID uuid.UUID) (*contract.PaginatedCustomerResponse, error) {
	modelQuery := transformer.ListCustomersRequestToModel(query)

	customersResponse, err := s.customerProcessor.ListCustomers(ctx, modelQuery, organizationID)
	if err != nil {
		return nil, err
	}

	contractResponse := transformer.PaginatedCustomerResponseToContract(customersResponse)
	return contractResponse, nil
}

func (s *CustomerServiceImpl) UpdateCustomer(ctx context.Context, customerID, organizationID uuid.UUID, req *contract.UpdateCustomerRequest) (*contract.CustomerResponse, error) {
	modelReq := transformer.UpdateCustomerRequestToModel(req)

	customerResponse, err := s.customerProcessor.UpdateCustomer(ctx, customerID, organizationID, modelReq)
	if err != nil {
		return nil, err
	}

	contractResponse := transformer.CustomerModelToResponse(customerResponse)
	return contractResponse, nil
}

func (s *CustomerServiceImpl) DeleteCustomer(ctx context.Context, customerID, organizationID uuid.UUID) error {
	return s.customerProcessor.DeleteCustomer(ctx, customerID, organizationID)
}

func (s *CustomerServiceImpl) SetDefaultCustomer(ctx context.Context, customerID, organizationID uuid.UUID) (*contract.CustomerResponse, error) {
	customerResponse, err := s.customerProcessor.SetDefaultCustomer(ctx, customerID, organizationID)
	if err != nil {
		return nil, err
	}

	contractResponse := transformer.CustomerModelToResponse(customerResponse)
	return contractResponse, nil
}

func (s *CustomerServiceImpl) GetDefaultCustomer(ctx context.Context, organizationID uuid.UUID) (*contract.CustomerResponse, error) {
	customerResponse, err := s.customerProcessor.GetDefaultCustomer(ctx, organizationID)
	if err != nil {
		return nil, err
	}

	contractResponse := transformer.CustomerModelToResponse(customerResponse)
	return contractResponse, nil
}

func (s *CustomerServiceImpl) EnsureDefaultCustomer(ctx context.Context, organizationID uuid.UUID) (*contract.CustomerResponse, error) {
	customerResponse, err := s.customerProcessor.EnsureDefaultCustomer(ctx, organizationID)
	if err != nil {
		return nil, err
	}

	contractResponse := transformer.CustomerModelToResponse(customerResponse)
	return contractResponse, nil
}
