const OFFICE_MIME_SUBSTRINGS = [
    'application/msword',
    'application/vnd.ms-excel',
    'application/vnd.ms-powerpoint',
    'application/vnd.openxmlformats-officedocument',
    'application/vnd.oasis.opendocument',
    'application/rtf'
];
const OFFICE_EXTENSIONS = [
    '.doc',
    '.docm',
    '.docx',
    '.odp',
    '.ods',
    '.odt',
    '.ppt',
    '.pptm',
    '.pptx',
    '.rtf',
    '.xls',
    '.xlsm',
    '.xlsx'
];
const TEXT_ATTACHMENT_MIME_TYPES = {
    csv: 'text/csv',
    css: 'text/css',
    json: 'application/json',
    txt: 'text/plain',
    yaml: 'text/yaml'
};
export const TEXT_LIKE_FILE_EXTENSIONS = [
    '.txt',
    '.text',
    '.log',
    '.md',
    '.markdown',
    '.csv',
    '.tsv',
    '.json',
    '.jsonl',
    '.ndjson',
    '.xml',
    '.yaml',
    '.yml',
    '.toml',
    '.ini',
    '.cfg',
    '.conf',
    '.env',
    '.sh',
    '.bash',
    '.zsh',
    '.js',
    '.jsx',
    '.ts',
    '.tsx',
    '.mts',
    '.cts',
    '.py',
    '.go',
    '.java',
    '.rb',
    '.php',
    '.sql',
    '.css',
    '.scss',
    '.html',
    '.htm'
];
const MIME_TYPE_FILE_EXTENSIONS = {
    'application/json': '.json',
    'application/pdf': '.pdf',
    'application/x-yaml': '.yaml',
    'application/yaml': '.yaml',
    'image/gif': '.gif',
    'image/jpeg': '.jpg',
    'image/jpg': '.jpg',
    'image/png': '.png',
    'image/webp': '.webp',
    'text/css': '.css',
    'text/csv': '.csv',
    'text/plain': '.txt',
    'text/yaml': '.yaml'
};
export function buildAttachmentUploadMetadata(params) {
    const label = normalizeNonEmptyString(params.label);
    const insight = normalizeNonEmptyString(params.insight);
    if (!label && !insight) {
        return undefined;
    }
    return {
        ...(label ? { label } : {}),
        ...(insight ? { insight } : {})
    };
}
function normalizeNonEmptyString(value) {
    if (typeof value !== 'string') {
        return undefined;
    }
    const trimmed = value.trim();
    return trimmed.length > 0 ? trimmed : undefined;
}
export function isTextLikeMimeType(mimeType) {
    const normalizedMimeType = mimeType.toLowerCase();
    return (normalizedMimeType.startsWith('text/') ||
        normalizedMimeType.includes('json') ||
        normalizedMimeType.includes('xml') ||
        normalizedMimeType.includes('yaml') ||
        normalizedMimeType.includes('toml') ||
        normalizedMimeType.includes('javascript') ||
        normalizedMimeType.includes('typescript') ||
        normalizedMimeType.includes('ecmascript') ||
        normalizedMimeType.includes('markdown') ||
        normalizedMimeType.includes('shellscript') ||
        normalizedMimeType.includes('python') ||
        normalizedMimeType.includes('ruby') ||
        normalizedMimeType.includes('php') ||
        normalizedMimeType.includes('sql'));
}
export function isOfficeXml(params) {
    const normalizedMimeType = normalizeNonEmptyString(params.mimeType)?.toLowerCase();
    if (normalizedMimeType && OFFICE_MIME_SUBSTRINGS.some((mimeType) => normalizedMimeType.includes(mimeType))) {
        return true;
    }
    const normalizedFileName = normalizeNonEmptyString(params.fileName)?.toLowerCase();
    if (!normalizedFileName) {
        return false;
    }
    return OFFICE_EXTENSIONS.some((extension) => normalizedFileName.endsWith(extension));
}
export function getTextAttachmentType(params) {
    if (isOfficeXml(params)) {
        return null;
    }
    const normalizedFileName = normalizeNonEmptyString(params.fileName)?.toLowerCase();
    const normalizedMimeType = normalizeNonEmptyString(params.mimeType)?.toLowerCase();
    if (normalizedMimeType === 'text/csv' || normalizedFileName?.endsWith('.csv')) {
        return 'csv';
    }
    if (normalizedMimeType === 'application/json' || normalizedFileName?.endsWith('.json')) {
        return 'json';
    }
    if (normalizedMimeType === 'text/yaml' ||
        normalizedMimeType === 'application/x-yaml' ||
        normalizedMimeType === 'application/yaml' ||
        normalizedFileName?.endsWith('.yaml') ||
        normalizedFileName?.endsWith('.yml')) {
        return 'yaml';
    }
    if (normalizedMimeType === 'text/css' || normalizedFileName?.endsWith('.css')) {
        return 'css';
    }
    if (normalizedMimeType === 'text/plain' ||
        (normalizedMimeType ? isTextLikeMimeType(normalizedMimeType) : false) ||
        (normalizedFileName ? TEXT_LIKE_FILE_EXTENSIONS.some((extension) => normalizedFileName.endsWith(extension)) : false)) {
        return 'txt';
    }
    return null;
}
function getTextLikeMimeTypeFromFileName(fileName) {
    const textAttachmentType = getTextAttachmentType({ fileName });
    return textAttachmentType ? TEXT_ATTACHMENT_MIME_TYPES[textAttachmentType] : undefined;
}
export function normalizeAttachmentMimeType(params) {
    const normalizedMimeType = normalizeNonEmptyString(params.mimeType)?.toLowerCase() ?? normalizeNonEmptyString(params.fallbackMimeType)?.toLowerCase();
    const textLikeMimeType = getTextLikeMimeTypeFromFileName(params.fileName);
    if (normalizedMimeType && isTextLikeMimeType(normalizedMimeType)) {
        return normalizedMimeType;
    }
    if (textLikeMimeType) {
        return textLikeMimeType;
    }
    return normalizedMimeType ?? undefined;
}
function getDefaultFileName(mimeType) {
    const normalizedMimeType = mimeType.toLowerCase();
    const knownExtension = MIME_TYPE_FILE_EXTENSIONS[normalizedMimeType];
    if (knownExtension) {
        return `attachment${knownExtension}`;
    }
    if (normalizedMimeType.startsWith('image/')) {
        const subtype = normalizedMimeType.slice('image/'.length).split(/[+;]/)[0]?.trim();
        if (subtype) {
            return `attachment.${subtype}`;
        }
    }
    return 'attachment';
}
function resolveFileName(params) {
    return (normalizeNonEmptyString(params.fileName) ?? normalizeNonEmptyString(params.fallbackFileName) ?? getDefaultFileName(params.mimeType));
}
function decodeBase64(base64Data) {
    return Uint8Array.from(atob(base64Data), (char) => char.charCodeAt(0));
}
function withMimeType(blob, mimeType) {
    if (blob.type === mimeType) {
        return blob;
    }
    return new Blob([blob], { type: mimeType });
}
function parseDataUrl(data) {
    const match = data.match(/^data:([^;,]+)?(?:;base64)?,(.*)$/s);
    if (!match) {
        return null;
    }
    return {
        mimeType: normalizeNonEmptyString(match[1]),
        base64Data: match[2] ?? ''
    };
}
function isAttachmentDataLike(source) {
    return 'data' in source && typeof source.data === 'string' && !('type' in source);
}
export function toAttachmentUploadDescriptor(source, options) {
    if (source instanceof File) {
        const mimeType = normalizeAttachmentMimeType({
            fileName: source.name,
            mimeType: source.type,
            fallbackMimeType: options?.fallbackMimeType
        });
        if (!mimeType) {
            return null;
        }
        return {
            blob: withMimeType(source, mimeType),
            fileName: resolveFileName({
                fileName: source.name,
                fallbackFileName: options?.fallbackFileName,
                mimeType
            }),
            mimeType
        };
    }
    if (source instanceof Blob) {
        const sourceWithOptionalName = source;
        const mimeType = normalizeAttachmentMimeType({
            fileName: typeof sourceWithOptionalName.name === 'string' ? sourceWithOptionalName.name : options?.fallbackFileName,
            mimeType: source.type,
            fallbackMimeType: options?.fallbackMimeType
        });
        if (!mimeType) {
            return null;
        }
        return {
            blob: withMimeType(source, mimeType),
            fileName: resolveFileName({
                fileName: sourceWithOptionalName.name,
                fallbackFileName: options?.fallbackFileName,
                mimeType
            }),
            mimeType
        };
    }
    if (isAttachmentDataLike(source)) {
        const parsedDataUrl = parseDataUrl(source.data);
        const mimeType = normalizeAttachmentMimeType({
            fileName: typeof source.name === 'string' ? source.name : source.fileName,
            mimeType: parsedDataUrl?.mimeType ?? source.mimeType,
            fallbackMimeType: options?.fallbackMimeType
        });
        const base64Data = parsedDataUrl?.base64Data ?? source.data;
        if (!mimeType) {
            return null;
        }
        return {
            blob: new Blob([decodeBase64(base64Data)], { type: mimeType }),
            fileName: resolveFileName({
                fileName: source.name ?? source.fileName,
                fallbackFileName: options?.fallbackFileName,
                mimeType
            }),
            mimeType
        };
    }
    if (source.type === 'image') {
        const parsedDataUrl = parseDataUrl(source.image);
        if (!parsedDataUrl?.mimeType) {
            return null;
        }
        return {
            blob: new Blob([decodeBase64(parsedDataUrl.base64Data)], {
                type: parsedDataUrl.mimeType
            }),
            fileName: resolveFileName({
                fileName: source.fileName,
                fallbackFileName: options?.fallbackFileName,
                mimeType: parsedDataUrl.mimeType
            }),
            mimeType: parsedDataUrl.mimeType
        };
    }
    if (source.type === 'pdf' || source.type === 'archive') {
        const parsedDataUrl = parseDataUrl(source.data);
        const defaultMimeType = source.type === 'pdf' ? 'application/pdf' : 'application/octet-stream';
        const mimeType = parsedDataUrl?.mimeType ?? normalizeNonEmptyString(options?.fallbackMimeType) ?? defaultMimeType;
        return {
            blob: new Blob([decodeBase64(parsedDataUrl?.base64Data ?? source.data)], {
                type: mimeType
            }),
            fileName: resolveFileName({
                fileName: source.fileName,
                fallbackFileName: options?.fallbackFileName,
                mimeType
            }),
            mimeType
        };
    }
    if (source.type === 'csv' || source.type === 'css' || source.type === 'json' || source.type === 'txt' || source.type === 'yaml') {
        const mimeType = normalizeAttachmentMimeType({
            fileName: source.fileName,
            mimeType: source.mimeType,
            fallbackMimeType: options?.fallbackMimeType ?? TEXT_ATTACHMENT_MIME_TYPES[source.type]
        });
        if (!mimeType) {
            return null;
        }
        return {
            blob: new Blob([source.content], { type: mimeType }),
            fileName: resolveFileName({
                fileName: source.fileName,
                fallbackFileName: options?.fallbackFileName,
                mimeType
            }),
            mimeType
        };
    }
    return null;
}
export function buildAttachmentUploadFormData(params) {
    const formData = new FormData();
    formData.append(params.fieldName ?? 'file', params.descriptor.blob, params.descriptor.fileName);
    formData.append('prefix', params.prefix);
    if (params.branchId) {
        formData.append('branchId', params.branchId);
    }
    if (params.commitId) {
        formData.append('commitId', params.commitId);
    }
    const metadata = buildAttachmentUploadMetadata(params.metadata ?? {});
    if (metadata) {
        formData.append('metadata', JSON.stringify(metadata));
    }
    return formData;
}
export function createUploadedAttachmentFromServer(params) {
    const mediaType = normalizeNonEmptyString(params.response.mimeType) ?? params.fallbackMimeType;
    return {
        type: 'uploaded',
        url: normalizeNonEmptyString(params.response.contentUrl) ?? params.response.signedUrl,
        signedUrl: params.response.signedUrl,
        mediaType,
        fileName: normalizeNonEmptyString(params.response.fileName) ?? params.fallbackFileName,
        label: params.label,
        insight: params.insight,
        storageKey: normalizeNonEmptyString(params.response.storageKey),
        signedUrlExpiresAt: params.response.signedUrlExpiresAt,
        scopeType: params.response.scopeType,
        applicationId: normalizeNonEmptyString(params.response.applicationId)
    };
}
/**
 * Shared transport for POST /api/v1/files/upload. Builds form-data, URL with query params,
 * fetches, and returns the raw server DTO. Callers map to their own types (e.g. Attachment,
 * AttachmentUploadResult).
 */
