import { fork } from "node:child_process";
import {
  show,
  listMachineUsers,
  getMachineUserToken,
  createWorkspace,
  deleteWorkspace,
  deploy,
} from "@tailor-platform/sdk/cli";
import type { TestProject } from "vitest/node";

declare module "vitest" {
  export interface ProvidedContext {
    url: string;
    token: string;
  }
}

const APP_NAME = "template-app";

export async function setup(project: TestProject) {
  // In CI, the workspace is already deployed and seeded; reuse it as-is.
  // Do NOT deploy or re-seed: the E2E job may run against it at the same time,
  // and re-seeding would wipe its data. Tests create their own rows.
  // Locally (no env var), create, deploy, seed, and delete a throwaway workspace.
  const providedWorkspaceId = process.env.TAILOR_PLATFORM_WORKSPACE_ID;
  const ownsWorkspace = !providedWorkspaceId;
  let workspaceId: string;

  if (providedWorkspaceId) {
    workspaceId = providedWorkspaceId;
    console.log(`[integration] reusing workspace ${workspaceId} (no deploy/seed, no teardown)`);
  } else {
    console.log("[integration] creating throwaway workspace (deploy + seed, deleted on teardown)");
    const workspace = await createWorkspace({
      name: `${APP_NAME}-test-${Date.now()}`,
      region: "asia-northeast",
      organizationId: process.env.TAILOR_PLATFORM_ORGANIZATION_ID,
      folderId: process.env.TAILOR_PLATFORM_FOLDER_ID,
    });
    workspaceId = workspace.id;

    await deploy({ workspaceId, yes: true });

    await new Promise<void>((resolve, reject) => {
      const child = fork("seed/exec.mjs", [], {
        env: { ...process.env, TAILOR_PLATFORM_WORKSPACE_ID: workspaceId },
        stdio: "inherit",
      });
      child.on("close", (code) =>
        code === 0 ? resolve() : reject(new Error(`seed exited with code ${code}`)),
      );
    });
  }

  const app = await show({ workspaceId });
  const url = app.url;

  const machineUsers = await listMachineUsers({ workspaceId });
  const tokens = await getMachineUserToken({
    name: machineUsers[0].name,
    workspaceId,
  });
  const token = tokens.accessToken;

  project.provide("url", url);
  project.provide("token", token);

  return async () => {
    if (ownsWorkspace) {
      await deleteWorkspace({ workspaceId });
    }
  };
}
