/**
 * Exercise Repository Interface
 * 
 * Contract for exercise data access operations.
 * Implementations can use Prisma, caching, or other data sources.
 */

import type {
  Exercise,
  ExerciseType,
  ExerciseDifficulty,
  Prisma,
} from '@prisma/client';
import type { PaginatedResult, QueryOptions } from '@/core/types';

/**
 * Filter options for exercises
 */
export interface ExerciseFilterOptions {
  moduleId?: string;
  topicId?: string | null;
  type?: ExerciseType;
  difficulty?: ExerciseDifficulty;
  isPublished?: boolean;
  isAIGenerated?: boolean;
}

/**
 * Exercise with computed fields
 */
export interface ExerciseWithStats extends Exercise {
  totalAttempts: number;
  correctAttempts: number;
  successRate: number;
  averageTimeSpent: number;
}

/**
 * Exercise Repository Interface
 */
export interface IExerciseRepository {
  /**
   * Find exercise by ID
   */
  findById(
    id: string,
    options?: QueryOptions
  ): Promise<Exercise | null>;

  /**
   * Find exercise with all relations
   */
  findWithDetails(
    id: string,
    includeSolution?: boolean
  ): Promise<Exercise | null>;

  /**
   * List exercises with filtering and pagination
   */
  findMany(
    filters: ExerciseFilterOptions,
    page: number,
    limit: number
  ): Promise<PaginatedResult<Exercise>>;

  /**
   * Find exercises by module
   */
  findByModule(
    moduleId: string,
    options?: { includeUnpublished?: boolean }
  ): Promise<Exercise[]>;

  /**
   * Create new exercise
   */
  create(
    data: Prisma.ExerciseCreateInput
  ): Promise<Exercise>;

  /**
   * Update exercise
   */
  update(
    id: string,
    data: Prisma.ExerciseUpdateInput
  ): Promise<Exercise>;

  /**
   * Delete exercise (soft or hard)
   */
  delete(
    id: string,
    hardDelete?: boolean
  ): Promise<void>;

  /**
   * Count exercises matching filters
   */
  count(filters: ExerciseFilterOptions): Promise<number>;

  /**
   * Get exercise statistics
   */
  getStats(id: string): Promise<ExerciseWithStats | null>;

  /**
   * Find next exercise in module sequence
   */
  findNextInModule(
    moduleId: string,
    currentOrder: number
  ): Promise<Exercise | null>;

  /**
   * Find previous exercise in module sequence
   */
  findPreviousInModule(
    moduleId: string,
    currentOrder: number
  ): Promise<Exercise | null>;
}
