import { setupWorker, } from '@jarrodek/amw';
import { RouteBuilder } from './RouteBuilder.js';
import { ModelingMock } from '../mocking/ModelingMock.js';
import { DataDomain } from '../modeling/DataDomain.js';
import { nanoid } from '../nanoid.js';
/**
 * SDK mocking utility for testing. Uses Service Workers to intercept HTTP requests
 * and provide mock responses for API calls.
 *
 * This class uses the `@jarrodek/amw` library to set up a Service Worker that intercepts
 * fetch requests matching the configured routes. Each method adds an intercept for a specific
 * API endpoint, returning either random generated data or custom responses.
 *
 * @example
 * ```typescript
 * import { SdkMock } from '@api-client/core/sdk/SdkMock.js';
 * import { StoreSdk } from '@api-client/core/sdk/StoreSdkWeb.js';
 *
 * const sdk = new StoreSdk('http://localhost:8080');
 * const mocker = new SdkMock({
 *   swPath: '/mockServiceWorker.js', // Path to the Service Worker script
 *   base: 'http://localhost:8080'    // Base URL matching the SDK
 * });
 *
 * // Initialize the Service Worker
 * await mocker.setup();
 *
 * // Add intercept - returns random organizations
 * await mocker.organizations.list();
 *
 * // Custom response with specific data
 * await mocker.organizations.create({
 *   response: {
 *     status: 201,
 *     headers: { 'Content-Type': 'application/json', 'X-Custom-Header': 'value' },
 *     body: JSON.stringify({ key: 'custom-id', name: 'Custom Org' })
 *   }
 * });
 *
 * // Control pagination in list responses
 * await mocker.groups.list({
 *   size: 10,        // Number of items to generate
 *   cursor: true     // Include pagination cursor
 * });
 *
 * // Error simulation
 * await mocker.users.me({
 *   response: {
 *     status: 404,
 *     headers: { 'Content-Type': 'application/json' },
 *     body: JSON.stringify({ error: 'Not found' })
 *   }
 * });
 *
 * // Remove all intercepts (keep Service Worker active)
 * await mocker.reset();
 *
 * // Stop and remove the Service Worker
 * await mocker.teardown();
 * ```
 *
 * @TODO: Add a in-memory state store so that mocks can maintain state across requests.
 * This way, operations like create, update, delete can affect subsequent list/read calls
 * and we can mimic the API behavior more closely.
 */
