import { Vitest, TestSpecification, TestProject, WorkspaceProject, ResolvedCoverageOptions } from 'vitest/node';
import { ReportBase, Visitor, ReportNode } from 'istanbul-lib-report';
import { ThrottledFunction } from './function/throttle.js';
import { TestResult } from 'vitest/dist/node.js';
import { experimental_UniversalStore } from 'storybook/internal/core-server';
import { API_HashEntry, PreviewAnnotation, StoryId, Options, StatusStoreByTypeId, TestProviderStoreById } from 'storybook/internal/types';
import { Report } from 'storybook/preview-api';

interface VitestError extends Error {
    VITEST_TEST_PATH?: string;
    VITEST_TEST_NAME?: string;
    stacks?: Array<{
        line: number;
        column: number;
        file: string;
        method: string;
    }>;
}
type ErrorLike = {
    message: string;
    name?: string;
    stack?: string;
    cause?: ErrorLike;
};
type RunTrigger = 'run-all' | 'global' | 'watch' | Extract<API_HashEntry['type'], string>;
type StoreState = {
    config: {
        coverage: boolean;
        a11y: boolean;
    };
    watching: boolean;
    cancelling: boolean;
    indexUrl: string | undefined;
    previewAnnotations: PreviewAnnotation[];
    fatalError: {
        message: string | undefined;
        error: ErrorLike;
    } | undefined;
    currentRun: {
        triggeredBy: RunTrigger | undefined;
        config: StoreState['config'];
        componentTestCount: {
            success: number;
            error: number;
        };
        a11yCount: {
            success: number;
            warning: number;
            error: number;
        };
        totalTestCount: number | undefined;
        storyIds: StoryId[] | undefined;
        startedAt: number | undefined;
        finishedAt: number | undefined;
        unhandledErrors: VitestError[];
        coverageSummary: {
            status: 'positive' | 'warning' | 'negative' | 'unknown';
            percentage: number;
        } | undefined;
    };
};
type TriggerRunEvent = {
    type: 'TRIGGER_RUN';
    payload: {
        storyIds?: string[] | undefined;
        triggeredBy: RunTrigger;
    };
};
type CancelRunEvent = {
    type: 'CANCEL_RUN';
};
type ToggleWatchingEvent = {
    type: 'TOGGLE_WATCHING';
    payload: {
        to: boolean;
    };
};
type FatalErrorEvent = {
    type: 'FATAL_ERROR';
    payload: {
        message: string;
        error: ErrorLike;
    };
};
type TestRunCompletedEvent = {
    type: 'TEST_RUN_COMPLETED';
    payload: StoreState['currentRun'];
};
type StoreEvent = TriggerRunEvent | CancelRunEvent | FatalErrorEvent | ToggleWatchingEvent | TestRunCompletedEvent;

declare class VitestManager {
    private testManager;
    vitest: Vitest | null;
    vitestStartupCounter: number;
    vitestRestartPromise: Promise<void> | null;
    runningPromise: Promise<any> | null;
    constructor(testManager: TestManager);
    startVitest({ coverage }: {
        coverage: boolean;
    }): Promise<void>;
    restartVitest({ coverage }: {
        coverage: boolean;
    }): Promise<void>;
    private resetGlobalTestNamePattern;
    private updateLastChanged;
    private fetchStories;
    private filterTestSpecifications;
    runTests(runPayload: TriggerRunEvent['payload']): Promise<void>;
    cancelCurrentRun(): Promise<void>;
    getStorybookTestSpecifications(): Promise<TestSpecification[]>;
    runAffectedTestsAfterChange(changedFilePath: string, event: 'change' | 'add'): Promise<void>;
    private getTestDependencies;
    registerVitestConfigListener(): Promise<void>;
    setupWatchers(): Promise<void>;
    isStorybookProject(project: TestProject | WorkspaceProject): boolean;
}

type TestManagerOptions = {
    storybookOptions: Options;
    store: experimental_UniversalStore<StoreState, StoreEvent>;
    componentTestStatusStore: StatusStoreByTypeId;
    a11yStatusStore: StatusStoreByTypeId;
    testProviderStore: TestProviderStoreById;
    onError?: (message: string, error: Error) => void;
    onReady?: () => void;
};
declare class TestManager {
    store: TestManagerOptions['store'];
    vitestManager: VitestManager;
    private componentTestStatusStore;
    private a11yStatusStore;
    private testProviderStore;
    private onReady?;
    storybookOptions: Options;
    private batchedTestCaseResults;
    constructor(options: TestManagerOptions);
    handleTriggerRunEvent(event: TriggerRunEvent): Promise<void>;
    handleCancelEvent(): Promise<void>;
    runTestsWithState({ storyIds, triggeredBy, callback, }: {
        storyIds?: string[];
        triggeredBy: RunTrigger;
        callback: () => Promise<void>;
    }): Promise<void>;
    onTestModuleCollected(collectedTestCount: number): void;
    onTestCaseResult(result: {
        storyId?: string;
        testResult: TestResult;
        reports?: Report[];
    }): void;
    /**
     * Throttled function to process batched test case results.
     *
     * This function:
     *
     * 1. Takes all batched test case results and clears the batch
     * 2. Updates the store state with new test counts (component tests and a11y tests)
     * 3. Adjusts the totalTestCount if more tests were run than initially anticipated
     * 4. Creates status objects for component tests and updates the component test status store
     * 5. Creates status objects for a11y tests (if any) and updates the a11y status store
     *
     * The throttling (500ms) is necessary as the channel would otherwise get overwhelmed with events,
     * eventually causing the manager and dev server to lose connection.
     */
    throttledFlushTestCaseResults: ThrottledFunction<() => void>;
    onTestRunEnd(endResult: {
        totalTestCount: number;
        unhandledErrors: VitestError[];
    }): void;
    onCoverageCollected(coverageSummary: StoreState['currentRun']['coverageSummary']): void;
    reportFatalError(message: string, error: Error | any): Promise<void>;
    static start(options: TestManagerOptions): Promise<TestManager>;
}

type StorybookCoverageReporterOptions = {
    testManager: TestManager;
    coverageOptions: ResolvedCoverageOptions<'v8'> | undefined;
};
declare class StorybookCoverageReporter extends ReportBase implements Partial<Visitor> {
    #private;
    constructor(opts: StorybookCoverageReporterOptions);
    onSummary(node: ReportNode): void;
}

export { StorybookCoverageReporterOptions, StorybookCoverageReporter as default };
