package ipanonymization

import (
	"context"
	"time"

	"go.uber.org/zap"

	"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/config"
	uc_collection "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/usecase/collection"
	uc_filemetadata "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/usecase/filemetadata"
	uc_user "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/usecase/user"
)

// AnonymizeOldIPsService handles the business logic for anonymizing old IP addresses
type AnonymizeOldIPsService interface {
	Execute(ctx context.Context) error
}

type anonymizeOldIPsServiceImpl struct {
	config                       *config.Config
	logger                       *zap.Logger
	userAnonymizeUseCase         uc_user.AnonymizeOldIPsUseCase
	collectionAnonymizeUseCase   uc_collection.AnonymizeOldIPsUseCase
	fileMetadataAnonymizeUseCase uc_filemetadata.AnonymizeOldIPsUseCase
}

// NewAnonymizeOldIPsService creates a new service for anonymizing old IP addresses
func NewAnonymizeOldIPsService(
	cfg *config.Config,
	logger *zap.Logger,
	userAnonymizeUseCase uc_user.AnonymizeOldIPsUseCase,
	collectionAnonymizeUseCase uc_collection.AnonymizeOldIPsUseCase,
	fileMetadataAnonymizeUseCase uc_filemetadata.AnonymizeOldIPsUseCase,
) AnonymizeOldIPsService {
	logger = logger.Named("AnonymizeOldIPsService")
	return &anonymizeOldIPsServiceImpl{
		config:                       cfg,
		logger:                       logger,
		userAnonymizeUseCase:         userAnonymizeUseCase,
		collectionAnonymizeUseCase:   collectionAnonymizeUseCase,
		fileMetadataAnonymizeUseCase: fileMetadataAnonymizeUseCase,
	}
}

// Execute runs the IP anonymization process for all tables
func (s *anonymizeOldIPsServiceImpl) Execute(ctx context.Context) error {
	if !s.config.Security.IPAnonymizationEnabled {
		s.logger.Info("IP anonymization is disabled, skipping")
		return nil
	}

	retentionDays := s.config.Security.IPAnonymizationRetentionDays
	cutoffDate := time.Now().AddDate(0, 0, -retentionDays)

	s.logger.Info("Starting IP anonymization process",
		zap.Int("retention_days", retentionDays),
		zap.Time("cutoff_date", cutoffDate))

	totalAnonymized := 0

	// Anonymize user tables using use-case
	userCount, err := s.userAnonymizeUseCase.Execute(ctx, cutoffDate)
	if err != nil {
		s.logger.Error("Failed to anonymize user tables",
			zap.Error(err),
			zap.Int("records_anonymized_before_error", totalAnonymized))
		return err
	}
	totalAnonymized += userCount

	// Anonymize collection tables using use-case
	collectionCount, err := s.collectionAnonymizeUseCase.Execute(ctx, cutoffDate)
	if err != nil {
		s.logger.Error("Failed to anonymize collection tables",
			zap.Error(err),
			zap.Int("records_anonymized_before_error", totalAnonymized))
		return err
	}
	totalAnonymized += collectionCount

	// Anonymize file tables using use-case
	fileCount, err := s.fileMetadataAnonymizeUseCase.Execute(ctx, cutoffDate)
	if err != nil {
		s.logger.Error("Failed to anonymize file tables",
			zap.Error(err),
			zap.Int("records_anonymized_before_error", totalAnonymized))
		return err
	}
	totalAnonymized += fileCount

	s.logger.Info("IP anonymization process completed successfully",
		zap.Int("total_rows_anonymized", totalAnonymized),
		zap.Int("user_rows", userCount),
		zap.Int("collection_rows", collectionCount),
		zap.Int("file_rows", fileCount))

	return nil
}
