package site

import (
	"context"
	"fmt"

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

	domainsite "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/domain/site"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/dns"
)

// VerifySiteUseCase handles site verification business logic
type VerifySiteUseCase struct {
	repo        domainsite.Repository
	dnsVerifier *dns.Verifier
	logger      *zap.Logger
}

// ProvideVerifySiteUseCase creates a new VerifySiteUseCase
func ProvideVerifySiteUseCase(
	repo domainsite.Repository,
	dnsVerifier *dns.Verifier,
	logger *zap.Logger,
) *VerifySiteUseCase {
	return &VerifySiteUseCase{
		repo:        repo,
		dnsVerifier: dnsVerifier,
		logger:      logger,
	}
}

// VerifySiteInput is the input for verifying a site
// No input fields needed - verification is done via DNS TXT record lookup
type VerifySiteInput struct {
	// Empty struct - DNS verification uses the token stored in the site entity
}

// VerifySiteOutput is the output after verifying a site
type VerifySiteOutput struct {
	Success bool   `json:"success"`
	Status  string `json:"status"`
	Message string `json:"message"`
}

// Execute verifies a site using the verification token
func (uc *VerifySiteUseCase) Execute(
	ctx context.Context,
	tenantID gocql.UUID,
	siteID gocql.UUID,
	input *VerifySiteInput,
) (*VerifySiteOutput, error) {
	uc.logger.Info("executing verify site use case via DNS",
		zap.String("tenant_id", tenantID.String()),
		zap.String("site_id", siteID.String()))

	// Get site from repository
	site, err := uc.repo.GetByID(ctx, tenantID, siteID)
	if err != nil {
		uc.logger.Error("failed to get site", zap.Error(err))
		return nil, domainsite.ErrSiteNotFound
	}

	// Check if site is already verified
	if site.IsVerified {
		uc.logger.Info("site already verified",
			zap.String("site_id", siteID.String()))
		return &VerifySiteOutput{
			Success: true,
			Status:  site.Status,
			Message: "Site is already verified",
		}, nil
	}

	// Test mode sites don't need verification
	if site.IsTestMode() {
		uc.logger.Info("test mode site, skipping DNS verification",
			zap.String("site_id", siteID.String()))
		site.Verify()
		if err := uc.repo.Update(ctx, site); err != nil {
			uc.logger.Error("failed to update site", zap.Error(err))
			return nil, fmt.Errorf("failed to update site: %w", err)
		}
		return &VerifySiteOutput{
			Success: true,
			Status:  site.Status,
			Message: "Test mode site verified successfully",
		}, nil
	}

	// Perform DNS TXT record verification
	uc.logger.Info("performing DNS verification",
		zap.String("site_id", siteID.String()),
		zap.String("domain", site.Domain),
		zap.String("expected_token", site.VerificationToken))

	verified, err := uc.dnsVerifier.VerifyDomainOwnership(ctx, site.Domain, site.VerificationToken)
	if err != nil {
		uc.logger.Error("DNS verification failed",
			zap.String("site_id", siteID.String()),
			zap.String("domain", site.Domain),
			zap.Error(err))
		return nil, fmt.Errorf("DNS verification failed: %w", err)
	}

	if !verified {
		uc.logger.Warn("DNS verification record not found",
			zap.String("site_id", siteID.String()),
			zap.String("domain", site.Domain))
		return nil, fmt.Errorf("DNS TXT record not found. Please add the verification record to your domain's DNS settings")
	}

	// DNS verification successful - mark site as verified
	site.Verify()

	// Update in repository
	if err := uc.repo.Update(ctx, site); err != nil {
		uc.logger.Error("failed to update site", zap.Error(err))
		return nil, fmt.Errorf("failed to update site: %w", err)
	}

	uc.logger.Info("site verified successfully via DNS",
		zap.String("site_id", siteID.String()),
		zap.String("domain", site.Domain))

	return &VerifySiteOutput{
		Success: true,
		Status:  site.Status,
		Message: "Domain ownership verified successfully via DNS TXT record",
	}, nil
}
