import { makeApi, Zodios, type ZodiosOptions } from "@zodios/core";
import { z } from "zod";

type MultiAssetModel = {
    _t: "MultiAsset";
    assets: Array<FileAssetModel | MultiAssetModel | NullAssetModel | TextAssetModel>;
    metadata: Record<
        string,
        | ClassificationMetadataModel
        | CountMetadataModel
        | DemographicMetadataModel
        | ImageDimensionMetadataModel
        | LocationMetadataModel
        | OriginalFilenameMetadataModel
        | PromptMetadataModel
        | SourceUrlMetadataModel
        | TextMetadataModel
        | TranscriptionMetadataModel
        | TranslatedPromptMetadataModel
    >;
    identifier: string;
};
type FileAssetModel = {
    _t: "FileAsset";
    fileName: string;
    metadata: Record<
        string,
        | ClassificationMetadataModel
        | CountMetadataModel
        | DemographicMetadataModel
        | ImageDimensionMetadataModel
        | LocationMetadataModel
        | OriginalFilenameMetadataModel
        | PromptMetadataModel
        | SourceUrlMetadataModel
        | TextMetadataModel
        | TranscriptionMetadataModel
        | TranslatedPromptMetadataModel
    >;
    identifier: string;
};
type ClassificationMetadataModel = {
    _t: "ClassificationMetadata";
    classification: string;
};
type CountMetadataModel = {
    _t: "CountMetadata";
    count: number;
};
type DemographicMetadataModel = {
    _t: "DemographicMetadata";
    demographics?: Record<string, Demographic> | undefined;
};
type Demographic = {
    value: string;
    confidence: number;
};
type ImageDimensionMetadataModel = {
    _t: "ImageDimensionMetadata";
    height?: number | undefined;
    width?: number | undefined;
};
type LocationMetadataModel = {
    _t: "LocationMetadata";
    x: number;
    y: number;
};
type OriginalFilenameMetadataModel = {
    _t: "OriginalFilenameMetadata";
    originalFilename: string;
};
type PromptMetadataModel = {
    _t: "PromptMetadata";
    prompt: string;
};
type SourceUrlMetadataModel = {
    _t: "SourceUrlMetadataModel";
    url: string;
};
type TextMetadataModel = {
    _t: "TextMetadata";
    text: string;
};
type TranscriptionMetadataModel = {
    _t: "TranscriptionMetadataModel";
    transcription: string;
};
type TranslatedPromptMetadataModel = {
    _t: "TranslatedPromptMetadata";
    prompt: TranslatedString;
};
type TranslatedString = {
    wasTranslated: boolean;
    englishText: string;
    text: string;
    targetLanguage: string;
};
type NullAssetModel = {
    _t: "NullAsset";
    metadata: Record<
        string,
        | ClassificationMetadataModel
        | CountMetadataModel
        | DemographicMetadataModel
        | ImageDimensionMetadataModel
        | LocationMetadataModel
        | OriginalFilenameMetadataModel
        | PromptMetadataModel
        | SourceUrlMetadataModel
        | TextMetadataModel
        | TranscriptionMetadataModel
        | TranslatedPromptMetadataModel
    >;
    identifier: string;
};
type TextAssetModel = {
    _t: "TextAsset";
    text: string;
    metadata: Record<
        string,
        | ClassificationMetadataModel
        | CountMetadataModel
        | DemographicMetadataModel
        | ImageDimensionMetadataModel
        | LocationMetadataModel
        | OriginalFilenameMetadataModel
        | PromptMetadataModel
        | SourceUrlMetadataModel
        | TextMetadataModel
        | TranscriptionMetadataModel
        | TranslatedPromptMetadataModel
    >;
    identifier: string;
};

