import { W as WeightedCard, U as UserDBInterface, C as CourseDBInterface } from '../contentSource-BP9hznNV.js';
export { J as ActivityRecord, A as AdminDBInterface, v as AssignedCard, g as AssignedContent, u as AssignedCourse, t as AssignedTag, c as ClassroomDBInterface, F as ClassroomRegistration, E as ClassroomRegistrationDesignation, G as ClassroomRegistrationDoc, f as ContentNavigator, q as ContentSourceID, d as CourseInfo, K as CourseRegistration, s as CourseRegistrationDoc, b as CoursesDBInterface, O as NavigatorRole, P as NavigatorRoles, N as Navigators, j as ScheduledCard, H as SessionTrackingData, L as StrategyContribution, i as StudentClassroomDBInterface, h as StudyContentSource, k as StudySessionFailedItem, l as StudySessionFailedNewItem, m as StudySessionFailedReviewItem, S as StudySessionItem, n as StudySessionNewItem, o as StudySessionReviewItem, T as TeacherClassroomDBInterface, I as UserConfig, z as UserCourseSetting, y as UserCourseSettings, x as UserDBAuthenticator, a as UserDBReader, w as UserDBWriter, B as UsrCrsDataInterface, M as getCardOrigin, r as getStudySource, R as isFilter, Q as isGenerator, p as isReview } from '../contentSource-BP9hznNV.js';
export { D as DataLayerProvider } from '../dataLayerProvider-MDTxXq2l.js';
import { b as DocTypePrefixes, D as DocType, C as CardHistory, c as CardRecord, i as QuestionRecord } from '../types-legacy-DDY4N-Uq.js';
export { d as CardData, e as CourseListData, g as DataShapeData, f as DisplayableData, F as Field, G as GuestUsername, Q as QualifiedCardID, h as QuestionData, S as SkuilderCourseData, a as Tag, T as TagStub, l as log } from '../types-legacy-DDY4N-Uq.js';
import { DataShape, ParsedCard } from '@vue-skuilder/common';
import 'moment';

declare abstract class Loggable {
    protected abstract readonly _className: string;
    protected log(...args: unknown[]): void;
    protected error(...args: unknown[]): void;
}

/**
 * Shared context available to all filters in a pipeline.
 *
 * Built once per getWeightedCards() call and passed to each filter.
 * This avoids repeated lookups for common data like user ELO.
 */
interface FilterContext {
    /** User database interface */
    user: UserDBInterface;
    /** Course database interface */
    course: CourseDBInterface;
    /** User's global ELO score for this course */
    userElo: number;
}
/**
 * A filter that transforms a list of weighted cards.
 *
 * Filters are pure transforms - they receive cards and context,
 * and return a modified list of cards. No delegate wrapping,
 * no side effects beyond provenance tracking.
 *
 * ## Implementation Guidelines
 *
 * 1. **Append provenance**: Every filter should add a StrategyContribution
 *    entry documenting its decision for each card.
 *
 * 2. **Use multipliers**: Adjust scores by multiplying, not replacing.
 *    This ensures filter order doesn't matter.
 *
 * 3. **Score 0 for exclusion**: To exclude a card, set score to 0.
 *    Don't filter it out - let provenance show why it was excluded.
 *
 * 4. **Don't sort**: The Pipeline handles final sorting.
 *    Filters just transform scores.
 *
 * ## Example Implementation
 *
 * ```typescript
 * const myFilter: CardFilter = {
 *   name: 'My Filter',
 *   async transform(cards, context) {
 *     return cards.map(card => {
 *       const multiplier = computeMultiplier(card, context);
 *       const newScore = card.score * multiplier;
 *       return {
 *         ...card,
 *         score: newScore,
 *         provenance: [...card.provenance, {
 *           strategy: 'myFilter',
 *           strategyName: 'My Filter',
 *           strategyId: 'MY_FILTER',
 *           action: multiplier < 1 ? 'penalized' : 'passed',
 *           score: newScore,
 *           reason: 'Explanation of decision'
 *         }]
 *       };
 *     });
 *   }
 * };
 * ```
 */