export async function uploadAttachmentToServerApi(params) {
    const { baseUrl, authorization, descriptor, scopeType, purpose, applicationId, branchName, commitId, prefix = 'message-attachment', metadata } = params;
    const formData = buildAttachmentUploadFormData({
        descriptor,
        prefix,
        metadata,
        ...(branchName != null && { branchId: branchName }),
        ...(commitId != null && { commitId })
    });
    const uploadUrl = new URL('/api/v1/files/upload', baseUrl);
    uploadUrl.searchParams.set('scopeType', scopeType);
    uploadUrl.searchParams.set('purpose', purpose);
    if (applicationId != null && applicationId.trim() !== '') {
        uploadUrl.searchParams.set('applicationId', applicationId);
    }
    if (branchName != null && branchName.trim() !== '') {
        uploadUrl.searchParams.set('branchName', branchName);
    }
    if (commitId != null && commitId.trim() !== '') {
        uploadUrl.searchParams.set('commitId', commitId);
    }
    const response = await fetch(uploadUrl.toString(), {
        method: 'POST',
        body: formData,
        headers: {
            Authorization: authorization
        }
    });
    if (!response.ok) {
        const errorText = await response.text().catch(() => '');
        throw new Error(`Attachment upload failed: status=${response.status}${errorText ? `, body=${errorText}` : ''}`);
    }
    return (await response.json());
}
//# sourceMappingURL=attachment-upload.js.map