import { ProjectResources, EnvironmentConfig } from "../lib";
import { BASIC_CONFIG, CDK_OUTDIR, createBasicProjectResources } from "./utils";
import { mockClient } from "aws-sdk-client-mock";
import { MWAA, GetEnvironmentCommand } from "@aws-sdk/client-mwaa";
import * as fs from "fs";

const mwaaMock = mockClient(MWAA);
beforeEach(() => {
  mwaaMock.reset();
  mwaaMock.on(GetEnvironmentCommand).resolves({
    Environment: {
      ExecutionRoleArn: "arn:aws:iam::123456:role/airflow-execution-role",
    },
  });
});

test("select environment", async () => {
  const project = await createBasicProjectResources();
  expect(project.env).toEqual(BASIC_CONFIG);
});

test("bucket name", async () => {
  const project = await createBasicProjectResources();
  expect(project.bucketName()).toEqual("test-project.test-env.123456");
});

test("ecr url", async () => {
  const project = await createBasicProjectResources();
  expect(project.ecrUrl()).toEqual(
    "123456.dkr.ecr.us-west-2.amazonaws.com/test-project.test-env:test-branch-asdf"
  );
});

test("s3 url", async () => {
  const project = await createBasicProjectResources();
  expect(project.s3UrlForPath(["", ""])).toEqual(
    "s3://test-project.test-env.123456/test-branch"
  );
  expect(project.s3UrlForPath(["some", "path", "segments"])).toEqual(
    "s3://test-project.test-env.123456/test-branch/some/path/segments"
  );
});

test("sagemaker execution role", async () => {
  const project = await createBasicProjectResources();
  expect(project.sagemakerExecutionRole()).toEqual(
    "arn:aws:iam::123456:role/xJZp1OZbjUdwSrxR-sm-execution-role-us-west-2"
  );

  const envConfig: EnvironmentConfig = {
    accountId: "123456",
    accountName: "test-account",
    defaultRegion: "us-west-2",
    airflow: {
      mwaaEnvironmentName: "test-mwaa-env",
    },
    sagemaker: {
      executionRole: "arn:aws:iam::123456:role/custom-execution-role",
    },
  };
  const customProjectResources = new ProjectResources({
    name: "test-project",
    envName: "test-env",
    env: envConfig,
    branch: "test-branch",
    commitHash: "asdf",
    cdkOutdir: "/tmp/test-conductor-cdk/",
  });
  await customProjectResources.createCoreStack();
  expect(customProjectResources.sagemakerExecutionRole()).toEqual(
    "arn:aws:iam::123456:role/custom-execution-role"
  );
});

test("unload role chain", async () => {
  const project = await createBasicProjectResources();
  expect(() => project.unloadRoleChain()).toThrowError(
    "Cannot unload from Redshift if no unload role is provided by your RedshiftConfig."
  );

  const envConfig: EnvironmentConfig = {
    accountId: "123456",
    accountName: "test-account",
    defaultRegion: "us-west-2",
    airflow: {
      mwaaEnvironmentName: "test-mwaa-env",
    },
    redshift: {
      host: "redshift.amazon.com",
      dbName: "test-db",
      dbUser: "test-user",
      unloadRole: "arn:aws:iam::123456:role/custom-unload-role",
    },
  };
  const customProjectResources = new ProjectResources({
    name: "test-project",
    envName: "test-env",
    env: envConfig,
    branch: "test-branch",
    commitHash: "asdf",
    cdkOutdir: "/tmp/test-conductor-cdk/",
  });
  await customProjectResources.createCoreStack();
  expect(customProjectResources.unloadRoleChain()).toEqual(
    "arn:aws:iam::123456:role/custom-unload-role,arn:aws:iam::123456:role/xJZp1OZbjUdwSrxR-unload-role"
  );
});

test("project bucket access", async () => {
  const envConfig: EnvironmentConfig = {
    accountId: "123456",
    accountName: "test-account",
    defaultRegion: "us-west-2",
    airflow: {
      mwaaEnvironmentName: "test-mwaa-env",
    },
    projectBucket: {
      airflowExecutionRoleAccess: true,
      readAccessRoles: ["arn:aws:iam::123456:role/external-role"],
    },
  };
  const customProjectResources = new ProjectResources({
    name: "test-project",
    envName: "test-env",
    env: envConfig,
    branch: "test-branch",
    commitHash: "asdf",
    cdkOutdir: "/tmp/test-conductor-cdk/",
  });
  await customProjectResources.createCoreStack();

  // On error.
  mwaaMock.reset();
  mwaaMock.on(GetEnvironmentCommand).rejects("environment not found");
  await expect(async () => {
    const customProjectResources = new ProjectResources({
      name: "test-project",
      envName: "test-env",
      env: envConfig,
      branch: "test-branch",
      commitHash: "asdf",
      cdkOutdir: "/tmp/test-conductor-cdk/",
    });
    await customProjectResources.createCoreStack();
  }).rejects.toThrowError("environment not found");
});

test("synth", async () => {
  fs.rmSync(CDK_OUTDIR, { recursive: true });
  const project = await createBasicProjectResources();
  project.synth();
  expect(fs.readdirSync(CDK_OUTDIR)).toContain("cdk.out");
});
