import { prisma } from "../lib/db";
import { createLogger } from "../lib/logger";
import { makeEc2Client, describeAllManagedInstances, terminateInstance, deleteKeyPairAws, deleteSecurityGroupAws } from "./ec2";

const log = createLogger("ORPHAN_CLEANUP");

export async function runOrphanCleanup() {
  log.info("Running orphan EC2 instance cleanup");

  const users = await prisma.user.findMany({
    where: {
      awsAccessKeyId: { not: null },
      awsSecretAccessKey: { not: null },
      awsRegion: { not: null },
    },
  });

  const activePreviews = await prisma.preview.findMany({
    where: { status: { notIn: ["STOPPED", "IGNORED"] }, instanceId: { not: null } },
    select: { id: true, instanceId: true },
  });
  const activeInstanceIds = new Set(activePreviews.map(p => p.instanceId!));

  for (const user of users) {
    try {
      const ec2 = makeEc2Client(user as any);
      const instances = await describeAllManagedInstances(ec2);

      for (const inst of instances) {
        const instanceId = inst.InstanceId;
        if (!instanceId) continue;

        const tags = Object.fromEntries((inst.Tags || []).map((t: any) => [t.Key, t.Value]));
        const previewId = parseInt(tags["pp:previewId"] || "0", 10);

        if (!activeInstanceIds.has(instanceId)) {
          log.info({ instanceId, previewId }, "Terminating orphan instance");
          try {
            const keyName = `pp-preview-${previewId}`;
            const sgName = `pp-preview-${previewId}`;
            await deleteKeyPairAws(ec2, keyName);
            await terminateInstance(ec2, instanceId);
            setTimeout(() => deleteSecurityGroupAws(ec2, sgName), 30_000);
          } catch (e) {
            log.warn({ e, instanceId }, "Failed to terminate orphan");
          }
        }
      }
    } catch (e) {
      log.warn({ e, userId: user.id }, "Failed to check orphans for user");
    }
  }

  log.info("Orphan cleanup complete");
}
