import axios from 'axios';
import * as fs from 'fs';
import * as path from 'path';
export class ZenodoClient {
    constructor(accessToken, sandbox = false) {
        this.baseURL = 'https://zenodo.org/api';
        if (!accessToken) {
            throw new Error('Cannot connect to zenodo without an access token.');
        }
        this.accessToken = accessToken;
        if (sandbox) {
            this.baseURL = 'https://sandbox.zenodo.org/api';
        }
        this.axiosInstance = axios.create({
            baseURL: this.baseURL,
            params: {
                access_token: this.accessToken,
            },
        });
    }
    /**
     * Create a new deposition with the provided metadata.
     * @param metadata Deposition metadata
     */
    async createEmptyDeposition() {
        try {
            const response = await this.axiosInstance.post('/deposit/depositions', {}, {
                headers: {
                    'Content-Type': 'application/json',
                },
            });
            return response.data;
        }
        catch (error) {
            this.handleError(error);
        }
    }
    /**
     * Create a new deposition with the provided metadata.
     * @param metadata Deposition metadata
     */
    async createDeposition(metadata) {
        try {
            const response = await this.axiosInstance.post('/deposit/depositions', { metadata }, {
                headers: {
                    'Content-Type': 'application/json',
                },
            });
            return response.data;
        }
        catch (error) {
            this.handleError(error);
        }
    }
    /**
     * Get a deposition by ID.
     * @param depositionId ID of the deposition
     */
    async getDeposition(depositionId) {
        try {
            const response = await this.axiosInstance.get(`/deposit/depositions/${depositionId}`);
            return response.data;
        }
        catch (error) {
            this.handleError(error);
        }
    }
    /**
     * Create a new deposition with the provided metadata.
     * @param metadata Deposition metadata
     */
    async updateDeposition(depositionId, metadata) {
        try {
            const response = await this.axiosInstance.put(`/deposit/depositions/${depositionId}`, { metadata }, {
                headers: {
                    'Content-Type': 'application/json',
                },
            });
            return response.data;
        }
        catch (error) {
            this.handleError(error);
        }
    }
    /**
     * Upload a file to an existing deposition.
     * @param depositionId ID of the deposition
     * @param filePath Path to the file to upload
     */
    async uploadFile(bucketUrl, filePath) {
        try {
            // Prepare the file for upload
            const fileName = path.basename(filePath);
            const url = `${bucketUrl}/${encodeURIComponent(fileName)}`;
            const fileStream = fs.createReadStream(filePath);
            // Calculate the file size
            const stats = fs.statSync(filePath);
            const fileSizeInBytes = stats.size;
            // Set the appropriate headers and config
            const response = await axios.put(url, fileStream, {
                headers: {
                    'Content-Type': 'application/octet-stream', // or the actual MIME type of your file
                    'Content-Length': fileSizeInBytes,
                },
                params: {
                    access_token: this.accessToken,
                },
                maxContentLength: Infinity,
                maxBodyLength: Infinity,
            });
            return response.data;
        }
        catch (error) {
            this.handleError(error);
        }
    }
    /**
     * List all files in an unpublished deposition.
     * @param depositionId ID of the deposition
     */
    async listFiles(depositionId) {
        try {
            const response = await this.axiosInstance.get(`/deposit/depositions/${depositionId}/files`);
            return response.data;
        }
        catch (error) {
            this.handleError(error);
        }
    }
    /**
     * Publish a deposition.
     * @param depositionId ID of the deposition
     */
    async publishDeposition(depositionId) {
        try {
            const response = await this.axiosInstance.post(`/deposit/depositions/${depositionId}/actions/publish`);
            return response.data;
        }
        catch (error) {
            this.handleError(error);
        }
    }
    /**
     * Handle API errors.
     * @param error Error object
     */
    handleError(error) {
        if (error.response) {
            console.error('API Error:', error.response.status, error.response.data);
            throw new Error(`API Error: ${error.response.status} ${JSON.stringify(error.response.data)}`);
        }
        else {
            console.error('Error:', error.message);
            throw new Error(`Error: ${error.message}`);
        }
    }
}