const ClassificationMetadataModel = z.object({
    _t: z.literal("ClassificationMetadata").default("ClassificationMetadata"),
    classification: z.string(),
});
const CountMetadataModel = z.object({
    _t: z.literal("CountMetadata").default("CountMetadata"),
    count: z.number().int(),
});
const Demographic = z.object({ value: z.string(), confidence: z.number() });
const DemographicMetadataModel = z.object({
    _t: z.literal("DemographicMetadata").default("DemographicMetadata"),
    demographics: z.record(Demographic).optional(),
});
const ImageDimensionMetadataModel = z.object({
    _t: z.literal("ImageDimensionMetadata").default("ImageDimensionMetadata"),
    height: z.number().int().optional(),
    width: z.number().int().optional(),
});
const LocationMetadataModel = z.object({
    _t: z.literal("LocationMetadata").default("LocationMetadata"),
    x: z.number(),
    y: z.number(),
});
const OriginalFilenameMetadataModel = z.object({
    _t: z.literal("OriginalFilenameMetadata").default("OriginalFilenameMetadata"),
    originalFilename: z.string(),
});
const PromptMetadataModel = z.object({ _t: z.literal("PromptMetadata").default("PromptMetadata"), prompt: z.string() });
const SourceUrlMetadataModel = z.object({
    _t: z.literal("SourceUrlMetadataModel").default("SourceUrlMetadataModel"),
    url: z.string(),
});
const TextMetadataModel = z.object({ _t: z.literal("TextMetadata").default("TextMetadata"), text: z.string() });
const TranscriptionMetadataModel = z.object({
    _t: z.literal("TranscriptionMetadataModel").default("TranscriptionMetadataModel"),
    transcription: z.string(),
});
const TranslatedString = z.object({
    wasTranslated: z.boolean(),
    englishText: z.string(),
    text: z.string(),
    targetLanguage: z.string(),
});
const TranslatedPromptMetadataModel = z.object({
    _t: z.literal("TranslatedPromptMetadata").default("TranslatedPromptMetadata"),
    prompt: TranslatedString,
});
const FileAssetModel = z.object({
    _t: z.literal("FileAsset").default("FileAsset"),
    fileName: z.string(),
    metadata: z.record(
        z.discriminatedUnion("_t", [
            ClassificationMetadataModel,
            CountMetadataModel,
            DemographicMetadataModel,
            ImageDimensionMetadataModel,
            LocationMetadataModel,
            OriginalFilenameMetadataModel,
            PromptMetadataModel,
            SourceUrlMetadataModel,
            TextMetadataModel,
            TranscriptionMetadataModel,
            TranslatedPromptMetadataModel,
        ])
    ),
    identifier: z.string(),
});
const NullAssetModel = z.object({
    _t: z.literal("NullAsset").default("NullAsset"),
    metadata: z.record(
        z.discriminatedUnion("_t", [
            ClassificationMetadataModel,
            CountMetadataModel,
            DemographicMetadataModel,
            ImageDimensionMetadataModel,
            LocationMetadataModel,
            OriginalFilenameMetadataModel,
            PromptMetadataModel,
            SourceUrlMetadataModel,
            TextMetadataModel,
            TranscriptionMetadataModel,
            TranslatedPromptMetadataModel,
        ])
    ),
    identifier: z.string(),
});
const TextAssetModel = z.object({
    _t: z.literal("TextAsset").default("TextAsset"),
    text: z.string(),
    metadata: z.record(
        z.discriminatedUnion("_t", [
            ClassificationMetadataModel,
            CountMetadataModel,
            DemographicMetadataModel,
            ImageDimensionMetadataModel,
            LocationMetadataModel,
            OriginalFilenameMetadataModel,
            PromptMetadataModel,
            SourceUrlMetadataModel,
            TextMetadataModel,
            TranscriptionMetadataModel,
            TranslatedPromptMetadataModel,
        ])
    ),
    identifier: z.string(),
});
const MultiAssetModel: z.ZodType<MultiAssetModel> = z.lazy(() =>
    z.object({
        _t: z.literal("MultiAsset").default("MultiAsset"),
        assets: z.array(z.union([FileAssetModel, MultiAssetModel, NullAssetModel, TextAssetModel])),
        metadata: z.record(
            z.discriminatedUnion("_t", [
                ClassificationMetadataModel,
                CountMetadataModel,
                DemographicMetadataModel,
                ImageDimensionMetadataModel,
                LocationMetadataModel,
                OriginalFilenameMetadataModel,
                PromptMetadataModel,
                SourceUrlMetadataModel,
                TextMetadataModel,
                TranscriptionMetadataModel,
                TranslatedPromptMetadataModel,
            ])
        ),
        identifier: z.string(),
    })
);
const DatapointModel = z.object({
    id: z.string(),
    datasetId: z.string(),
    asset: z.union([FileAssetModel, MultiAssetModel, NullAssetModel, TextAssetModel]),
});
const GetDatapointsByDatasetIdResult = z.object({ list: z.array(DatapointModel) });
const GetDatapointByIdResult = z.object({
    id: z.string(),
    datasetId: z.string(),
    state: z.enum(["Ready", "Pending", "Failed"]),
    sortIndex: z.number().int().nullish(),
    asset: z.union([FileAssetModel, MultiAssetModel, NullAssetModel, TextAssetModel]),
    createdAt: z.string().datetime({ offset: true }),
});
const CreateDatapointFromUrlsModel = z.object({ urls: z.array(z.string()) });
const BaseError = z.object({ errorMessage: z.string() }).partial();
const CreateDatapointResult = z.object({ datapointId: z.string(), errors: z.array(BaseError).optional() });
const GetDatasetProgressResult = z.object({
    total: z.number().int(),
    ready: z.number().int(),
    pending: z.number().int(),
    failed: z.number().int(),
});
const PrivateTextMetadataInput = z.object({
    _t: z.literal("PrivateTextMetadataInput").default("PrivateTextMetadataInput"),
    text: z.string(),
    identifier: z.string(),
});
const PromptMetadataInput = z.object({
    _t: z.literal("PromptMetadataInput").default("PromptMetadataInput"),
    prompt: z.string(),
});
const PublicTextMetadataInput = z.object({
    _t: z.literal("PublicTextMetadataInput").default("PublicTextMetadataInput"),
    text: z.string(),
    identifier: z.string(),
});
const TranscriptionMetadataInput = z.object({
    _t: z.literal("TranscriptionMetadataInput").default("TranscriptionMetadataInput"),
    transcription: z.string(),
});
const DatapointMetadataModel = z.object({
    datasetId: z.string(),
    metadata: z.array(
        z.discriminatedUnion("_t", [
            PrivateTextMetadataInput,
            PromptMetadataInput,
            PublicTextMetadataInput,
            TranscriptionMetadataInput,
        ])
    ),
    sortIndex: z.number().int().nullish(),
});
const postDatasetCreateDatapoint_Body = z
    .object({ files: z.array(z.instanceof(File)), model: DatapointMetadataModel })
    .partial()
    .passthrough();
