import type { ConfigurationPlain, DesktopBrowserInfo, ChromeEmulationInfo, IOSDeviceInfo, IOSMultiDeviceInfo } from '@applitools/eyes';

type irrelevantToStorybook = 'waitBeforeScreenshots'
    | 'agentId'
    | 'captureStatusBar'
    | 'concurrentSessions'
    | 'connectionTimeout'
    | 'debugScreenshots'
    | 'defaultMatchSettings'
    | 'disableNMLUrlCache'
    | 'forceFullPageScreenshot'
    | 'hideCaret'
    | 'hideScrollbars'
    | 'hostApp'
    | 'hostAppInfo'
    | 'hostOS'
    | 'hostOSInfo'
    | 'ignoreBaseline'
    | 'ignoreCaret'
    | 'latestCommitInfo'
    | 'isDisabled'
    | 'matchTimeout'
    | 'mobileOptions'
    | 'removeSession'
    | 'rotation'
    | 'scaleRatio'
    | 'scrollRootElement'
    | 'sessionType'
    | 'stitchMode'
    | 'stitchOverlap'
    | 'viewportSize'
;


/**
 * Configuration options for Applitools Eyes Storybook integration.
 * 
 * This configuration can be specified in three ways:
 * - Command line arguments
 * - Environment variables (uppercase with APPLITOOLS_ prefix)
 * - applitools.config.js file (CommonJS module export)
 * 
 * Environment variables override applitools.config.js values.
 * 
 * @see https://applitools.com/tutorials/sdks/storybook/config
 */
