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 OrganizationService interface {
	CreateOrganization(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateOrganizationRequest) *contract.Response
	UpdateOrganization(ctx context.Context, id uuid.UUID, req *contract.UpdateOrganizationRequest) *contract.Response
	DeleteOrganization(ctx context.Context, id uuid.UUID) *contract.Response
	GetOrganizationByID(ctx context.Context, id uuid.UUID) *contract.Response
	ListOrganizations(ctx context.Context, req *contract.ListOrganizationsRequest) *contract.Response
}

type OrganizationServiceImpl struct {
	organizationProcessor processor.OrganizationProcessor
}

func NewOrganizationService(organizationProcessor processor.OrganizationProcessor) *OrganizationServiceImpl {
	return &OrganizationServiceImpl{
		organizationProcessor: organizationProcessor,
	}
}

func (s *OrganizationServiceImpl) CreateOrganization(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateOrganizationRequest) *contract.Response {
	modelReq := transformer.CreateOrganizationRequestToModel(req)

	organizationResponse, err := s.organizationProcessor.CreateOrganization(ctx, modelReq)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.OrganizationServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponse := transformer.CreateOrganizationResponseToContract(organizationResponse)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *OrganizationServiceImpl) UpdateOrganization(ctx context.Context, id uuid.UUID, req *contract.UpdateOrganizationRequest) *contract.Response {
	modelReq := transformer.UpdateOrganizationRequestToModel(req)

	organizationResponse, err := s.organizationProcessor.UpdateOrganization(ctx, id, modelReq)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.OrganizationServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponse := transformer.OrganizationModelResponseToResponse(organizationResponse)
	return contract.BuildSuccessResponse(contractResponse)
}

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

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

func (s *OrganizationServiceImpl) GetOrganizationByID(ctx context.Context, id uuid.UUID) *contract.Response {
	organizationResponse, err := s.organizationProcessor.GetOrganizationByID(ctx, id)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.OrganizationServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponse := transformer.OrganizationModelResponseToResponse(organizationResponse)
	return contract.BuildSuccessResponse(contractResponse)
}

func (s *OrganizationServiceImpl) ListOrganizations(ctx context.Context, req *contract.ListOrganizationsRequest) *contract.Response {
	filters := make(map[string]interface{})
	if req.PlanType != "" {
		filters["plan_type"] = req.PlanType
	}
	if req.Search != "" {
		filters["name"] = req.Search
	}

	organizations, totalCount, err := s.organizationProcessor.ListOrganizations(ctx, filters, req.Page, req.Limit)
	if err != nil {
		errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.OrganizationServiceEntity, err.Error())
		return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
	}

	contractResponses := make([]contract.OrganizationResponse, len(organizations))
	for i, org := range organizations {
		response := transformer.OrganizationModelResponseToResponse(&org)
		if response != nil {
			contractResponses[i] = *response
		}
	}

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

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

	return contract.BuildSuccessResponse(listResponse)
}