const UploadTextSourcesToDatasetModel = z.object({
    datasetId: z.string(),
    textSources: z.array(z.string()),
    sortIndex: z.number().int().nullish(),
});
const GetDatasetByIdResult = z.object({ name: z.string() });
const ImportFromFileResult = z.object({ datasetId: z.string() });
const UploadFilesFromS3BucketModel = z.object({
    datasetId: z.string(),
    bucketName: z.string(),
    region: z.string().nullish(),
    sourcePrefix: z.string(),
    accessKey: z.string().nullish(),
    secretKey: z.string().nullish(),
    useCustomAwsCredentials: z.boolean(),
    clearDataset: z.boolean(),
});
const UploadFromS3Result = z.object({ estimatedCount: z.number().int() }).partial();

export const schemas = {
    ClassificationMetadataModel,
    CountMetadataModel,
    Demographic,
    DemographicMetadataModel,
    ImageDimensionMetadataModel,
    LocationMetadataModel,
    OriginalFilenameMetadataModel,
    PromptMetadataModel,
    SourceUrlMetadataModel,
    TextMetadataModel,
    TranscriptionMetadataModel,
    TranslatedString,
    TranslatedPromptMetadataModel,
    FileAssetModel,
    NullAssetModel,
    TextAssetModel,
    MultiAssetModel,
    DatapointModel,
    GetDatapointsByDatasetIdResult,
    GetDatapointByIdResult,
    CreateDatapointFromUrlsModel,
    BaseError,
    CreateDatapointResult,
    GetDatasetProgressResult,
    PrivateTextMetadataInput,
    PromptMetadataInput,
    PublicTextMetadataInput,
    TranscriptionMetadataInput,
    DatapointMetadataModel,
    postDatasetCreateDatapoint_Body,
    UploadTextSourcesToDatasetModel,
    GetDatasetByIdResult,
    ImportFromFileResult,
    UploadFilesFromS3BucketModel,
    UploadFromS3Result,
};

