import { TestStats, RunnerStats, SuiteStats } from '@wdio/reporter';
import { EVENTS, SLACK_REQUEST_TYPE } from './constants.js';
import { WebClientOptions, FilesUploadArguments, ChatPostMessageArguments, WebAPICallResult, FilesCompleteUploadExternalResponse } from '@slack/web-api';
import { IncomingWebhookDefaultArguments, IncomingWebhookSendArguments, IncomingWebhookResult } from '@slack/webhook';
import { Reporters } from '@wdio/types';

/**
 * Copyright (c) moroo
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

declare class TimeoutError extends Error {
    code: string;
    constructor(message: string);
}
type FilesUploadV2Response = WebAPICallResult & {
    files: FilesCompleteUploadExternalResponse[];
};
interface SlackWebClientOptions extends WebClientOptions {
    token: string;
}
interface SlackIncomingWebhookOptions extends IncomingWebhookDefaultArguments {
    webhook: string;
}
type TestResultType = 'passed' | 'failed' | 'pending' | 'skipped';
interface StateCount {
    passed: number;
    failed: number;
    skipped: number;
}
declare class CucumberStats extends SuiteStats {
    state: TestStats['state'];
}
interface EmojiSymbols {
    passed?: string;
    failed?: string;
    skipped?: string;
    pending?: string;
    start?: string;
    finished?: string;
    watch?: string;
}
interface SlackWebApiOptions extends SlackWebClientOptions {
    type: 'web-api';
    channel: string;
    /**
     * @deprecated This property is deprecated. Please use the inherited 'token' property instead. Will be removed in the next major version.
     */
    slackBotToken?: string;
    uploadScreenshotOfFailedCase?: boolean;
    notifyDetailResultThread?: boolean;
    filterForDetailResults?: TestResultType[];
    createScreenshotPayload?: (testStats: TestStats, screenshotBuffer: string | Buffer) => FilesUploadArguments;
    createResultDetailPayload?: (runnerStats: RunnerStats, stateCounts: StateCount) => ChatPostMessageArguments;
}
interface SlackWebhookOptions extends SlackIncomingWebhookOptions {
    type: 'webhook';
    /**
     * @deprecated This property is deprecated. Please use the inherited 'username' property instead. Will be removed in the next major version.
     */
    slackName?: string;
    /**
     * @deprecated This property is deprecated. Please use the inherited 'icon_url' property instead. Will be removed in the next major version.
     */
    slackIconUrl?: string;
}
type SlackOptions = SlackWebApiOptions | SlackWebhookOptions;
interface SlackReporterOptions extends Reporters.Options {
    slackOptions?: SlackOptions;
    emojiSymbols?: EmojiSymbols;
    title?: string;
    resultsUrl?: string;
    notifyFailedCase?: boolean;
    notifyTestStartMessage?: boolean;
    notifyTestFinishMessage?: boolean;
    useScenarioBasedStateCounts?: boolean;
    createStartPayload?: (runnerStats: RunnerStats) => ChatPostMessageArguments | IncomingWebhookSendArguments;
    createFailedTestPayload?: (testStats: TestStats) => ChatPostMessageArguments | IncomingWebhookSendArguments;
    createResultPayload?: (runnerStats: RunnerStats, stateCounts: StateCount) => ChatPostMessageArguments | IncomingWebhookSendArguments;
}
interface FilesUploadV2Options {
    waitForUpload?: boolean;
    timeout?: number;
    interval?: number;
}
type SlackRequestType = PostMessage | Upload | Send;
interface PostMessage {
    type: typeof SLACK_REQUEST_TYPE.WEB_API_POST_MESSAGE;
    payload: ChatPostMessageArguments;
    isDetailResult?: boolean;
}
interface Upload {
    type: typeof SLACK_REQUEST_TYPE.WEB_API_UPLOAD;
    payload: FilesUploadArguments;
    options?: FilesUploadV2Options;
}
interface Send {
    type: typeof SLACK_REQUEST_TYPE.WEBHOOK_SEND;
    payload: IncomingWebhookSendArguments;
}
declare global {
    namespace WebdriverIO {
        interface ReporterOption extends SlackReporterOptions {
        }
    }
    namespace NodeJS {
        interface Process {
            emit(event: typeof EVENTS.POST_MESSAGE, payload: ChatPostMessageArguments): boolean;
            emit(event: typeof EVENTS.UPLOAD, args: {
                payload: FilesUploadArguments;
                options?: FilesUploadV2Options;
            }): Promise<WebAPICallResult & {
                files: FilesCompleteUploadExternalResponse[];
            }>;
            emit(event: typeof EVENTS.SEND, payload: IncomingWebhookSendArguments): boolean;
            emit(event: typeof EVENTS.SCREENSHOT, args: {
                buffer: string | Buffer;
            }): boolean;
            emit(event: typeof EVENTS.RESULT, args: {
                result: WebAPICallResult | IncomingWebhookResult | (WebAPICallResult & {
                    files: FilesCompleteUploadExternalResponse[];
                }) | undefined;
                error: any;
            }): boolean;
            on(event: typeof EVENTS.POST_MESSAGE, listener: (payload: ChatPostMessageArguments) => Promise<WebAPICallResult>): this;
            on(event: typeof EVENTS.UPLOAD, listener: (args: {
                payload: FilesUploadArguments;
                options?: FilesUploadV2Options;
            }) => Promise<WebAPICallResult & {
                files: FilesCompleteUploadExternalResponse[];
            }>): this;
            on(event: typeof EVENTS.SEND, listener: (payload: IncomingWebhookSendArguments) => Promise<IncomingWebhookResult>): this;
            on(event: typeof EVENTS.SCREENSHOT, listener: (args: {
                buffer: string | Buffer;
            }) => void): this;
            once(event: typeof EVENTS.RESULT, listener: (args: {
                result: WebAPICallResult | IncomingWebhookResult | (WebAPICallResult & {
                    files: FilesCompleteUploadExternalResponse[];
                }) | undefined;
                error: any;
            }) => Promise<void>): this;
        }
    }
}

export { CucumberStats, type EmojiSymbols, type FilesUploadV2Options, type FilesUploadV2Response, type SlackIncomingWebhookOptions, type SlackOptions, type SlackReporterOptions, type SlackRequestType, type SlackWebApiOptions, type SlackWebClientOptions, type SlackWebhookOptions, type StateCount, type TestResultType, TimeoutError };
