import { MikroDB } from 'mikrodb';

/**
 * @description Storage interface for MikroAuth.
 */
interface StorageProvider {
    get(key: string): Promise<string | null>;
    set(key: string, value: string, expirySeconds?: number): Promise<void>;
    delete(key: string): Promise<void>;
    addToCollection(collectionKey: string, item: string, expirySeconds?: number): Promise<void>;
    removeFromCollection(collectionKey: string, item: string): Promise<void>;
    getCollection(collectionKey: string): Promise<string[]>;
    getCollectionSize(collectionKey: string): Promise<number>;
    removeOldestFromCollection(collectionKey: string): Promise<string | null>;
    findKeys(pattern: string): Promise<string[]>;
}
interface EmailMessage {
    from: string;
    to: string | string[];
    cc?: string | string[];
    bcc?: string | string[];
    subject: string;
    text: string;
    html: string;
}
interface EmailProvider {
    sendMail(message: EmailMessage): Promise<void>;
}
interface JwtPayload {
    sub: string;
    jti: string;
    iat?: number;
    exp?: number;
    lastLogin: number;
    metadata?: {
        ip?: string;
    };
}
interface JwtPayload {
    sub: string;
    username?: string;
    email?: string;
    role?: string;
    jti: string;
    iat?: number;
    exp?: number;
    lastLogin: number;
    metadata?: {
        ip?: string;
    };
}
interface RequestContext {
    body?: Record<string, any>;
    query?: Record<string, any>;
    headers?: Record<string, any>;
    ip?: string;
    log?: {
        error: (message: string, error: Error) => void;
        info?: (message: string, ...args: any[]) => void;
    };
    user?: {
        email: string;
    };
}
interface RequestContext {
    body?: Record<string, any>;
    query?: Record<string, any>;
    headers?: Record<string, any>;
    ip?: string;
    log?: {
        error: (message: string, error: Error) => void;
        info?: (message: string, ...args: any[]) => void;
    };
    user?: {
        email: string;
    };
}
interface MagicLinkRequest {
    email: string;
    ip?: string;
}
interface MagicLinkRequest {
    email: string;
    ip?: string;
}
interface VerifyTokenRequest {
    token: string;
    email: string;
}
interface VerifyTokenRequest {
    token: string;
    email: string;
}
interface SessionInfo {
    id: string;
    createdAt: number;
    lastLogin: number;
    lastUsed?: number;
    metadata?: {
        ip?: string;
    };
    isCurrentSession?: boolean;
}
interface SessionInfo {
    id: string;
    createdAt: number;
    lastLogin: number;
    lastUsed?: number;
    metadata?: {
        ip?: string;
    };
    isCurrentSession?: boolean;
}
interface TokenResponse {
    accessToken: string;
    refreshToken: string;
    exp: number;
    tokenType: string;
}
interface TokenResponse {
    accessToken: string;
    refreshToken: string;
    exp: number;
    tokenType: string;
}
type UserIdentity = {
    id: string;
    email: string;
    username: string;
    role: string;
};
type AuthConfiguration = {
    /**
     * The JSON Web Token secret to use.
     */
    jwtSecret: string;
    /**
     * How many seconds until a magic link expires?
     */
    magicLinkExpirySeconds: number;
    /**
     * How many seconds until the JSON Web Token expires?
     */
    jwtExpirySeconds: number;
    /**
     * How many seconds until the refresh token expires?
     */
    refreshTokenExpirySeconds: number;
    /**
     * How many sessions can be active?
     */
    maxActiveSessions: number;
    /**
     * The URL to the application we are authenticating towards.
     */
    appUrl: string;
    /**
     * Custom email templates.
     */
    templates: EmailTemplateConfiguration | null | undefined;
    /**
     * Use debug mode?
     */
    debug: boolean;
};
/**
 * @description Options for configuring MikroAuth.
 */
type AuthOptions = Partial<AuthConfiguration>;
type EmailConfiguration = {
    emailSubject: string;
    user: string;
    host: string;
    password: string;
    port: number;
    secure: boolean;
    maxRetries: number;
    debug: boolean;
};
type EmailOptions = Partial<EmailConfiguration>;
/**
 * @description Configuration for magic link email templates.
 * Defines the structure for text and HTML versions of authentication emails.
 */
type EmailTemplateConfiguration = {
    textVersion: MagicLinkTemplate;
    htmlVersion: MagicLinkTemplate;
};
/**
 * @description Function that generates the text and HTML version of the email.
 * @param magicLink - The authentication link to include in the email.
 * @param expiryMinutes - The number of minutes until the link expires.
 * @returns The formatted text or HTML content for the email.
 */
type MagicLinkTemplate = (magicLink: string, expiryMinutes: number) => string;

/**
 * @description MikroAuth is a dead-simple "Magic Link"
 * authentication service that works with your storage and email.
 */
