import { KeetaNet } from '../../client/index.js';
import * as CurrencyInfo from '@keetanetwork/currency-info';
import { KeetaAnchorUserError } from '../../lib/error.js';
import { assertCreateVerificationRequest, assertCreateVerificationResponse } from './common.generated.js';
import { verifySignedData } from './common.js';
import { KeetaAnchorMetadataServer } from '../../lib/anchor-metadata-server.js';
const kycProviderURLUndefined = 'NO_KYC_PROVIDER_URL:87f0175c-4d0a-4029-a4f3-ba93ef725654';
;
export class KeetaNetKYCAnchorHTTPServer extends KeetaAnchorMetadataServer {
    homepage;
    client;
    signer;
    ca;
    kyc;
    kycProviderURL;
    routes;
    #countryCodes;
    constructor(config) {
        super(config);
        this.homepage = config.homepage ?? '';
        this.client = config.client;
        this.signer = config.signer;
        this.ca = config.ca;
        this.kyc = config.kyc;
        this.routes = config.routes ?? {};
        this.kycProviderURL = config.kycProviderURL ?? kycProviderURLUndefined;
        if (config.kyc.countryCodes) {
            this.#countryCodes = config.kyc.countryCodes.map(function (inputCode) {
                if (CurrencyInfo.Country.isCountryCode(inputCode)) {
                    return (new CurrencyInfo.Country(inputCode));
                }
                return (inputCode);
            });
        }
    }
    async initRoutes(config) {
        const routes = {};
        /**
         * If a homepage is provided, setup the route for it
         */
        if ('homepage' in config) {
            routes['GET /'] = async function () {
                let homepageData;
                if (typeof config.homepage === 'string') {
                    homepageData = config.homepage;
                }
                else {
                    if (!config.homepage) {
                        throw (new Error('internal error: No homepage function provided'));
                    }
                    homepageData = await config.homepage();
                }
                return ({
                    output: homepageData,
                    contentType: 'text/html'
                });
            };
        }
        /**
         * Begin the KYC verification process
         * with this KYC provider
         */
        routes['POST /api/createVerification'] = async function (_ignore_params, bodyInput) {
            if (bodyInput === null || typeof bodyInput !== 'object' || !('request' in bodyInput)) {
                throw (new KeetaAnchorUserError('Invalid request'));
            }
            const body = assertCreateVerificationRequest(bodyInput.request);
            const valid = await verifySignedData(body);
            if (!valid) {
                throw (new KeetaAnchorUserError('Invalid signature'));
            }
            /* XXX:TODO: Validate that the nonce is unique (within a reasonable time frame) */
            let response = {};
            if (config.kyc.verificationStarted) {
                response = await config.kyc.verificationStarted(body);
            }
            response ??= {};
            if (response?.ok === false) {
                throw (new KeetaAnchorUserError(response.error ?? 'Unknown error'));
            }
            response.ok = true;
            if (!response.ok) {
                throw (new Error('internal error: invalid response'));
            }
            response.id ??= crypto.randomUUID();
            let defaultWebURL;
            if (typeof config.kycProviderURL === 'string') {
                defaultWebURL = config.kycProviderURL.replace('{id}', encodeURIComponent(response.id));
            }
            else if (config.kycProviderURL !== undefined) {
                defaultWebURL = config.kycProviderURL(response.id);
            }
            else {
                defaultWebURL = kycProviderURLUndefined;
            }
            response.webURL ??= defaultWebURL;
            if (!response.webURL || response.webURL === kycProviderURLUndefined) {
                throw (new KeetaAnchorUserError('No webURL provided -- cannot proceed with verification'));
            }
            response.expectedCost = {
                min: '0',
                max: '0',
                token: KeetaNet.lib.Account.generateBaseAddresses(config.client.network).baseToken.publicKeyString.get(),
                ...response.expectedCost
            };
            const responseValidated = assertCreateVerificationResponse(response);
            return ({
                output: JSON.stringify(responseValidated)
            });
        };
        /**
         * Request an estimate for a KYC
         * verification (optional)
         *
         * XXX:TODO
         */
        // if (false) {
        // 	routes['POST /api/createEstimate'] = async function(_ignore_params, _ignore_body) {
        // 		throw(new Error('not implemented'));
        // 	};
        // }
        /**
         * Get the certificate for the
         * KYC verification
         */
        routes['GET /api/getCertificates/:verificationID'] = async function (params) {
            const verificationID = params.get('verificationID');
            if (verificationID === undefined) {
                throw (new KeetaAnchorUserError('No verification ID provided'));
            }
            const certificates = await config.kyc.getCertificates(verificationID);
            const response = {
                ok: true,
                results: certificates
            };
            return ({
                output: JSON.stringify(response)
            });
        };
        /**
         * Check if the KYC provider can
         * service a more specific locality
         * (optional)
         *
         * XXX:TODO
         */
        // if (false) {
        // 	routes['GET /api/checkLocality'] = async function(_ignore_params, _ignore_body) {
        // 		throw(new Error('not implemented'));
        // 	};
        // }
        /**
         * Notification that payment has been received for the KYC verification
         *
         * XXX:TODO
         */
        // if (false) {
        // 	routes['POST /api/notifyPayment/:verificationID'] = async function(_ignore_params, _ignore_body) {
        // 		throw(new Error('not implemented'));
        // 	};
        // }
        return ({
            ...config.routes,
            ...routes
        });
    }
    async buildServiceMetadata() {
        return ({
            ca: this.ca.toPEM(),
            countryCodes: this.#countryCodes?.map(function (country) {
                return (country.code);
            }) ?? [],
            operations: {
                // checkLocality: (new URL('/api/checkLocality', this.url)).toString(),
                // getEstimate: (new URL('/api/createEstimate', this.url)).toString(),
                // notifyPayment: (new URL('/api/notifyPayment/{id}', this.url)).toString(),
                createVerification: (new URL('/api/createVerification', this.url)).toString(),
                getCertificates: (new URL('/api/getCertificates', this.url)).toString() + '/{id}'
            }
        });
    }
}
//# sourceMappingURL=server.js.map