
import assert from 'node:assert/strict';
import fs from 'node:fs';
import path from 'node:path';
import superagent from '@cloudron/superagent';

import { app, clearCache, click, cloudronCli, goto, LOCATION, sendKeys, setupBrowser, takeScreenshot, teardownBrowser, waitFor } from '@cloudron/charlie';

/* global it, describe, before, after, afterEach */

describe('Application life cycle test', function () {
    const BUCKET = 'cloudrontestbucket';

    before(setupBrowser);
    after(teardownBrowser);

    afterEach(async function () {
        await takeScreenshot(this.currentTest);
    });

    async function confirmLicense() {
        try {
            await waitFor('css=#acknowledge-confirm', { timeout: 10000 });
            await click('css=#acknowledge-confirm');
        } catch {
            // license modal not shown
        }
    }

    async function login(accessKey, secretKey, acceptLicense = false) {
        await goto(`https://${app.fqdn}/login`, 'css=#accessKey');
        await sendKeys('css=#accessKey', accessKey);
        await sendKeys('css=#secretKey', secretKey);
        await click('css=#do-login');

        if (acceptLicense) await confirmLicense();

        await waitFor('Create Bucket');
    }

    async function addBucket() {
        await click('Create Bucket');
        await sendKeys('css=#bucket-name', BUCKET);
        await click('css=#create-bucket');
        await waitFor(`xpath=//h1[contains(text(), "${BUCKET}")]`);
    }

    async function checkBucket() {
        await waitFor(`xpath=//h1[contains(text(), "${BUCKET}")]`);
    }

    async function checkRedirect() {
        const response = await superagent.get(`https://${app.secondaryDomains[0].fqdn}`).set('User-Agent', 'Mozilla/5.0').redirects(0).ok(() => true);
        assert.strictEqual(response.status, 307);
        assert.strictEqual(response.headers.location, `https://${app.fqdn}`);
    }

    async function checkApi() {
        const response = await superagent.get(`https://${app.secondaryDomains[0].fqdn}`).ok(() => true);
        assert.strictEqual(response.status, 403);
        assert.ok(response.body.toString('utf8').includes('<Code>AccessDenied</Code>'));
    }

    async function changeAdminCredentials() {
        let data = fs.readFileSync(path.join(import.meta.dirname, '../env.sh.template'), 'utf8');
        data += '\nexport MINIO_ROOT_USER=minioakey\nexport MINIO_ROOT_PASSWORD=minioskey\n';
        fs.writeFileSync('/tmp/env.sh', data);
        await cloudronCli.push('/tmp/env.sh', '/app/data/env.sh');
        await cloudronCli.restart();
    }

    it('install app', () => cloudronCli.install({ secondaryDomains: { API_SERVER_DOMAIN: `${LOCATION}-api` } }));

    it('can admin login', login.bind(null, 'minioadmin', 'minioadmin', true));
    it('can add bucket', addBucket);
    it('can logout', clearCache);
    it('does redirect', checkRedirect);
    it('check api', checkApi);

    it('can change admin credentials', changeAdminCredentials);

    it('can restart app', cloudronCli.restart);

    it('can admin login', login.bind(null, 'minioakey', 'minioskey', false));
    it('has bucket', checkBucket);
    it('can logout', clearCache);
    it('does redirect', checkRedirect);
    it('check api', checkApi);

    it('backup app', cloudronCli.createBackup);
    it('restore app', cloudronCli.restoreFromLatestBackup);

    it('can admin login', login.bind(null, 'minioakey', 'minioskey', false));
    it('has bucket', checkBucket);
    it('can logout', clearCache);

    it('does redirect', checkRedirect);
    it('check api', checkApi);

    it('move to different location', cloudronCli.changeLocation);

    it('can admin login', login.bind(null, 'minioakey', 'minioskey', true));
    it('has bucket', checkBucket);
    it('can logout', clearCache);

    it('does redirect', checkRedirect);
    it('check api', checkApi);

    it('uninstall app', cloudronCli.uninstall);
});
