import apps from '../apps.js';
import assert from 'node:assert';
import archives from '../archives.js';
import AuditSource from '../auditsource.js';
import BoxError from '../boxerror.js';
import { HttpError } from '@cloudron/connect-lastmile';
import { HttpSuccess } from '@cloudron/connect-lastmile';
import safe from 'safetydance';
import { getImageContentType } from '../image-content-type.js';


async function load(req, res, next) {
    assert.strictEqual(typeof req.params.id, 'string');

    const [error, result] = await safe(archives.get(req.params.id));
    if (error) return next(BoxError.toHttpError(error));
    if (!result) return next(new HttpError(404, 'Backup not found'));

    req.resources.archive = result;

    next();
}

async function list(req, res, next) {
    const page = typeof req.query.page === 'string' ? parseInt(req.query.page) : 1;
    if (!page || page < 0) return next(new HttpError(400, 'page query param has to be a postive number'));

    const perPage = typeof req.query.per_page === 'string'? parseInt(req.query.per_page) : 25;
    if (!perPage || perPage < 0) return next(new HttpError(400, 'per_page query param has to be a postive number'));

    const [error, result] = await safe(archives.list(page, perPage));
    if (error) return next(BoxError.toHttpError(error));

    next(new HttpSuccess(200, { archives: result }));
}

async function get(req, res, next) {
    assert.strictEqual(typeof req.params.id, 'string');

    next(new HttpSuccess(200, req.resources.archive));
}

async function getIcon(req, res, next) {
    assert.strictEqual(typeof req.params.id, 'string');
    assert.strictEqual(typeof req.resources.archive, 'object');

    const original = typeof req.query.original === 'string' ? (req.query.original === '1' || req.query.original === 'true') : false;

    const [error, icon] = await safe(archives.getIcon(req.params.id, { original }));
    if (error) return next(BoxError.toHttpError(error));

    res.set('Content-Type', getImageContentType(icon)).send(icon);
}

async function del(req, res, next) {
    assert.strictEqual(typeof req.params.id, 'string');
    assert.strictEqual(typeof req.resources.archive, 'object');

    const [error] = await safe(archives.del(req.resources.archive, AuditSource.fromRequest(req)));
    if (error) return next(BoxError.toHttpError(error));

    next(new HttpSuccess(204));
}

async function unarchive(req, res, next) {
    assert.strictEqual(typeof req.params.id, 'string');
    assert.strictEqual(typeof req.resources.archive, 'object');
    assert.strictEqual(typeof req.body, 'object');

    const data = req.body;

    // required
    if (typeof data.subdomain !== 'string') return next(new HttpError(400, 'subdomain is required'));
    if (typeof data.domain !== 'string') return next(new HttpError(400, 'domain is required'));

    // optional
    if (('ports' in data) && typeof data.ports !== 'object') return next(new HttpError(400, 'ports must be an object'));

    if ('secondaryDomains' in data) {
        if (!data.secondaryDomains || typeof data.secondaryDomains !== 'object') return next(new HttpError(400, 'secondaryDomains must be an object'));
        if (Object.keys(data.secondaryDomains).some(function (key) { return typeof data.secondaryDomains[key].domain !== 'string' || typeof data.secondaryDomains[key].subdomain !== 'string'; })) return next(new HttpError(400, 'secondaryDomain object must contain domain and subdomain strings'));
    }

    const [error, result] = await safe(apps.unarchive(req.resources.archive, req.body, AuditSource.fromRequest(req)));
    if (error) return next(BoxError.toHttpError(error));

    next(new HttpSuccess(202, { id: result.id, taskId: result.taskId }));
}

export default {
    load,

    list,
    get,
    getIcon,
    del,
    unarchive
};
