import "server-only";

import { getActiveAccountId } from "@/lib/account-context";
import { prisma } from "@/lib/db";
import type { JobProgressDetail } from "./types";
import { isJobCancelled, JobCancelledError } from "./cancel";

export async function trackAiTask<T>(label: string, task: () => Promise<T>): Promise<T> {
  const accountId = await getActiveAccountId();
  if (!accountId) return task();

  const detail: JobProgressDetail = {
    summary: `${label}執行中…`,
    phase: "ai-work",
    tasks: [{ id: "ai-work", label, status: "running", startedAt: Date.now() }],
  };
  const job = await prisma.backgroundJob.create({
    data: {
      accountId,
      type: "ai-task",
      label,
      status: "running",
      progress: detail.summary,
      progressDetail: JSON.stringify(detail),
    },
  });

  try {
    const result = await task();
    if (await isJobCancelled(job.id)) {
      throw new JobCancelledError();
    }
    detail.summary = `${label}完成`;
    if (detail.tasks?.[0]) detail.tasks[0].status = "done";
    await prisma.backgroundJob.update({
      where: { id: job.id },
      data: {
        status: "completed",
        progress: detail.summary,
        progressDetail: JSON.stringify(detail),
        completedAt: new Date(),
      },
    });
    return result;
  } catch (error) {
    if (error instanceof JobCancelledError || await isJobCancelled(job.id)) {
      await prisma.backgroundJob.update({
        where: { id: job.id },
        data: { status: "cancelled", progress: "已停止", completedAt: new Date() },
      });
      throw new JobCancelledError("任務已由使用者停止");
    }
    const message = error instanceof Error ? error.message : `${label}失敗`;
    detail.summary = `${label}失敗`;
    if (detail.tasks?.[0]) {
      detail.tasks[0].status = "failed";
      detail.tasks[0].error = message;
    }
    await prisma.backgroundJob.update({
      where: { id: job.id },
      data: {
        status: "failed",
        progress: detail.summary,
        progressDetail: JSON.stringify(detail),
        error: message,
        completedAt: new Date(),
      },
    });
    throw error;
  }
}