const endpoints = makeApi([
    {
        method: "delete",
        path: "/Datapoint/Delete",
        alias: "deleteDatapointDelete",
        requestFormat: "json",
        parameters: [
            {
                name: "id",
                type: "Query",
                schema: z.string().optional(),
            },
        ],
        response: z.void(),
    },
    {
        method: "get",
        path: "/Datapoint/GetAllDatapointsByDatasetId",
        alias: "getDatapointGetAllDatapointsByDatasetId",
        requestFormat: "json",
        parameters: [
            {
                name: "datasetId",
                type: "Query",
                schema: z.string().optional(),
            },
        ],
        response: GetDatapointsByDatasetIdResult,
    },
    {
        method: "get",
        path: "/Datapoint/GetById",
        alias: "getDatapointGetById",
        requestFormat: "json",
        parameters: [
            {
                name: "id",
                type: "Query",
                schema: z.string().optional(),
            },
        ],
        response: GetDatapointByIdResult,
    },
    {
        method: "post",
        path: "/Dataset/:datasetId/datapoints/urls",
        alias: "postDatasetDatasetIddatapointsurls",
        description: `Passing in multiple urls will create a single datapoint with a MultiAsset.
Each url will be fetched and stored as a sub-asset of the MultiAsset.
&lt;para /&gt;
If any of the urls are not accessible, the request will fail.`,
        requestFormat: "json",
        parameters: [
            {
                name: "body",
                description: `The body of the request.`,
                type: "Body",
                schema: CreateDatapointFromUrlsModel,
            },
            {
                name: "datasetId",
                type: "Path",
                schema: z.string(),
            },
        ],
        response: CreateDatapointResult,
    },
    {
        method: "get",
        path: "/Dataset/:datasetId/progress",
        alias: "getDatasetDatasetIdprogress",
        requestFormat: "json",
        parameters: [
            {
                name: "datasetId",
                type: "Path",
                schema: z.string(),
            },
        ],
        response: GetDatasetProgressResult,
    },
    {
        method: "post",
        path: "/Dataset/CreateDatapoint",
        alias: "postDatasetCreateDatapoint",
        description: `If multiple files are uploaded, a multi asset datapoint will be created.`,
        requestFormat: "form-data",
        parameters: [
            {
                name: "body",
                type: "Body",
                schema: postDatasetCreateDatapoint_Body,
            },
        ],
        response: CreateDatapointResult,
    },
    {
        method: "post",
        path: "/Dataset/CreatTextDatapoint",
        alias: "postDatasetCreatTextDatapoint",
        description: `If multiple text sources are uploaded, a new datapoint will be created for each text source.`,
        requestFormat: "json",
        parameters: [
            {
                name: "body",
                description: `The body of the request.`,
                type: "Body",
                schema: UploadTextSourcesToDatasetModel,
            },
        ],
        response: CreateDatapointResult,
    },
    {
        method: "get",
        path: "/Dataset/GetById",
        alias: "getDatasetGetById",
        requestFormat: "json",
        parameters: [
            {
                name: "id",
                type: "Query",
                schema: z.string().optional(),
            },
        ],
        response: z.object({ name: z.string() }),
    },
    {
        method: "post",
        path: "/Dataset/Import",
        alias: "postDatasetImport",
        requestFormat: "form-data",
        parameters: [
            {
                name: "body",
                type: "Body",
                schema: z
                    .object({ file: z.instanceof(File) })
                    .partial()
                    .passthrough(),
            },
            {
                name: "datasetId",
                type: "Query",
                schema: z.string().optional(),
            },
        ],
        response: z.object({ datasetId: z.string() }),
    },
    {
        method: "post",
        path: "/Dataset/UpdateName",
        alias: "postDatasetUpdateName",
        requestFormat: "json",
        parameters: [
            {
                name: "id",
                type: "Query",
                schema: z.string().optional(),
            },
            {
                name: "name",
                type: "Query",
                schema: z.string().optional(),
            },
        ],
        response: z.void(),
    },
    {
        method: "post",
        path: "/Dataset/UploadFilesFromS3",
        alias: "postDatasetUploadFilesFromS3",
        description: `A new datapoint will be created for each file in the bucket.`,
        requestFormat: "json",
        parameters: [
            {
                name: "body",
                description: `The body of the request.`,
                type: "Body",
                schema: UploadFilesFromS3BucketModel,
            },
        ],
        response: z.object({ estimatedCount: z.number().int() }).partial(),
    },
]);

export const api = new Zodios(endpoints);

export function createApiClient(baseUrl: string, options?: ZodiosOptions) {
    return new Zodios(baseUrl, endpoints, options);
}
