import type {
	AddDataTableColumnDto,
	AddDataTableRowsDto,
	PublicApiCreateDataTableDto,
	PublicTestRunStatus,
	UpdateDataTableDto,
	UpdateDataTableColumnDto,
	UpdateDataTableRowDto,
	UpsertDataTableRowDto,
	UpdateSecurityPolicyDto,
	PublicCreateDestination,
	UpdateOidcConfigurationDto,
	UpdateOtelSettingsDto,
	TestOtelTraceDto,
	UpdateSamlConfigurationDto,
	UpdateLdapConfigurationDto,
	LdapSyncDto,
} from '@n8n/api-types';
import type { AuthenticatedRequest, TagEntity } from '@n8n/db';
import type { ICredentialDataDecryptedObject } from 'n8n-workflow';

import type { AuthlessRequest } from '@/requests';
import type { Risk } from '@/security-audit/types';

export type PaginatedRequest = AuthenticatedRequest<
	{},
	{},
	{},
	{
		limit?: number;
		cursor?: string;
		offset?: number;
		lastId?: string;
	}
>;
export declare namespace ExecutionRequest {
	type Retry = AuthenticatedRequest<{ id: string }, {}, { loadWorkflow?: boolean }, {}>;
}

export declare namespace TestRunRequest {
	// `id` is the workflow id (named `id` so `projectScope(..., 'workflow')`
	// resolves it from `req.params.id`); `runId` is the test run id.
	type GetMany = AuthenticatedRequest<
		{ id: string },
		{},
		{},
		{
			status?: PublicTestRunStatus;
			limit?: number;
			cursor?: string;
			offset?: number;
			lastId?: string;
		}
	>;
	type GetOne = AuthenticatedRequest<{ id: string; runId: string }>;
	type GetCases = AuthenticatedRequest<
		{ id: string; runId: string },
		{},
		{},
		{
			limit?: number;
			cursor?: string;
			offset?: number;
			lastId?: string;
		}
	>;
	type Create = AuthenticatedRequest<{ id: string }>;
	type Cancel = AuthenticatedRequest<{ id: string; runId: string }>;
}

export declare namespace TagRequest {
	type Create = AuthenticatedRequest<{}, {}, TagEntity>;
	type Get = AuthenticatedRequest<{ id: string }>;
	type Delete = Get;
	type Update = AuthenticatedRequest<{ id: string }, {}, TagEntity>;
}

export declare namespace CredentialTypeRequest {
	type Get = AuthenticatedRequest<{ credentialTypeName: string }, {}, {}, {}>;
}

export declare namespace WorkflowRequest {
	type Activate = AuthenticatedRequest<
		{ id: string },
		{},
		{ versionId?: string; name?: string; description?: string },
		{}
	>;
	type GetVersion = AuthenticatedRequest<{ id: string; versionId: string }, {}, {}, {}>;
}

export declare namespace PackageRequest {
	type Import = AuthenticatedRequest<
		{},
		{},
		{ projectId?: string; folderId?: string },
		Record<string, never>
	>;
}

export declare namespace UserRequest {
	export type Invite = AuthenticatedRequest<{}, {}, Array<{ email: string }>>;

	export type ResolveSignUp = AuthlessRequest<
		{},
		{},
		{},
		{ inviterId?: string; inviteeId?: string }
	>;

	export type SignUp = AuthenticatedRequest<
		{ id: string },
		{ inviterId?: string; inviteeId?: string }
	>;

	export type Delete = AuthenticatedRequest<
		{ id: string; email: string },
		{},
		{},
		{ transferId?: string; includeRole: boolean }
	>;

	export type Get = AuthenticatedRequest<
		{ id: string; email: string },
		{},
		{},
		{ limit?: number; offset?: number; cursor?: string; includeRole?: boolean }
	>;

	export type Reinvite = AuthenticatedRequest<{ id: string }>;

	export type Update = AuthlessRequest<
		{ id: string },
		{},
		{
			inviterId: string;
			firstName: string;
			lastName: string;
			password: string;
		}
	>;
}

export declare namespace CredentialRequest {
	type GetAll = AuthenticatedRequest<
		{},
		{},
		{},
		{ limit?: number; cursor?: string; offset?: number }
	>;

	type Get = AuthenticatedRequest<{ id: string }>;

	type Create = AuthenticatedRequest<
		{},
		{},
		{
			type: string;
			name: string;
			data: ICredentialDataDecryptedObject;
			projectId?: string;
			isResolvable?: boolean;
		},
		{}
	>;

	type Update = AuthenticatedRequest<
		{ id: string },
		{},
		{
			type?: string;
			name?: string;
			data?: ICredentialDataDecryptedObject;
			isGlobal?: boolean;
			isResolvable?: boolean;
			isPartialData?: boolean;
		},
		{}
	>;

	type Test = AuthenticatedRequest<{ id: string }, {}, {}, {}>;

	type Delete = AuthenticatedRequest<{ id: string }, {}, {}, Record<string, string>>;

	type Transfer = AuthenticatedRequest<{ id: string }, {}, { destinationProjectId: string }>;
}

export declare namespace InsightsRequest {
	type GetSummary = AuthenticatedRequest<
		{},
		{},
		{},
		{
			startDate?: string;
			endDate?: string;
			projectId?: string;
		}
	>;
}

export type OperationID = 'getUsers' | 'getUser';

type PaginationBase = { limit: number };

export type PaginationOffsetDecoded = PaginationBase & { offset: number };

export type PaginationCursorDecoded = PaginationBase & { lastId: string };

