package site

import (
	"context"

	"go.uber.org/zap"

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

// AuthenticateAPIKeyUseCase handles API key authentication
type AuthenticateAPIKeyUseCase struct {
	repo         domainsite.Repository
	apiKeyHasher apikey.Hasher
	logger       *zap.Logger
}

// ProvideAuthenticateAPIKeyUseCase creates a new AuthenticateAPIKeyUseCase
func ProvideAuthenticateAPIKeyUseCase(
	repo domainsite.Repository,
	apiKeyHasher apikey.Hasher,
	logger *zap.Logger,
) *AuthenticateAPIKeyUseCase {
	return &AuthenticateAPIKeyUseCase{
		repo:         repo,
		apiKeyHasher: apiKeyHasher,
		logger:       logger,
	}
}

// AuthenticateAPIKeyInput is the input for authenticating an API key
type AuthenticateAPIKeyInput struct {
	APIKey string
}

// AuthenticateAPIKeyOutput is the output after authenticating an API key
type AuthenticateAPIKeyOutput struct {
	Site *domainsite.Site
}

// Execute authenticates an API key and returns the associated site
func (uc *AuthenticateAPIKeyUseCase) Execute(ctx context.Context, input *AuthenticateAPIKeyInput) (*AuthenticateAPIKeyOutput, error) {
	// Hash the API key
	apiKeyHash := uc.apiKeyHasher.Hash(input.APIKey)

	// Lookup site by API key hash (from sites_by_apikey table)
	site, err := uc.repo.GetByAPIKeyHash(ctx, apiKeyHash)
	if err != nil {
		uc.logger.Debug("API key authentication failed", zap.Error(err))
		return nil, domainsite.ErrInvalidAPIKey
	}

	// Verify API key using constant-time comparison
	if !uc.apiKeyHasher.Verify(input.APIKey, site.APIKeyHash) {
		uc.logger.Warn("API key hash mismatch",
			zap.String("site_id", site.ID.String()))
		return nil, domainsite.ErrInvalidAPIKey
	}

	// Check if site can access API (allows pending sites for initial setup)
	if !site.CanAccessAPI() {
		uc.logger.Warn("site cannot access API",
			zap.String("site_id", site.ID.String()),
			zap.String("status", site.Status),
			zap.Bool("verified", site.IsVerified))
		return nil, domainsite.ErrSiteNotActive
	}

	uc.logger.Debug("API key authenticated successfully",
		zap.String("site_id", site.ID.String()),
		zap.String("domain", site.Domain))

	return &AuthenticateAPIKeyOutput{Site: site}, nil
}
