import { prisma } from "@/lib/db";
import { eventBus } from "@/lib/events/bus";
import { buildAndPush } from "@/lib/docker/build";
import { deployQueue, type BuildJob } from "@/lib/queue";

export async function runBuild(data: BuildJob): Promise<void> {
  const dep = await prisma.deployHistory.findUnique({
    where: { id: data.deployId },
    include: { project: true },
  });
  if (!dep) throw new Error("deploy not found");

  await prisma.deployHistory.update({
    where: { id: dep.id },
    data: { status: "building" },
  });
  eventBus.emit({ type: "deploy.update", deployId: dep.id, status: "building" });

  const result = await buildAndPush({
    contextDir: dep.project.path,
    imageTag: data.imageTag,
    onLine: (line) => eventBus.emit({ type: "deploy.log", deployId: dep.id, line }),
  });

  if (!result.ok) {
    await prisma.deployHistory.update({
      where: { id: dep.id },
      data: {
        status: "failed",
        finishedAt: new Date(),
        errorMsg: "build_or_push_failed",
        logBlob: result.logTail,
      },
    });
    eventBus.emit({ type: "deploy.update", deployId: dep.id, status: "failed" });
    return;
  }

  await prisma.deployHistory.update({
    where: { id: dep.id },
    data: { logBlob: result.logTail },
  });

  if (!dep.project.deployTargetId) {
    await prisma.deployHistory.update({
      where: { id: dep.id },
      data: {
        status: "failed",
        finishedAt: new Date(),
        errorMsg: "no_deploy_target",
      },
    });
    eventBus.emit({ type: "deploy.update", deployId: dep.id, status: "failed" });
    return;
  }

  await deployQueue.add("deploy", {
    deployId: dep.id,
    projectId: dep.projectId,
    targetId: dep.project.deployTargetId,
    imageTag: data.imageTag,
  });
}