interface CardFilter {
    /** Human-readable name for this filter */
    name: string;
    /**
     * Transform a list of weighted cards.
     *
     * @param cards - Cards to transform (already scored by generator)
     * @param context - Shared context (user, course, userElo, etc.)
     * @returns Transformed cards with updated scores and provenance
     */
    transform(cards: WeightedCard[], context: FilterContext): Promise<WeightedCard[]>;
}
/**
 * Factory function type for creating filters from configuration.
 *
 * Used by PipelineAssembler to instantiate filters from strategy documents.
 */
type CardFilterFactory<TConfig = unknown> = (config: TConfig) => CardFilter;

/**
 * Context available to generators when producing candidates.
 *
 * Built once per getWeightedCards() call by the Pipeline.
 */
interface GeneratorContext {
    /** User database interface */
    user: UserDBInterface;
    /** Course database interface */
    course: CourseDBInterface;
    /** User's global ELO score for this course */
    userElo: number;
}
/**
 * A generator that produces candidate cards with initial scores.
 *
 * Generators are the "source" stage of a navigation pipeline.
 * They query the database for eligible cards and assign initial
 * suitability scores based on their strategy (ELO proximity,
 * review urgency, fixed order, etc.).
 *
 * ## Implementation Guidelines
 *
 * 1. **Create provenance**: Each card should have a provenance entry
 *    with action='generated' documenting why it was selected.
 *
 * 2. **Score semantics**: Higher scores = more suitable for presentation.
 *    Scores should be in [0, 1] range for composability.
 *
 * 3. **Limit handling**: Respect the limit parameter, but may over-fetch
 *    internally if needed for scoring accuracy.
 *
 * 4. **Sort before returning**: Return cards sorted by score descending.
 *
 * ## Example Implementation
 *
 * ```typescript
 * const myGenerator: CardGenerator = {
 *   name: 'My Generator',
 *   async getWeightedCards(limit, context) {
 *     const candidates = await fetchCandidates(context.course, limit);
 *     return candidates.map(c => ({
 *       cardId: c.id,
 *       courseId: context.course.getCourseID(),
 *       score: computeScore(c, context),
 *       provenance: [{
 *         strategy: 'myGenerator',
 *         strategyName: 'My Generator',
 *         strategyId: 'MY_GENERATOR',
 *         action: 'generated',
 *         score: computeScore(c, context),
 *         reason: 'Explanation of selection'
 *       }]
 *     }));
 *   }
 * };
 * ```
 */
interface CardGenerator {
    /** Human-readable name for this generator */
    name: string;
    /**
     * Produce candidate cards with initial scores.
     *
     * @param limit - Maximum number of cards to return
     * @param context - Shared context (user, course, userElo, etc.)
     * @returns Cards sorted by score descending, with provenance
     */
    getWeightedCards(limit: number, context: GeneratorContext): Promise<WeightedCard[]>;
}
/**
 * Factory function type for creating generators from configuration.
 *
 * Used by PipelineAssembler to instantiate generators from strategy documents.
 */
type CardGeneratorFactory<TConfig = unknown> = (config: TConfig) => CardGenerator;

/**
 * Template literal type for strategy state document IDs.
 *
 * Format: `STRATEGY_STATE-{courseId}-{strategyKey}`
 */
type StrategyStateId = `${(typeof DocTypePrefixes)[DocType.STRATEGY_STATE]}::${string}::${string}`;
/**
 * Document storing strategy-specific state in the user database.
 *
 * Each strategy can persist its own state (user preferences, learned patterns,
 * temporal tracking, etc.) using this document type. The state is scoped to
 * a (user, course, strategy) tuple.
 *
 * ## Use Cases
 *
 * 1. **Explicit user preferences**: User configures tag filters, difficulty
 *    preferences, or learning goals. UI writes to strategy state.
 *
 * 2. **Learned/temporal state**: Strategy tracks patterns over time, e.g.,
 *    "when did I last introduce confusable concepts together?"
 *
 * 3. **Adaptive personalization**: Strategy infers user preferences from
 *    behavior and stores them for future sessions.
 *
 * ## Storage Location
 *
 * These documents live in the **user database**, not the course database.
 * They sync with the user's data across devices.
 *
 * ## Document ID Format
 *
 * `STRATEGY_STATE::{courseId}::{strategyKey}`
 *
 * Example: `STRATEGY_STATE::piano-basics::UserTagPreferenceFilter`
 *
 * @template T - The shape of the strategy-specific data payload
 */