declare class MikroAuth {
    private readonly config;
    private readonly email;
    private readonly storage;
    private readonly jwtService;
    private readonly templates;
    constructor(options: {
        auth: AuthOptions;
        email: EmailOptions;
    }, emailProvider?: EmailProvider, storageProvider?: StorageProvider);
    /**
     * @description Verify that we are not using defaults.
     */
    private checkIfUsingDefaultCredentialsInProduction;
    /**
     * @description Generates a secure token.
     */
    generateToken(email: string): string;
    /**
     * @description Generate a JWT for an authenticated user.
     */
    generateJsonWebToken(user: UserIdentity): string;
    /**
     * @description Generates a refresh token.
     */
    private generateRefreshToken;
    /**
     * @description Tracks a user session in storage.
     */
    private trackSession;
    /**
     * @description Creates the actual magic link URL, using the token and email.
     */
    private generateMagicLinkUrl;
    /**
     * @description Creates and sends a magic link to the user.
     */
    createMagicLink(params: MagicLinkRequest): Promise<{
        message: string;
    }>;
    /**
     * @description Verifies a magic link token and creates session tokens.
     */
    verifyToken(params: VerifyTokenRequest): Promise<TokenResponse>;
    /**
     * @description Refreshes an access token using a refresh token.
     */
    refreshAccessToken(refreshToken: string): Promise<TokenResponse>;
    /**
     * @description Verifies a JWT token.
     */
    verify(token: string): JwtPayload;
    /**
     * @description Logs out a user by revoking their session token.
     */
    logout(refreshToken: string): Promise<{
        message: string;
    }>;
    /**
     * @description Gets all active sessions for a user.
     */
    getSessions(request: RequestContext): Promise<{
        sessions: SessionInfo[];
    }>;
    /**
     * @description Revokes all active sessions for a user.
     */
    revokeSessions(request: RequestContext): Promise<{
        message: string;
    }>;
    /**
     * @description Middleware to authenticate requests with JWT tokens.
     */
    authenticate(request: any, next: (error?: Error) => void): void;
}

/**
 * @description MikroDB implementation of the StorageProvider interface.
 */
declare class MikroDBProvider implements StorageProvider {
    private readonly db;
    private readonly PREFIX_KV;
    private readonly PREFIX_COLLECTION;
    private readonly TABLE_NAME;
    constructor(mikroDb: MikroDB);
    /**
     * @description Start the MikroDB instance.
     */
    start(): Promise<void>;
    /**
     * @description Close the database connection and clean up resources.
     */
    close(): Promise<void>;
    /**
     * @description Set a value with optional expiry.
     */
    set(key: string, value: string, expirySeconds?: number): Promise<void>;
    /**
     * @description Get a value by key.
     */
    get(key: string): Promise<string | null>;
    /**
     * @description Delete a key.
     */
    delete(key: string): Promise<void>;
    /**
     * @description Add an item to a collection.
     */
    addToCollection(collectionKey: string, item: string, expirySeconds?: number): Promise<void>;
    /**
     * @description Remove an item from a collection.
     */
    removeFromCollection(collectionKey: string, item: string): Promise<void>;
    /**
     * @description Get all items in a collection.
     */
    getCollection(collectionKey: string): Promise<string[]>;
    /**
     * @description Get the number of items in a collection.
     */
    getCollectionSize(collectionKey: string): Promise<number>;
    /**
     * @description Remove and return the oldest item from a collection.
     */
    removeOldestFromCollection(collectionKey: string): Promise<string | null>;
    /**
     * @description Find keys matching a pattern.
     */
    findKeys(pattern: string): Promise<string[]>;
}

/**
 * @description Use MikroMail as the email provider.
 * @see https://github.com/mikaelvesavuori/mikromail
 */
declare class MikroMailProvider implements EmailProvider {
    private readonly email;
    private readonly sender;
    constructor(config: Record<string, any>);
    /**
     * @description Send an email using the MikroMail provider.
     */
    sendMail(message: EmailMessage): Promise<void>;
}

/**
 * @description Mock implementation of EmailProvider
 * for development and testing purposes.
 */
declare class InMemoryEmailProvider implements EmailProvider {
    private options?;
    private sentEmails;
    constructor(options?: {
        logToConsole?: boolean;
        onSend?: (message: EmailMessage) => void;
    } | undefined);
    /**
     * @description Send an email with the in-memory provider.
     */
    sendMail(message: EmailMessage): Promise<void>;
    /**
     * @description Get all sent emails (for testing purposes).
     */
    getSentEmails(): EmailMessage[];
    /**
     * @description Clear sent emails history (for testing purposes).
     */
    clearSentEmails(): void;
}

/**
 * @description In-memory implementation of the StorageProvider interface.
 */
declare class InMemoryStorageProvider implements StorageProvider {
    private data;
    private collections;
    private expiryEmitter;
    private expiryCheckInterval;
    constructor(checkIntervalMs?: number);
    /**
     * @description Clean up resources.
     */
    destroy(): void;
    /**
     * @description Check for and remove expired items.
     */
    private checkExpiredItems;
    /**
     * @description Set a value with optional expiry.
     */
    set(key: string, value: string, expirySeconds?: number): Promise<void>;
    /**
     * @description Get a value by key.
     */
    get(key: string): Promise<string | null>;
    /**
     * @description Delete a key.
     */
    delete(key: string): Promise<void>;
    /**
     * @description Add an item to a collection.
     */
    addToCollection(collectionKey: string, item: string, expirySeconds?: number): Promise<void>;
    /**
     * @description Remove an item from a collection.
     */
    removeFromCollection(collectionKey: string, item: string): Promise<void>;
    /**
     * @description Get all items in a collection.
     */
    getCollection(collectionKey: string): Promise<string[]>;
    /**
     * @description Get the number of items in a collection.
     */
    getCollectionSize(collectionKey: string): Promise<number>;
    /**
     * @description Remove and return the oldest item from a collection.
     */
    removeOldestFromCollection(collectionKey: string): Promise<string | null>;
    /**
     * @description Find keys matching a pattern (simple wildcard support).
     */
    findKeys(pattern: string): Promise<string[]>;
}

export { type EmailProvider, InMemoryEmailProvider, InMemoryStorageProvider, MikroAuth, MikroDBProvider, MikroMailProvider, type StorageProvider };
