// import { Client } from 'guzzle';
// import { Log } from '@adonisjs/core/build/standalone';
// import { DoiInterface } from './interfaces/DoiInterface';
import DoiClientContract from '#app/Library/Doi/DoiClientContract';
import DoiClientException from '#app/exceptions/DoiClientException';
import { StatusCodes } from 'http-status-codes';
import logger from '@adonisjs/core/services/logger';
import { AxiosResponse } from 'axios';
import axios from 'axios';

export class DoiClient implements DoiClientContract {
    public username: string;
    public password: string;
    public serviceUrl: string;

    constructor() {
        // const datacite_environment = process.env.DATACITE_ENVIRONMENT || 'debug';
        this.username = process.env.DATACITE_USERNAME || '';
        this.password = process.env.DATACITE_PASSWORD || '';
        this.serviceUrl = process.env.DATACITE_SERVICE_URL || '';
        // this.prefix = process.env.DATACITE_PREFIX || '';
        // this.base_domain = process.env.BASE_DOMAIN || '';

        if (this.username === '' || this.password === '' || this.serviceUrl === '') {
            const message = 'issing configuration settings to properly initialize DOI client';
            logger.error(message);
            throw new DoiClientException(StatusCodes.BAD_REQUEST, message);
        }
    }

    /**
     * Creates a DOI with the given identifier
     *
     * @param doiValue The desired DOI identifier e.g. '10.5072/tethys.999',
     * @param xmlMeta
     * @param landingPageUrl e.g. https://www.tethys.at/dataset/1
     *
     * @return Promise<AxiosResponse<any>> The http response in the form of a axios response
     */
    public async registerDoi(doiValue: string, xmlMeta: string, landingPageUrl: string): Promise<AxiosResponse<any>> {
        //step 1: register metadata via xml upload
        // state draft
        // let response;
        // let url = `${this.serviceUrl}/metadata/${doiValue}`; //https://mds.test.datacite.org/metadata/10.21388/tethys.213
        const auth = {
            username: this.username,
            password: this.password,
        };
        let headers = {
            'Content-Type': 'application/xml;charset=UTF-8',
        };
        try {
            const metadataResponse = await axios.default.put(`${this.serviceUrl}/metadata/${doiValue}`, xmlMeta, { auth, headers });

            // Response Codes
            // 201 Created: operation successful
            // 401 Unauthorised: no login
            // 403 Forbidden: login problem, quota exceeded
            // 415 Wrong Content Type : Not including content type in the header.
            // 422 Unprocessable Entity : invalid XML
            // let test = metadataResponse.data; // 'OK (10.21388/TETHYS.213)'
            if (metadataResponse.status !== 201) {
                const message = `Unexpected DataCite MDS response code ${metadataResponse.status}`;
                logger.error(message);
                throw new DoiClientException(metadataResponse.status, message);
            }

            const doiResponse = await axios.default.put(`${this.serviceUrl}/doi/${doiValue}`, `doi=${doiValue}\nurl=${landingPageUrl}`, {
                auth,
                headers,
            });

            // Response Codes
            // 201 Created: operation successful
            // 400 Bad Request: request body must be exactly two lines: DOI and URL; wrong domain, wrong prefix;
            // 401 Unauthorised: no login
            // 403 Forbidden: login problem, quota exceeded
            // 412 Precondition failed: metadata must be uploaded first.
            if (doiResponse.status !== 201) {
                const message = `Unexpected DataCite MDS response code ${doiResponse.status}`;
                logger.error(message);
                throw new DoiClientException(doiResponse.status, message);
            }

            return doiResponse;
        } catch (error) {
            // const message = `request for registering DOI failed with ${error.message}`;
            // Handle the error, log it, or rethrow as needed
            logger.error(error.message);
            throw new DoiClientException(error.response.status, error.response.data);
        }
    }
}
