import assert from 'node:assert';
import BoxError from './boxerror.js';
import logger from './logger.js';
import Docker from 'dockerode';
import safe from 'safetydance';
import tokens from './tokens.js';

const { log } = logger('janitor');


const gConnection = new Docker({ socketPath: '/var/run/docker.sock' });

async function cleanupTokens() {
    log('Cleaning up expired tokens');

    const [error, result] = await safe(tokens.delExpired());
    if (error) return log('cleanupTokens: error removing expired tokens. %o', error);

    log(`Cleaned up ${result} expired tokens`);
}

async function cleanupTmpVolume(containerInfo) {
    assert.strictEqual(typeof containerInfo, 'object');

    const cmd = 'find /tmp -type f -mtime +10 -exec rm -rf {} +'.split(' '); // 10 day old files

    log(`cleanupTmpVolume ${JSON.stringify(containerInfo.Names)}`);

    const [error, execContainer] = await safe(gConnection.getContainer(containerInfo.Id).exec({ Cmd: cmd, AttachStdout: true, AttachStderr: true, Tty: false }));
    if (error) throw new BoxError(BoxError.DOCKER_ERROR, `Failed to exec container: ${error.message}`);

    const [startError, stream] = await safe(execContainer.start({ hijack: true }));
    if (startError) throw new BoxError(BoxError.DOCKER_ERROR, `Failed to start exec container: ${startError.message}`);

    gConnection.modem.demuxStream(stream, process.stdout, process.stderr);

    return new Promise((resolve, reject) => {
        stream.on('error', (streamError) => reject(new BoxError(BoxError.DOCKER_ERROR, `Failed to cleanup in exec container: ${streamError.message}`)));
        stream.on('end', resolve);
    });
}

async function cleanupDockerVolumes() {
    log('Cleaning up docker volumes');

    const [error, containers] = await safe(gConnection.listContainers({ all: 0 }));
    if (error) throw new BoxError(BoxError.DOCKER_ERROR, error);

    for (const container of containers) {
        await safe(cleanupTmpVolume(container), { debug: log }); // intentionally ignore error
    }

    log('Cleaned up docker volumes');
}

export default {
    cleanupTokens,
    cleanupDockerVolumes
};
