// monorepo/cloud/maplefile-backend/internal/maplefile/repo/storageusageevent/delete.go
package storageusageevent

import (
	"context"
	"fmt"
	"time"

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

func (impl *storageUsageEventRepositoryImpl) DeleteByUserAndDay(ctx context.Context, userID gocql.UUID, eventDay time.Time) error {
	// Ensure event day is truncated to date only
	eventDay = eventDay.Truncate(24 * time.Hour)

	query := `DELETE FROM maplefile.storage_usage_events_by_user_id_and_event_day_with_asc_event_time
		WHERE user_id = ? AND event_day = ?`

	err := impl.Session.Query(query, userID, eventDay).WithContext(ctx).Exec()
	if err != nil {
		impl.Logger.Error("failed to delete storage usage events by user and day", zap.Error(err))
		return fmt.Errorf("failed to delete storage usage events: %w", err)
	}

	return nil
}

// DeleteByUserID deletes all storage usage events for a user (all days)
// Used for GDPR right-to-be-forgotten implementation
//
// NOTE: Because storage_usage_events table is partitioned by (user_id, event_day),
// we need to query to find all event_day values first, then delete each partition.
// For efficiency, we'll delete up to 2 years of data (should cover most reasonable usage).
func (impl *storageUsageEventRepositoryImpl) DeleteByUserID(ctx context.Context, userID gocql.UUID) error {
	// Delete events from the last 2 years (730 days)
	// This should cover all reasonable user data retention periods
	endDay := time.Now().Truncate(24 * time.Hour)
	startDay := endDay.Add(-730 * 24 * time.Hour) // 2 years ago

	impl.Logger.Info("Deleting storage usage events for user",
		zap.String("user_id", userID.String()),
		zap.Time("start_day", startDay),
		zap.Time("end_day", endDay))

	// Use batch delete for efficiency
	batch := impl.Session.NewBatch(gocql.LoggedBatch).WithContext(ctx)
	deletedDays := 0

	// Delete each day's partition
	for day := startDay; !day.After(endDay); day = day.Add(24 * time.Hour) {
		query := `DELETE FROM maplefile.storage_usage_events_by_user_id_and_event_day_with_asc_event_time
			WHERE user_id = ? AND event_day = ?`
		batch.Query(query, userID, day)
		deletedDays++

		// Execute batch every 100 days to avoid batch size limits
		if deletedDays%100 == 0 {
			if err := impl.Session.ExecuteBatch(batch); err != nil {
				impl.Logger.Error("failed to execute batch delete for storage usage events",
					zap.String("user_id", userID.String()),
					zap.Int("days_in_batch", 100),
					zap.Error(err))
				return fmt.Errorf("failed to delete storage usage events for user %s: %w", userID.String(), err)
			}
			// Create new batch for next set of days
			batch = impl.Session.NewBatch(gocql.LoggedBatch).WithContext(ctx)
		}
	}

	// Execute remaining batch
	if batch.Size() > 0 {
		if err := impl.Session.ExecuteBatch(batch); err != nil {
			impl.Logger.Error("failed to execute final batch delete for storage usage events",
				zap.String("user_id", userID.String()),
				zap.Int("days_in_final_batch", batch.Size()),
				zap.Error(err))
			return fmt.Errorf("failed to delete storage usage events for user %s: %w", userID.String(), err)
		}
	}

	impl.Logger.Info("✅ Deleted all storage usage events for user",
		zap.String("user_id", userID.String()),
		zap.Int("total_days_deleted", deletedDays))

	return nil
}
