package tenant

import (
	"context"

	"go.uber.org/zap"

	tenantusecase "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/usecase/tenant"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/logger"
)

// CreateTenantService handles tenant creation operations
type CreateTenantService interface {
	CreateTenant(ctx context.Context, input *tenantusecase.CreateTenantInput) (*tenantusecase.CreateTenantOutput, error)
}

type createTenantService struct {
	// Focused usecases
	validateSlugUC     *tenantusecase.ValidateTenantSlugUniqueUseCase
	createEntityUC     *tenantusecase.CreateTenantEntityUseCase
	saveTenantToRepoUC *tenantusecase.SaveTenantToRepoUseCase

	logger *zap.Logger
}

// NewCreateTenantService creates a new CreateTenantService
func NewCreateTenantService(
	validateSlugUC *tenantusecase.ValidateTenantSlugUniqueUseCase,
	createEntityUC *tenantusecase.CreateTenantEntityUseCase,
	saveTenantToRepoUC *tenantusecase.SaveTenantToRepoUseCase,
	logger *zap.Logger,
) CreateTenantService {
	return &createTenantService{
		validateSlugUC:     validateSlugUC,
		createEntityUC:     createEntityUC,
		saveTenantToRepoUC: saveTenantToRepoUC,
		logger:             logger.Named("create-tenant-service"),
	}
}

// CreateTenant orchestrates the tenant creation workflow
func (s *createTenantService) CreateTenant(ctx context.Context, input *tenantusecase.CreateTenantInput) (*tenantusecase.CreateTenantOutput, error) {
	// CWE-532: Use redacted tenant slug for logging
	s.logger.Info("creating tenant",
		logger.TenantSlugHash(input.Slug),
		logger.SafeTenantSlug("tenant_slug_redacted", input.Slug),
		zap.String("name", input.Name))

	// Step 1: Validate slug uniqueness (fail fast)
	if err := s.validateSlugUC.Execute(ctx, input.Slug); err != nil {
		// CWE-532: Use redacted tenant slug for logging
		s.logger.Error("slug validation failed",
			logger.TenantSlugHash(input.Slug),
			logger.SafeTenantSlug("tenant_slug_redacted", input.Slug),
			zap.Error(err))
		return nil, err
	}

	// Step 2: Create and validate tenant entity
	tenant, err := s.createEntityUC.Execute(input)
	if err != nil {
		// CWE-532: Use redacted tenant slug for logging
		s.logger.Error("entity creation failed",
			logger.TenantSlugHash(input.Slug),
			logger.SafeTenantSlug("tenant_slug_redacted", input.Slug),
			zap.Error(err))
		return nil, err
	}

	// Step 3: Save tenant to repository
	if err := s.saveTenantToRepoUC.Execute(ctx, tenant); err != nil {
		s.logger.Error("failed to save tenant",
			zap.String("tenant_id", tenant.ID),
			zap.Error(err))
		return nil, err
	}

	// CWE-532: Use redacted tenant slug for logging
	s.logger.Info("tenant created successfully",
		zap.String("tenant_id", tenant.ID),
		logger.TenantSlugHash(tenant.Slug),
		logger.SafeTenantSlug("tenant_slug_redacted", tenant.Slug))

	// Step 4: Build output
	return &tenantusecase.CreateTenantOutput{
		ID:        tenant.ID,
		Name:      tenant.Name,
		Slug:      tenant.Slug,
		Status:    string(tenant.Status),
		CreatedAt: tenant.CreatedAt,
	}, nil
}