export class SdkMock {
    options;
    handler;
    gen = new ModelingMock();
    constructor(options) {
        this.options = options;
    }
    /**
     * Initializes the mock handler. It uses options provided in the constructor.
     * It has to be called before using any of the mock methods.
     */
    async setup() {
        this.handler = await setupWorker(this.options);
    }
    /**
     * Removes the mock worker and all intercepts.
     */
    async teardown() {
        await this.mock.stop();
    }
    /**
     * Removes all added intercepts.
     */
    async reset() {
        await this.mock.reset();
    }
    get mock() {
        if (!this.handler) {
            throw new Error('Mock handler not initialized. Call setup() first.');
        }
        return this.handler;
    }
    createCursorOption(init = {}) {
        if (init.cursor === false) {
            return undefined;
        }
        const hasCursor = init.cursor === true ? true : this.gen.faker.datatype.boolean();
        if (!hasCursor) {
            return undefined;
        }
        return this.gen.faker.internet.jwt();
    }
    createDefaultResponse(status, headers, body, userConfig) {
        let respond;
        if (userConfig?.response) {
            // user config takes precedence
            respond = userConfig.response;
        }
        else {
            respond = {};
        }
        // Set defaults if not provided in user config
        if (!respond.status) {
            respond.status = status;
        }
        // only set headers if the user didn't configure the response only.
        // The user may want to remove default headers.
        if (!userConfig || !userConfig.response) {
            respond.headers = headers;
        }
        if (!respond.body && userConfig?.forceBody && body) {
            // when body is missing and forceBody is set, generate the body
            respond.body = (req) => body(req);
        }
        else if (body && (!userConfig || !userConfig.response)) {
            // we set the body by default when the user config is missing
            respond.body = (req) => body(req);
        }
        return respond;
    }
    /**
     * Organization API mocks.
     */
    organizations = {
        /**
         * Adds an intercept to mock the `organizations.list()` method.
         * @param options Optional response configuration
         */
        list: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify({
            //     items: this.gen.organization.organizations(init?.size ?? 5),
            //     cursor: this.createCursorOption(init),
            //   } as ContextListResult<IOrganization>),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify({
                items: this.gen.organization.organizations(init?.size ?? 5),
                cursor: this.createCursorOption(init),
            }), init);
            await mock.add({
                match: {
                    uri: RouteBuilder.organizations(),
                    methods: ['GET'],
                },
                respond,
            }, options);
        },
        /**
         * Adds an intercept to mock the `organizations.create()` method.
         * @param options Optional response configuration
         */
        create: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify(this.gen.organization.organization()),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.organization.organization()), init);
            await mock.add({
                match: {
                    uri: RouteBuilder.organizations(),
                    methods: ['POST'],
                },
                respond,
            }, options);
        },
        invitations: {
            list: async (init, options) => {
                const { mock } = this;
                // const respond = init?.response ?? {
                //   status: 200,
                //   headers: { 'content-type': 'application/json' },
                //   body: JSON.stringify({
                //     items: this.gen.invitation.invitations(init?.size ?? 5),
                //     cursor: this.createCursorOption(init),
                //   } as ContextListResult<InvitationSchema>),
                // }
                const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
                    const obj = {
                        items: this.gen.invitation.invitations(init?.size ?? 5),
                        cursor: this.createCursorOption(init),
                    };
                    return JSON.stringify(obj);
                }, init);
                await mock.add({
                    match: {
                        uri: RouteBuilder.invitations(':oid'),
                        methods: ['GET'],
                    },
                    respond,
                }, options);
            },
            create: async (init, options) => {
                const { mock } = this;
                // const respond = init?.response ?? {
                //   status: 200,
                //   headers: { 'content-type': 'application/json' },
                //   body: JSON.stringify(this.gen.invitation.invitation()),
                // }
                const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.invitation.invitation()), init);
                await mock.add({
                    match: {
                        uri: RouteBuilder.invitations(':oid'),
                        methods: ['POST'],
                    },
                    respond,
                }, options);
            },
            findByToken: async (init, options) => {
                const { mock } = this;
                // const respond = init?.response ?? {
                //   status: 200,
                //   headers: { 'content-type': 'application/json' },
                //   body: JSON.stringify(this.gen.invitation.invitation()),
                // }
                const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.invitation.invitation()), init);
                await mock.add({
                    match: {
                        uri: RouteBuilder.findInvitation(),
                        methods: ['GET'],
                    },
                    respond,
                }, options);
            },
            decline: async (init, options) => {
                const { mock } = this;
                // const respond = init?.response ?? {
                //   status: 200,
                //   headers: { 'content-type': 'application/json' },
                //   body: JSON.stringify(this.gen.invitation.invitation()),
                // }
                const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.invitation.invitation()), init);
                await mock.add({
                    match: {
                        uri: RouteBuilder.declineInvitation(':oid', ':id'),
                        methods: ['POST'],
                    },
                    respond,
                }, options);
            },
            delete: async (init, options) => {
                const { mock } = this;
                // const respond = init?.response ?? {
                //   status: 200,
                //   headers: { 'content-type': 'application/json' },
                //   body: JSON.stringify(this.gen.invitation.invitation()),
                // }
                const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.invitation.invitation()), init);
                await mock.add({
                    match: {
                        uri: RouteBuilder.invitation(':oid', ':id'),
                        methods: ['DELETE'],
                    },
                    respond,
                }, options);
            },
            patch: async (init, options) => {
                const { mock } = this;
                // const respond = init?.response ?? {
                //   status: 200,
                //   headers: { 'content-type': 'application/json' },
                //   body: JSON.stringify(this.gen.invitation.invitation()),
                // }
                const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.invitation.invitation()), init);
                await mock.add({
                    match: {
                        uri: RouteBuilder.invitation(':oid', ':id'),
                        methods: ['PATCH'],
                    },
                    respond,
                }, options);
            },
            resend: async (init, options) => {
                const { mock } = this;
                // const respond = init?.response ?? {
                //   status: 200,
                //   headers: { 'content-type': 'application/json' },
                //   body: JSON.stringify(this.gen.invitation.invitation()),
                // }
                const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.invitation.invitation()), init);
                await mock.add({
                    match: {
                        uri: RouteBuilder.resendInvitation(':oid', ':id'),
                        methods: ['PUT'],
                    },
                    respond,
                }, options);
            },
        },
        users: {
            list: async (init, options) => {
                const { mock } = this;
                // const respond = init?.response ?? {
                //   status: 200,
                //   headers: { 'content-type': 'application/json' },
                //   body: JSON.stringify({
                //     items: this.gen.users.users(init?.size ?? 5),
                //     cursor: this.createCursorOption(init),
                //   } as ContextListResult<IUser>),
                // }
                const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
                    const obj = {
                        items: this.gen.users.users(init?.size ?? 5),
                        cursor: this.createCursorOption(init),
                    };
                    return JSON.stringify(obj);
                }, init);
                await mock.add({
                    match: {
                        uri: RouteBuilder.organizationUsers(':oid'),
                        methods: ['GET'],
                    },
                    respond,
                }, options);
            },
            read: async (init, options) => {
                const { mock } = this;
                // const respond = init?.response ?? {
                //   status: 200,
                //   headers: { 'content-type': 'application/json' },
                //   body: JSON.stringify(this.gen.users.user()),
                // }
                const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.users.user()), init);
                await mock.add({
                    match: {
                        uri: RouteBuilder.organizationUser(':oid', ':id'),
                        methods: ['GET'],
                    },
                    respond,
                }, options);
            },
            readBatch: async (init, options) => {
                const { mock } = this;
                const path = RouteBuilder.organizationUserBatch(':oid');
                const respond = init?.response ?? {
                    status: 200,
                    headers: { 'content-type': 'application/json' },
                    body: JSON.stringify({
                        items: this.gen.users.users(init?.size ?? 5),
                        cursor: this.createCursorOption(init),
                    }),
                };
                await mock.add({
                    match: {
                        uri: path,
                        methods: ['POST'],
                    },
                    respond,
                }, options);
            },
            activate: async (init, options) => {
                const { mock } = this;
                // const respond = init?.response ?? {
                //   status: 200,
                //   headers: { 'content-type': 'application/json' },
                //   body: JSON.stringify(this.gen.users.user()),
                // }
                const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.users.user()), init);
                await mock.add({
                    match: {
                        uri: RouteBuilder.organizationUserActivate(':oid', ':id'),
                        methods: ['POST'],
                    },
                    respond,
                }, options);
            },
            deactivate: async (init, options) => {
                const { mock } = this;
                // const respond = init?.response ?? {
                //   status: 200,
                //   headers: { 'content-type': 'application/json' },
                //   body: JSON.stringify(this.gen.users.user()),
                // }
                const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.users.user()), init);
                await mock.add({
                    match: {
                        uri: RouteBuilder.organizationUserDeactivate(':oid', ':id'),
                        methods: ['POST'],
                    },
                    respond,
                }, options);
            },
            delete: async (init, options) => {
                const { mock } = this;
                // const respond = init?.response ?? {
                //   status: 204,
                // }
                const respond = this.createDefaultResponse(204, undefined, undefined, init);
                await mock.add({
                    match: {
                        uri: RouteBuilder.organizationUser(':oid', ':id'),
                        methods: ['DELETE'],
                    },
                    respond,
                }, options);
            },
        },
    };
    /**
     * Group API mocks.
     */
    groups = {
        /**
         * Mocks the `groups.list()` method.
         * @param options Optional response customization.
         */
        list: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify({
            //     items: this.gen.group.groups(init?.size ?? 5),
            //     cursor: this.createCursorOption(init),
            //   } as ContextListResult<GroupSchema>),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
                const obj = {
                    items: this.gen.group.groups(init?.size ?? 5),
                    cursor: this.createCursorOption(init),
                };
                return JSON.stringify(obj);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.groups(':oid'),
                    methods: ['GET'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `groups.create()` method.
         * @param options Optional response customization.
         */
        create: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 201,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify(this.gen.group.group()),
            // }
            const respond = this.createDefaultResponse(201, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.group.group()), init);
            await mock.add({
                match: {
                    uri: RouteBuilder.groups(':oid'),
                    methods: ['POST'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `groups.update()` method.
         * @param options Optional response customization.
         */
        update: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify(this.gen.group.group()),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.group.group()), init);
            await mock.add({
                match: {
                    uri: RouteBuilder.group(':oid', ':key'),
                    methods: ['PATCH'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `groups.delete()` method.
         * @param options Optional response customization.
         */
        delete: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 204,
            // }
            const respond = this.createDefaultResponse(204, undefined, undefined, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.group(':oid', ':key'),
                    methods: ['DELETE'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `groups.addUsers()` method.
         */
        addUsers: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify(this.gen.group.group()),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.group.group()), init);
            await mock.add({
                match: {
                    uri: RouteBuilder.groupUsers(':oid', ':key'),
                    methods: ['POST'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `groups.removeUsers()` method.
         */
        removeUsers: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify(this.gen.group.group()),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.group.group()), init);
            await mock.add({
                match: {
                    uri: RouteBuilder.groupUsers(':oid', ':key'),
                    methods: ['DELETE'],
                },
                respond,
            }, options);
        },
    };
    /**
     * User API mocks.
     */
    users = {
        /**
         * Mocks the `user.me()` method.
         * @param options Optional response customization.
         */
        me: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify(this.gen.users.user()),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.users.user()), init);
            await mock.add({
                match: {
                    uri: RouteBuilder.usersMe(),
                    methods: ['GET'],
                },
                respond,
            }, options);
        },
    };
    /**
     * Files API mocks.
     */
    files = {
        /**
         * Mocks the `file.list()` method.
         */
        list: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify({
            //     items: this.gen.files.files(init?.size ?? 5),
            //     cursor: this.createCursorOption(init),
            //   } as ContextListResult<IFile>),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
                const obj = {
                    items: this.gen.files.files(init?.size ?? 5),
                    cursor: this.createCursorOption(init),
                };
                return JSON.stringify(obj);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.files(':oid'),
                    methods: ['GET'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `file.createMeta()` method.
         */
        createMeta: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 201,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify(this.gen.files.file()),
            // }
            const respond = this.createDefaultResponse(201, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.files.file()), init);
            await mock.add({
                match: {
                    uri: RouteBuilder.files(':oid'),
                    methods: ['POST'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `file.createMedia()` method.
         */
        createMedia: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            // }
            const respond = this.createDefaultResponse(200, undefined, undefined, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.fileMedia(':oid', ':id'),
                    methods: ['PUT'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `file.create()` method.
         */
        create: async (init, options) => {
            await this.files.createMeta(init, options);
            // When SDK's file.create() is called, it responds with
            // what the result of file.createMeta() would be.
            // Because of that, we don't need to configure the media request.
            await this.files.createMedia(undefined, options);
        },
        /**
         * Mocks the `file.createFolder()` method.
         */
        createFolder: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 201,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify(this.gen.files.folder()),
            // }
            const respond = this.createDefaultResponse(201, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.files.folder()), init);
            await mock.add({
                match: {
                    uri: RouteBuilder.files(':oid'),
                    methods: ['POST'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `file.read()` method.
         */
        read: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify(this.gen.files.file()),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.files.file()), init);
            await mock.add({
                match: {
                    uri: RouteBuilder.file(':oid', ':id'),
                    methods: ['GET'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `file.readMedia()` method.
         */
        readMedia: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: {
            //     'content-type': 'application/json',
            //     'x-version': `${this.gen.faker.number.int({ min: 1, max: 100 })}`,
            //   },
            //   body: JSON.stringify({ data: this.gen.faker.lorem.sentences() }),
            // }
            const respond = this.createDefaultResponse(200, {
                'content-type': 'application/json',
                'x-version': `${this.gen.faker.number.int({ min: 1, max: 100 })}`,
            }, () => JSON.stringify({ data: this.gen.faker.lorem.sentences() }), init);
            await mock.add({
                match: {
                    uri: RouteBuilder.fileMedia(':oid', ':id'),
                    methods: ['GET'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `file.readBulk()` method.
         */
        readBulk: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify({
            //     items: this.gen.files.files(init?.size ?? 5),
            //   } as IBulkOperationResult<IFile>),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
                const obj = {
                    items: this.gen.files.files(init?.size ?? 5),
                };
                return JSON.stringify(obj);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.filesBatch(':oid'),
                    methods: ['POST'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `file.patch()` method.
         */
        patch: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify(this.gen.files.file()),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.files.file()), init);
            await mock.add({
                match: {
                    uri: RouteBuilder.file(':oid', ':id'),
                    methods: ['PATCH'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `file.patchMedia()` method.
         */
        patchMedia: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify(this.gen.patch.mediaPatchRevision()),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.patch.mediaPatchRevision()), init);
            await mock.add({
                match: {
                    uri: RouteBuilder.fileMedia(':oid', ':id'),
                    methods: ['PATCH'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `file.delete()` method.
         */
        delete: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 204,
            // }
            const respond = this.createDefaultResponse(204, undefined, undefined, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.file(':oid', ':id'),
                    methods: ['DELETE'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `file.deleteBulk()` method.
         */
        deleteBulk: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 204,
            // }
            const respond = this.createDefaultResponse(204, undefined, undefined, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.files(':oid'),
                    methods: ['DELETE'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `file.patchUsers()` method.
         */
        patchUsers: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify(this.gen.files.file()),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.files.file()), init);
            await mock.add({
                match: {
                    uri: RouteBuilder.filesAccess(':oid', ':id'),
                    methods: ['PATCH'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `file.addUser()` method.
         */
        addUser: async (init, options) => {
            await this.files.patchUsers(init, options);
        },
        /**
         * Mocks the `file.removeUser()` method.
         */
        removeUser: async (init, options) => {
            await this.files.patchUsers(init, options);
        },
        /**
         * Mocks the `file.listUsers()` method.
         */
        listUsers: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify({
            //     items: this.gen.users.users(init?.size ?? 5),
            //     cursor: this.createCursorOption(init),
            //   } as ContextListResult<IUser>),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
                const obj = {
                    items: this.gen.users.users(init?.size ?? 5),
                    cursor: this.createCursorOption(init),
                };
                return JSON.stringify(obj);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.fileUsers(':oid', ':id'),
                    methods: ['GET'],
                },
                respond,
            }, options);
        },
        /**
         * Mocks the `file.breadcrumbs()` method.
         */
        breadcrumbs: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify({
            //     items: this.gen.files.fileBreadcrumbs(init?.size ?? 5),
            //     cursor: this.createCursorOption(init),
            //   } as ContextListResult<FileBreadcrumb>),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
                const obj = {
                    items: this.gen.files.fileBreadcrumbs(init?.size ?? 5),
                    cursor: this.createCursorOption(init),
                };
                return JSON.stringify(obj);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.fileBreadcrumbs(':oid', ':id'),
                    methods: ['GET'],
                },
                respond,
            }, options);
        },
    };
    /**
     * @deprecated Use `files` instead.
     */
    file = this.files;
    /**
     * Shared API mocks.
     */
    shared = {
        list: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify({
            //     items: this.gen.files.files(init?.size ?? 5),
            //     cursor: this.createCursorOption(init),
            //   } as ContextListResult<IFile>),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
                const obj = {
                    items: this.gen.files.files(init?.size ?? 5),
                    cursor: this.createCursorOption(init),
                };
                return JSON.stringify(obj);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.shared(':oid'),
                    methods: ['GET'],
                },
                respond,
            }, options);
        },
    };
    /**
     * Trash API mocks.
     */
    trash = {
        list: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 200,
            //   headers: { 'content-type': 'application/json' },
            //   body: JSON.stringify({
            //     items: this.gen.trash.trashEntries(init?.size ?? 5),
            //     cursor: this.createCursorOption(init),
            //   } as ContextListResult<TrashEntry>),
            // }
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
                const obj = {
                    items: this.gen.trash.trashEntries(init?.size ?? 5),
                    cursor: this.createCursorOption(init),
                };
                return JSON.stringify(obj);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.trash(':oid'),
                    methods: ['GET'],
                },
                respond,
            }, options);
        },
        delete: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 204,
            // }
            const respond = this.createDefaultResponse(204, undefined, undefined, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.trashBatchDelete(':oid'),
                    methods: ['DELETE'],
                },
                respond,
            }, options);
        },
        restore: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 204,
            // }
            const respond = this.createDefaultResponse(204, undefined, undefined, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.trashBatchRestore(':oid'),
                    methods: ['POST'],
                },
                respond,
            }, options);
        },
        empty: async (init, options) => {
            const { mock } = this;
            // const respond = init?.response ?? {
            //   status: 204,
            // }
            const respond = this.createDefaultResponse(204, undefined, undefined, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.trashEmpty(':oid'),
                    methods: ['DELETE'],
                },
                respond,
            }, options);
        },
    };
    /**
     * Trash Data Catalog mocks.
     */
    dataCatalog = {
        list: async (init, options) => {
            const { mock } = this;
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
                const obj = {
                    items: this.gen.dataCatalog.dataCatalogsWithVersion(init?.size ?? 5),
                    cursor: this.createCursorOption(init),
                };
                return JSON.stringify(obj);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.dataCatalog(),
                    methods: ['GET'],
                },
                respond,
            }, options);
        },
        listVersions: async (init, options) => {
            const { mock } = this;
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
                const obj = {
                    items: this.gen.dataCatalog.versionInfos(init?.size ?? 5),
                    cursor: this.createCursorOption(init),
                };
                return JSON.stringify(obj);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.dataCatalogEntryVersions(':id'),
                    methods: ['GET'],
                },
                respond,
            }, options);
        },
        publish: async (init, options) => {
            const { mock } = this;
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
                const obj = this.gen.dataCatalog.dataCatalog();
                const result = {
                    key: obj.key,
                    item: obj,
                    kind: obj.kind,
                };
                return JSON.stringify(result);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.dataCatalog(),
                    methods: ['POST'],
                },
                respond,
            }, options);
        },
        read: async (init, options) => {
            const { mock } = this;
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, (req) => {
                const obj = this.gen.dataCatalog.dataCatalog({ key: req.params.id });
                return JSON.stringify(obj);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.dataCatalogEntry(':id'),
                    methods: ['GET'],
                },
                respond,
            }, options);
        },
        deprecate: async (init, options) => {
            const { mock } = this;
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, (req) => {
                const obj = this.gen.dataCatalog.dataCatalog({ key: req.params.id });
                const result = {
                    key: obj.key,
                    item: obj,
                    kind: obj.kind,
                };
                return JSON.stringify(result);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.dataCatalogDeprecate(':id'),
                    methods: ['PUT'],
                },
                respond,
            }, options);
        },
        unpublish: async (init, options) => {
            const { mock } = this;
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, (req) => {
                const obj = this.gen.dataCatalog.dataCatalog({ key: req.params.id });
                const result = {
                    key: obj.key,
                    item: obj,
                    kind: obj.kind,
                };
                return JSON.stringify(result);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.dataCatalogUnpublish(':id'),
                    methods: ['PUT'],
                },
                respond,
            }, options);
        },
        publishVersion: async (init, options) => {
            const { mock } = this;
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, (req) => {
                const raw = req.body;
                const body = JSON.parse(raw);
                const result = {
                    key: body.key,
                    item: body,
                    kind: body.kind,
                };
                return JSON.stringify(result);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.dataCatalogEntryVersions(':id'),
                    methods: ['POST'],
                },
                respond,
            }, options);
        },
        readVersion: async (init, options) => {
            const { mock } = this;
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, (req) => {
                const obj = this.gen.dataCatalog.dataCatalogVersion({ key: req.params.vid, catalogKey: req.params.id });
                return JSON.stringify(obj);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.dataCatalogVersion(':id', ':vid'),
                    methods: ['GET'],
                },
                respond,
            }, options);
        },
        listDependencies: async (init, options) => {
            const { mock } = this;
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, (req) => {
                const requirements = JSON.parse(req.body);
                const items = [];
                for (const item of requirements.items) {
                    const domain = new DataDomain({
                        key: item.key,
                        info: { name: `Domain ${item.key}`, version: item.version },
                    });
                    items.push(domain.toJSON());
                }
                const obj = {
                    items: items,
                };
                return JSON.stringify(obj);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.dataCatalogDependencies(),
                    methods: ['POST'],
                },
                respond,
            }, options);
        },
        deprecateVersion: async (init, options) => {
            const { mock } = this;
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, (req) => {
                const obj = this.gen.dataCatalog.dataCatalogVersion({ key: req.params.vid, catalogKey: req.params.id });
                obj.deprecated = true;
                obj.deprecatedAt = this.gen.faker.date.past().getTime();
                obj.deprecatedBy = nanoid();
                const info = JSON.parse(req.body);
                obj.deprecationReason = info.reason;
                const result = {
                    key: obj.key,
                    item: obj,
                    kind: obj.kind,
                };
                return JSON.stringify(result);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.dataCatalogVersionDeprecate(':id', ':vid'),
                    methods: ['PUT'],
                },
                respond,
            }, options);
        },
        unpublishVersion: async (init, options) => {
            const { mock } = this;
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, (req) => {
                const obj = this.gen.dataCatalog.dataCatalogVersion({ key: req.params.vid, catalogKey: req.params.id });
                obj.unpublishedAt = this.gen.faker.date.past().getTime();
                obj.scope = 'private';
                const result = {
                    key: obj.key,
                    item: obj,
                    kind: obj.kind,
                };
                return JSON.stringify(result);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.dataCatalogVersionUnpublish(':id', ':vid'),
                    methods: ['PUT'],
                },
                respond,
            }, options);
        },
        checkPublicationStatus: async (init, options) => {
            const { mock } = this;
            const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
                const obj = this.gen.dataCatalog.dataCatalog();
                obj.versions = this.gen.dataCatalog.versionInfos(1);
                return JSON.stringify(obj);
            }, init);
            await mock.add({
                match: {
                    uri: RouteBuilder.dataCatalogStatus(':id'),
                    methods: ['GET'],
                },
                respond,
            }, options);
        },
    };
}
//# sourceMappingURL=SdkMock.js.map