export type ApplitoolsConfig = Omit<ConfigurationPlain, irrelevantToStorybook | 'waitBeforeCapture'> & {
    /** 
     * URL for Storybook instance.
     * @example 'http://localhost:9001'
     */
    storybookUrl?: string;

    /** 
     * Port to run Storybook on.
     * @default 9000
     */
    storybookPort?: number;

    /** 
     * Host to run Storybook on.
     * @default 'localhost'
     */
    storybookHost?: string;

    /** 
     * Path to Storybook's config folder.
     * @default '.storybook'
     */
    storybookConfigDir?: string;

    /** 
     * Path to Storybook's static files folder.
     */
    storybookStaticDir?: string;

    /** 
     * Whether to display Storybook output in console.
     */
    showStorybookOutput?: boolean;

    /** 
     * Set to true if running the SDK in Docker to resolve potential issues.
     * @default false
     */
    runInDocker?: boolean;

    /** 
     * Predicate function, string, or regex specifying which stories should be visually tested.
     * Visual baselines will be created only for specified components.
     * Function receives object with name, kind, storyTitle, and parameters properties.
     * 
     * @example
     * // Exclude stories with names starting with [SKIP]
     * ({name, kind, storyTitle, parameters}) => !/^\\[SKIP\\]/.test(name)
     * 
     * @default true (includes all stories)
     */
    include?: ((story: { name: string; kind: string; storyTitle?: string; parameters?: any }) => boolean) | string | RegExp;

    /** 
     * Specifies additional variations for all or some stories (e.g., RTL).
     */
    variations?: Record<string, any>;

    /** 
     * Time in milliseconds that Eyes-Storybook waits for Storybook to load.
     * For Storybook versions 2 and 3, this is also the acknowledgment time.
     * Recommended to use small values (e.g., 3000) for versions 2-3.
     * 
     * @default 60000
     */
    readStoriesTimeout?: number;

    /** 
     * Low-level options to send to puppeteer.launch().
     * Use with great care.
     * 
     * @example
     * { args: ['--no-sandbox'], headless: false, devtools: true }
     */
    puppeteerOptions?: Record<string, any>;

    /** 
     * Options to send to page.setExtraHTTPHeaders().
     * @see https://pptr.dev/api/puppeteer.page.setextrahttpheaders
     */
    puppeteerExtraHTTPHeaders?: Record<string, string>;

    /** 
     * When to consider navigation finished.
     * @default 'load'
     */
    navigationWaitUntil?: 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2';

    /** 
     * Cache all requests from browser for faster performance.
     * @default false
     */
    browserCacheRequests?: boolean;

    /**
     * Headers to override in all browser requests.
     * @default undefined
     */
    browserHeadersOverride?: Record<string, string>;

    /**
     * Timeout in milliseconds for all browser requests.
     * @default undefined
     */
    browserRequestsTimeout?: number;

    /**
     * Array of URL patterns to block requests to.
     * @default undefined
     */
    networkBlockPatterns?: string[];

    /** 
     * Array of browser configurations for screenshot generation.
     * Defines size and browser type for generated screenshots.
     * 
     * @default [{ width: 1024, height: 768, name: 'chrome' }]
     */
    browser?: (DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | IOSMultiDeviceInfo)[];

    /** 
     * Name for the environment in which the application under test is running.
     */
    envName?: string;

    /** 
     * Maximum number of tests that can run concurrently.
     * Default value is the allowed amount for free accounts.
     * For paid accounts, set to your account quota.
     * 
     * @default 5
     */
    testConcurrency?: number;

    /** 
     * Whether to display logs of the Eyes-Storybook plugin.
     * @default false
     */
    showLogs?: boolean;

    /** 
     * If tests failed or have visual differences, close with non-zero exit code.
     * @default true
     */
    exitcode?: boolean;

    /** 
     * Array of regions to ignore when comparing checkpoint with baseline screenshot.
     */
    ignoreRegions?: any[];

    /** 
     * Array of regions to consider as floating when comparing checkpoint with baseline.
     */
    floatingRegions?: any[];

    /** 
     * Array of regions to consider as match level Layout when comparing screenshots.
     */
    layoutRegions?: any[];

    /** 
     * Array of regions to consider as match level Strict when comparing screenshots.
     */
    strictRegions?: any[];

    /** 
     * Array of regions to consider as match level Content when comparing screenshots.
     */
    contentRegions?: any[];

    /** 
     * Array of regions to validate accessibility according to configured accessibilityValidation.
     */
    accessibilityRegions?: any[];

    /** 
     * Directory path for JSON results file.
     * If set, creates eyes.json file with test results.
     */
    jsonFilePath?: string;

    /** 
     * Directory path for TAP results file.
     * If set, creates eyes.tap file with test results.
     */
    tapFilePath?: string;

    /** 
     * Directory path for XUnit XML results file.
     * If set, creates eyes.xml file with test results.
     */
    xmlFilePath?: string;

    /**
     * Selector, function, or timeout to wait before capturing.
     * 
     * * number: Milliseconds to wait before capturing.
     * * string: CSS selector to wait for before capturing.
     * * function: Predicate or async function to wait for before capturing.
     * 
     * @example
     * waitBeforeCapture: '#container.ready',
     * 
     * @example
     * waitBeforeCapture: () => document.querySelector('#container.ready') !== null,
     * 
     * @example
     * waitBeforeCapture: 3_000
     * 
     * @see https://applitools.com/tutorials/sdks/storybook/component-config#waitBeforeCapture
     */
    waitBeforeCapture?: number | string | (() => boolean | Promise<boolean>);

    /**
     * Unique identifier for the batch of tests - set to the same value if you want to group tests together.
     */
    batchId?: string;

    /**
     * Name for the batch of tests - will appear in the Eyes dashboard.
     */
    batchName?: string;

    /**
     * Sequence name for the batch of tests - will appear in the Eyes dashboard (in the 'insights' page and in the batch details).
     */
    batchSequenceName?: string;

    /**
     * Name for the baseline branch - use it if you want to compare with a specific branch that is different from the current branch.
     *
     * @see for more information and recommendations regarding baseline branches, see the [documentation](https://applitools.com/tutorials/concepts/best-practices/branching).
     */
    baselineBranchName?: string;

    /**
     * Dry run - if true, no actual visual testing will be performed.
     * @default false
     */
    isDisabled?: boolean;

    /**
     * Whether to ignore the baseline when comparing with the checkpoint (will make all checkpoints `new`)
     * @default false
     */
    ignoreBaseline?: boolean

    /**
     * Settings for accessibility validation.
     */
    accessibilitySettings?: {
        /**
         * Level of accessibility validation to perform.
         */
        level?: 'AA' | 'AAA';

        /**
         * Array of specific accessibility guidelines to check.
         */
        guidelinesVersion?: "WCAG_2_0" | "WCAG_2_1";
    };

    /**
     * Whether to notify when the test is complete (requires to turn on notifications in the Applitools dashboard).
     * @see https://applitools.com/tutorials/integrations/chat-&-notifications/email
     */
    notifyOnCompletion?: boolean;

    /**
     * Whether to show browser logs in the test results.
     * @default false
     */
    showBrowserLogs?: boolean;

    /**
     * A string formatted as `<ShardIndex>/<TotalShards>` to enable test sharding (running tests in parallel).
     * @default undefined
     */
    shard?: string;

    /** 
     * The size of the Puppeteer browser's window.
     * This is the browser window which renders the stories originally (and opens at the size provided in the `viewportSize` parameter), and then a DOM snapshot is uploaded to the server, which renders this snapshot on all the browsers and sizes provided in the browser parameter.
     * 
     * Note: Stories will **not** be rendered and tested on this viewport size, unless you also include it in the `browser` parameter.
     */
    viewportSize?: ConfigurationPlain['viewportSize'];
}

export type configKeys = keyof ApplitoolsConfig;
