import { getMailAuthUrlForCurrentRequest, getSessionUser } from "@/lib/auth";
import { createMailboxMessage } from "@/lib/official-mail";

export const runtime = "nodejs";

function parseUploadIdList(value: FormDataEntryValue | null) {
  return String(value ?? "")
    .split(",")
    .map((item) => Number(item.trim()))
    .filter((item) => Number.isInteger(item) && item > 0);
}

function extractErrorDetail(message: string, prefix: string) {
  if (!message.startsWith(prefix)) {
    return "";
  }

  return message.slice(prefix.length).trim().slice(0, 240);
}

function buildComposeErrorRedirect(error: unknown) {
  if (error instanceof Error && error.message === "compose-required") {
    return "/mail?view=compose&error=compose-required";
  }

  if (error instanceof Error && error.message === "invalid-recipient") {
    return "/mail?view=compose&error=invalid-recipient";
  }

  if (
    error instanceof Error &&
    (error.message === "mailbox-auth-missing" || error.message === "mailbox-auth-invalid")
  ) {
    return "/mail?view=compose&error=mailbox-auth";
  }

  if (error instanceof Error && error.message === "free-send-limit-daily") {
    return "/mail?view=compose&error=free-send-limit-daily";
  }

  if (error instanceof Error && error.message.startsWith("send-cooldown-active:")) {
    const detail = extractErrorDetail(error.message, "send-cooldown-active:");
    return `/mail?view=compose&error=send-cooldown-active${detail ? `&details=${encodeURIComponent(detail)}` : ""}`;
  }

  if (error instanceof Error && error.message.startsWith("mailbox-smtp-failed:")) {
    const detail = extractErrorDetail(error.message, "mailbox-smtp-failed:");
    return `/mail?view=compose&error=smtp-failed${detail ? `&details=${encodeURIComponent(detail)}` : ""}`;
  }

  if (error instanceof Error && error.message.startsWith("mailbox-imap-failed:")) {
    const detail = extractErrorDetail(error.message, "mailbox-imap-failed:");
    return `/mail?view=compose&error=imap-failed${detail ? `&details=${encodeURIComponent(detail)}` : ""}`;
  }

  return "/mail?view=compose&error=compose-failed";
}

export async function POST(request: Request) {
  const user = await getSessionUser();

  if (!user) {
    return Response.json(
      { redirectTo: await getMailAuthUrlForCurrentRequest("/login") },
      { status: 401 },
    );
  }

  const formData = await request.formData();
  const to = String(formData.get("to") ?? "");
  const cc = String(formData.get("cc") ?? "");
  const bcc = String(formData.get("bcc") ?? "");
  const subject = String(formData.get("subject") ?? "");
  const body = String(formData.get("body") ?? "");
  const bodyHtml = String(formData.get("bodyHtml") ?? "");
  const sendIndividually = String(formData.get("sendIndividually") ?? "") === "1";
  const attachmentUploadIds = parseUploadIdList(formData.get("attachmentUploadIds"));
  const attachmentFiles = formData
    .getAll("attachmentFiles")
    .filter((entry): entry is File => entry instanceof File);
  const inlineImageUploadIds = parseUploadIdList(formData.get("inlineImageUploadIds"));
  const encoder = new TextEncoder();

  const stream = new ReadableStream({
    async start(controller) {
      const writeEvent = (event: object) => {
        controller.enqueue(encoder.encode(`${JSON.stringify(event)}\n`));
      };

      try {
        if (
          attachmentUploadIds.length === 0 &&
          attachmentFiles.length === 0 &&
          inlineImageUploadIds.length === 0
        ) {
          writeEvent({ stage: "sending", type: "stage" });
        }

        const result = await createMailboxMessage(user.email, {
          attachmentUploadIds,
          bcc,
          body,
          bodyHtml,
          cc,
          inlineImageUploadIds,
          intent: "send",
          onStageChange: async (stage) => {
            writeEvent({ stage, type: "stage" });
          },
          onUploadProgress: async (snapshot) => {
            writeEvent({ snapshot, type: "upload-progress" });
          },
          rawAttachmentFiles: await Promise.all(
            attachmentFiles.map(async (file) => ({
              buffer: Buffer.from(await file.arrayBuffer()),
              contentType: file.type || "application/octet-stream",
              filename: file.name || "attachment",
              sizeBytes: file.size,
            })),
          ),
          sendIndividually,
          subject,
          to,
          waitForDelivery: true,
        });

        writeEvent({
          redirectTo: result.messageId
            ? `/mail?folder=${result.folder}&message=${result.messageId}&success=${result.success}`
            : `/mail?folder=${result.folder}&success=${result.success}`,
          type: "done",
        });
      } catch (error) {
        writeEvent({
          redirectTo: buildComposeErrorRedirect(error),
          type: "error",
        });
      } finally {
        controller.close();
      }
    },
  });

  return new Response(stream, {
    headers: {
      "Cache-Control": "no-cache, no-transform",
      "Content-Type": "application/x-ndjson; charset=utf-8",
      "X-Accel-Buffering": "no",
    },
  });
}
