package site

import (
	"context"
	"fmt"

	"github.com/gocql/gocql"
	"go.uber.org/zap"

	siteusecase "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/usecase/site"
)

// CreateSiteService handles site creation operations
type CreateSiteService interface {
	CreateSite(ctx context.Context, tenantID gocql.UUID, input *siteusecase.CreateSiteInput) (*siteusecase.CreateSiteOutput, error)
}

type createSiteService struct {
	// Focused usecases
	validateDomainUC      *siteusecase.ValidateDomainUseCase
	generateAPIKeyUC      *siteusecase.GenerateAPIKeyUseCase
	generateVerifyTokenUC *siteusecase.GenerateVerificationTokenUseCase
	createSiteEntityUC    *siteusecase.CreateSiteEntityUseCase
	saveSiteToRepoUC      *siteusecase.SaveSiteToRepoUseCase

	logger *zap.Logger
}

// NewCreateSiteService creates a new CreateSiteService
func NewCreateSiteService(
	validateDomainUC *siteusecase.ValidateDomainUseCase,
	generateAPIKeyUC *siteusecase.GenerateAPIKeyUseCase,
	generateVerifyTokenUC *siteusecase.GenerateVerificationTokenUseCase,
	createSiteEntityUC *siteusecase.CreateSiteEntityUseCase,
	saveSiteToRepoUC *siteusecase.SaveSiteToRepoUseCase,
	logger *zap.Logger,
) CreateSiteService {
	return &createSiteService{
		validateDomainUC:      validateDomainUC,
		generateAPIKeyUC:      generateAPIKeyUC,
		generateVerifyTokenUC: generateVerifyTokenUC,
		createSiteEntityUC:    createSiteEntityUC,
		saveSiteToRepoUC:      saveSiteToRepoUC,
		logger:                logger.Named("create-site-service"),
	}
}

// CreateSite orchestrates the site creation workflow
func (s *createSiteService) CreateSite(ctx context.Context, tenantID gocql.UUID, input *siteusecase.CreateSiteInput) (*siteusecase.CreateSiteOutput, error) {
	s.logger.Info("creating site",
		zap.String("tenant_id", tenantID.String()),
		zap.String("domain", input.Domain))

	// Step 1: Validate domain availability
	if err := s.validateDomainUC.Execute(ctx, input.Domain); err != nil {
		s.logger.Error("domain validation failed",
			zap.String("domain", input.Domain),
			zap.Error(err))
		return nil, err
	}

	// Step 2: Generate API key
	apiKeyResult, err := s.generateAPIKeyUC.Execute(input.TestMode)
	if err != nil {
		s.logger.Error("API key generation failed", zap.Error(err))
		return nil, fmt.Errorf("failed to generate API key: %w", err)
	}

	// Step 3: Generate verification token
	verificationToken, err := s.generateVerifyTokenUC.Execute()
	if err != nil {
		s.logger.Error("verification token generation failed", zap.Error(err))
		return nil, fmt.Errorf("failed to generate verification token: %w", err)
	}

	// Step 4: Create site entity (no plan tier - usage-based billing)
	site, err := s.createSiteEntityUC.Execute(&siteusecase.CreateSiteEntityInput{
		TenantID:          tenantID,
		Domain:            input.Domain,
		SiteURL:           input.SiteURL,
		APIKeyHash:        apiKeyResult.HashedKey,
		APIKeyPrefix:      apiKeyResult.Prefix,
		APIKeyLastFour:    apiKeyResult.LastFour,
		VerificationToken: verificationToken,
		IPAddress:         input.IPAddress,
	})
	if err != nil {
		s.logger.Error("failed to create site entity", zap.Error(err))
		return nil, err
	}

	// Step 5: Save site to repository
	if err := s.saveSiteToRepoUC.Execute(ctx, site); err != nil {
		s.logger.Error("failed to save site", zap.Error(err))
		return nil, err
	}

	s.logger.Info("site created successfully",
		zap.String("site_id", site.ID.String()),
		zap.String("domain", site.Domain))

	// Step 6: Build output
	return &siteusecase.CreateSiteOutput{
		ID:                site.ID.String(),
		Domain:            site.Domain,
		SiteURL:           site.SiteURL,
		APIKey:            apiKeyResult.PlaintextKey, // PLAINTEXT - only shown once!
		VerificationToken: verificationToken,
		Status:            site.Status,
		SearchIndexName:   site.SearchIndexName,
	}, nil
}
