import 'reflect-metadata';
import * as fs from 'node:fs';
import asyncRetry from 'async-retry';
// eslint-disable-next-line import/no-extraneous-dependencies -- cypress SHOULD be a dev dependency
import { defineConfig } from 'cypress';
import { initSeed } from './integration-tests/testkit/seed';

if (!process.env.RUN_AGAINST_LOCAL_SERVICES) {
  const dotenv = await import('dotenv');
  dotenv.config({ path: import.meta.dirname + '/integration-tests/.env' });
}

if (process.env.RUN_AGAINST_LOCAL_SERVICES === '1') {
  const dotenv = await import('dotenv');
  dotenv.config({ path: import.meta.dirname + '/packages/services/server/.env.template' });
  // It seems that this has to be set in the environment that the cypress cli is executed from.
  // process.env.CYPRESS_BASE_URL = process.env.CYPRESS_BASE_URL ?? 'http://localhost:3000';
}

const isCI = Boolean(process.env.CI);

export const seed = initSeed();

export default defineConfig({
  video: isCI,
  screenshotOnRunFailure: isCI,
  defaultCommandTimeout: 15_000, // sometimes the app takes longer to load, especially in the CI
  retries: 2,
  viewportWidth: 1280,
  viewportHeight: 720,
  e2e: {
    setupNodeEvents(on) {
      on('task', {
        async seedOrg() {
          const owner = await seed.createOwner();
          const org = await owner.createOrg();

          return {
            slug: org.organization.slug,
            refreshToken: owner.ownerRefreshToken,
            email: owner.ownerEmail,
          };
        },
        async purgeOIDCDomains() {
          await seed.purgeOIDCDomains();
          return {};
        },
        async forgeOIDCDNSChallenge(orgSlug: string) {
          await seed.forgeOIDCDNSChallenge(orgSlug);
          return {};
        },
        async seedTarget() {
          const owner = await seed.createOwner();
          const org = await owner.createOrg();
          const project = await org.createProject();
          const slug = `${org.organization.slug}/${project.project.slug}/${project.target.slug}`;
          return {
            slug,
            refreshToken: owner.ownerRefreshToken,
            email: owner.ownerEmail,
          };
        },
        async getEmailConfirmationLink(input: string | { email: string; now: number }) {
          const url = await seed.pollForEmailVerificationLink(input);
          return url.pathname + url.search;
        },
      });

      on('after:spec', (_, results) => {
        if (results && results.video) {
          // Do we have failures for any retry attempts?
          const failures = results.tests.some(test =>
            test.attempts.some(attempt => attempt.state === 'failed'),
          );
          if (!failures) {
            // delete the video if the spec passed and no tests retried
            fs.unlinkSync(results.video);
          }
        }
      });
    },
    env: {
      RUN_AGAINST_LOCAL_SERVICES: process.env.RUN_AGAINST_LOCAL_SERVICES || '0',
    },
  },
});