export type OffsetPagination = PaginationBase & { offset: number; numberOfTotalRecords: number };

export type CursorPagination = PaginationBase & { lastId: string; numberOfNextRecords: number };
export interface IRequired {
	required?: string[];
}
export interface IDependency {
	if?: { properties: {}; required?: string[] };
	then?: { allOf: IRequired[] };
}

export interface IJsonSchema {
	additionalProperties: boolean;
	type: 'object';
	properties: { [key: string]: { type: string } };
	allOf?: IDependency[];
	required: string[];
}

// ----------------------------------
//           /data-tables
// ----------------------------------

export declare namespace DataTableRequest {
	type List = AuthenticatedRequest<
		{},
		{},
		{},
		{
			limit?: number;
			cursor?: string;
			offset?: number;
			filter?: string;
			sortBy?: string;
		}
	>;

	type Create = AuthenticatedRequest<{}, {}, PublicApiCreateDataTableDto, {}>;

	type Get = AuthenticatedRequest<{ dataTableId: string }, {}, {}, {}>;

	type Update = AuthenticatedRequest<{ dataTableId: string }, {}, UpdateDataTableDto, {}>;

	type Delete = AuthenticatedRequest<{ dataTableId: string }, {}, {}, {}>;

	type GetRows = AuthenticatedRequest<
		{ dataTableId: string },
		{},
		{},
		{
			limit?: number;
			cursor?: string;
			offset?: number;
			filter?: string;
			sortBy?: string;
			search?: string;
		}
	>;

	type InsertRows = AuthenticatedRequest<{ dataTableId: string }, {}, AddDataTableRowsDto, {}>;

	type UpdateRows = AuthenticatedRequest<{ dataTableId: string }, {}, UpdateDataTableRowDto, {}>;

	type UpsertRow = AuthenticatedRequest<{ dataTableId: string }, {}, UpsertDataTableRowDto, {}>;

	type Clear = AuthenticatedRequest<{ dataTableId: string }, {}, {}, {}>;

	type DeleteRows = AuthenticatedRequest<
		{ dataTableId: string },
		{},
		{},
		{
			filter?: string;
			returnData?: string | boolean;
			dryRun?: string | boolean;
		}
	>;

	type ListColumns = AuthenticatedRequest<{ dataTableId: string }, {}, {}, {}>;

	type CreateColumn = AuthenticatedRequest<{ dataTableId: string }, {}, AddDataTableColumnDto, {}>;

	type DeleteColumn = AuthenticatedRequest<{ dataTableId: string; columnId: string }, {}, {}, {}>;

	type UpdateColumn = AuthenticatedRequest<
		{ dataTableId: string; columnId: string },
		{},
		UpdateDataTableColumnDto,
		{}
	>;
}

// ----------------------------------
//           /community-packages
// ----------------------------------

export declare namespace CommunityPackageRequest {
	type Install = AuthenticatedRequest<{}, {}, { name: string; version?: string }>;
	type List = AuthenticatedRequest;
	type Update = AuthenticatedRequest<{ name: string }, {}, { version?: string }>;
	type Uninstall = AuthenticatedRequest<{ name: string }>;
}

// ----------------------------------
//           /audit
// ----------------------------------

export declare namespace AuditRequest {
	type Generate = AuthenticatedRequest<
		{},
		{},
		{ additionalOptions?: { categories?: Risk.Category[]; daysAbandonedWorkflow?: number } }
	>;
}

// ----------------------------------
//        /settings/security-policy
// ----------------------------------

export declare namespace SecurityPolicyRequest {
	type Get = AuthenticatedRequest;
	type Update = AuthenticatedRequest<{}, {}, UpdateSecurityPolicyDto>;
}

export declare namespace LogStreamingRequest {
	type GetEventTypes = AuthenticatedRequest;
	type GetDestinations = AuthenticatedRequest;
	type GetDestination = AuthenticatedRequest<{ id: string }>;
	type CreateDestination = AuthenticatedRequest<{}, {}, PublicCreateDestination>;
	type UpdateDestination = AuthenticatedRequest<{ id: string }, {}, PublicCreateDestination>;
	type TestDestination = AuthenticatedRequest<{ id: string }>;
	type DeleteDestination = AuthenticatedRequest<{ id: string }>;
}

// ----------------------------------
//        /settings/sso/saml
// ----------------------------------

export declare namespace SsoSamlRequest {
	type Get = AuthenticatedRequest;
	type Update = AuthenticatedRequest<{}, {}, UpdateSamlConfigurationDto>;
}

// ----------------------------------
//        /settings/otel
// ----------------------------------

export declare namespace OtelSettingsRequest {
	type Get = AuthenticatedRequest;
	type Update = AuthenticatedRequest<{}, {}, UpdateOtelSettingsDto>;
	type Test = AuthenticatedRequest<{}, {}, TestOtelTraceDto>;
}

// ----------------------------------
//        /settings/ldap
// ----------------------------------

export declare namespace LdapRequest {
	type GetConfig = AuthenticatedRequest;
	type UpdateConfig = AuthenticatedRequest<{}, {}, UpdateLdapConfigurationDto>;
	type GetSync = PaginatedRequest;
	type RunSync = AuthenticatedRequest<{}, {}, LdapSyncDto>;
}

// ----------------------------------
//        /settings/sso/oidc
// ----------------------------------

export declare namespace SsoOidcRequest {
	type Get = AuthenticatedRequest;
	type Set = AuthenticatedRequest<{}, {}, UpdateOidcConfigurationDto>;
}