interface StrategyStateDoc<T = unknown> {
    _id: StrategyStateId;
    _rev?: string;
    docType: DocType.STRATEGY_STATE;
    /**
     * The course this state applies to.
     */
    courseId: string;
    /**
     * Unique key identifying the strategy instance.
     * Typically the strategy class name (e.g., "UserTagPreferenceFilter",
     * "InterferenceMitigatorNavigator").
     *
     * If a course has multiple instances of the same strategy type with
     * different configurations, use a more specific key.
     */
    strategyKey: string;
    /**
     * Strategy-specific data payload.
     * Each strategy defines its own schema for this field.
     */
    data: T;
    /**
     * ISO timestamp of last update.
     * Use `moment.utc(updatedAt)` to parse into a Moment object.
     */
    updatedAt: string;
}
/**
 * Build the document ID for a strategy state document.
 *
 * @param courseId - The course ID
 * @param strategyKey - The strategy key (typically class name)
 * @returns The document ID in format `STRATEGY_STATE::{courseId}::{strategyKey}`
 */
declare function buildStrategyStateId(courseId: string, strategyKey: string): StrategyStateId;

declare function areQuestionRecords(h: CardHistory<CardRecord>): h is CardHistory<QuestionRecord>;
declare function isQuestionRecord(c: CardRecord): c is QuestionRecord;
declare function getCardHistoryID(courseID: string, cardID: string): PouchDB.Core.DocumentId;
declare function parseCardHistoryID(id: string): {
    courseID: string;
    cardID: string;
};
interface PouchDBError extends Error {
    error?: string;
    reason?: string;
}
declare function docIsDeleted(e: PouchDBError): boolean;

/**
 * Interface representing the result of a bulk import operation for a single card
 */
interface ImportResult {
    /** The original text input for the card */
    originalText: string;
    /** Status of the import operation */
    status: 'success' | 'error';
    /** Message describing the result or error */
    message: string;
    /** ID of the newly created card (only for success) */
    cardId?: string;
}
/**
 * Configuration for the bulk card processor
 */
interface BulkCardProcessorConfig {
    /** The data shape to use for the cards */
    dataShape: DataShape;
    /** The course code used for adding notes */
    courseCode: string;
    /** The username of the current user */
    userName: string;
}

/**
 * Processes multiple cards from bulk text input
 *
 * @param parsedCards - Array of parsed cards to import
 * @param courseDB - Course database interface
 * @param config - Configuration for the card processor
 * @returns Array of import results
 */
declare function importParsedCards(parsedCards: ParsedCard[], courseDB: CourseDBInterface, config: BulkCardProcessorConfig): Promise<ImportResult[]>;
/**
 * Validates the configuration for bulk card processing
 *
 * @param config - Configuration to validate
 * @returns Object with validation result and error message if any
 */
declare function validateProcessorConfig(config: Partial<BulkCardProcessorConfig>): {
    isValid: boolean;
    errorMessage?: string;
};

export { type BulkCardProcessorConfig, type CardFilter, type CardFilterFactory, type CardGenerator, type CardGeneratorFactory, CardHistory, CardRecord, CourseDBInterface, DocType, DocTypePrefixes, type FilterContext, type GeneratorContext, type ImportResult, Loggable, QuestionRecord, type StrategyStateDoc, type StrategyStateId, UserDBInterface, WeightedCard, areQuestionRecords, buildStrategyStateId, docIsDeleted, getCardHistoryID, importParsedCards, isQuestionRecord, parseCardHistoryID, validateProcessorConfig };
