import assert from 'node:assert';
import BoxError from './boxerror.js';
import dashboard from './dashboard.js';
import domains from './domains.js';
import ejs from 'ejs';
import fs from 'node:fs';
import mail from './mail.js';
import mailServer from './mailserver.js';
import safe from 'safetydance';
import superagent from '@cloudron/superagent';


const MAIL_AUTOCONFIG_EJS = fs.readFileSync(import.meta.dirname + '/autoconfig.xml.ejs', { encoding: 'utf8' });

async function get(domain, location) {
    assert.strictEqual(typeof domain, 'string');
    assert.strictEqual(typeof location, 'string');

    if (location === 'autoconfig/mail/config-v1.1.xml') { // this also gets a ?emailaddress
        const mailDomain = await mail.getDomain(domain);
        if (!mailDomain) throw new BoxError(BoxError.NOT_FOUND, 'Domain not found');
        if (!mailDomain.enabled) throw new BoxError(BoxError.NOT_FOUND, 'Email not enabled');
        const { fqdn } = await mailServer.getLocation();

        const autoconfig = ejs.render(MAIL_AUTOCONFIG_EJS, { domain, fqdn });

        return { type: 'text/xml', body: autoconfig };
    } else if (location === 'host-meta' || location === 'matrix/server' || location === 'matrix/client') {
        const type = location === 'host-meta' ? 'text/xml' : 'application/json';

        const domainObject = await domains.get(domain);
        if (!domainObject) throw new BoxError(BoxError.NOT_FOUND, 'Domain not found');
        if (!domainObject.wellKnown || !(location in domainObject.wellKnown)) throw new BoxError(BoxError.NOT_FOUND, 'No custom well-known config');

        return { type, body: domainObject.wellKnown[location] };
    } else if (location === 'openid-configuration') {
        const { fqdn:dashboardFqdn } = await dashboard.getLocation();
        if (domain !== dashboardFqdn) throw new BoxError(BoxError.NOT_FOUND, 'No custom well-known config');
        // the oidc-provider module does not expose this in javascript but only via a route handler
        // we have to use the external route even
        const [error, result] = await safe(superagent.get(`https://${dashboardFqdn}/openid/.well-known/openid-configuration`));
        if (error) return new BoxError(BoxError.INTERNAL_ERROR, 'unable to connect to internal OpenID routes');

        return { type: 'application/json', body: result.body };
    } else if (location === 'carddav') {
        const domainObject = await domains.get(domain);
        if (!domainObject) throw new BoxError(BoxError.NOT_FOUND, 'Domain not found');
        if (!domainObject.wellKnown || !domainObject.wellKnown.carddav) throw new BoxError(BoxError.NOT_FOUND, 'No custom well-known config');

        return { redirectTo: `https://${domainObject.wellKnown.carddav}` };
    } else if (location === 'caldav') {
        const domainObject = await domains.get(domain);
        if (!domainObject) throw new BoxError(BoxError.NOT_FOUND, 'Domain not found');
        if (!domainObject.wellKnown || !domainObject.wellKnown.caldav) throw new BoxError(BoxError.NOT_FOUND, 'No custom well-known config');

        return { redirectTo: `https://${domainObject.wellKnown.caldav}` };
    } else {
        throw new BoxError(BoxError.NOT_FOUND, 'No custom well-known config');
    }
}

export default {
    get
};
