import { NextResponse } from "next/server";

export const runtime = "nodejs";

const MAX_TOTAL_FILE_BYTES = 4 * 1024 * 1024;
const MAX_FILE_COUNT = 8;
const ALLOWED_EXTENSIONS = new Set(["pdf", "jww", "dwg", "dxf", "zip"]);
const ALLOWED_BUILDING_USES = new Set(["戸建住宅", "共同住宅", "店舗", "店舗併用住宅", "その他"]);
const ALLOWED_FLOORS = new Set(["平屋", "2階建", "3階建", "その他"]);
const ALLOWED_SEISMIC_GRADES = new Set(["未定", "等級1", "等級2", "等級3"]);
const ALLOWED_WIND_GRADES = new Set(["未定", "等級1", "等級2"]);
const ALLOWED_SERVICES = new Set([
  "構造計算（建物上部のみ）",
  "構造計算＋構造図作成",
  "相談して決めたい",
]);

function stringValue(formData: FormData, key: string, maxLength: number) {
  const value = formData.get(key);
  if (typeof value !== "string") return "";
  return value.trim().slice(0, maxLength);
}

function safeFilename(filename: string) {
  return filename.replace(/[\\/\u0000-\u001f\u007f]/g, "_").slice(0, 180) || "document";
}

function isValidEmail(value: string) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
}

function isIsoDate(value: string) {
  return /^\d{4}-\d{2}-\d{2}$/.test(value) && !Number.isNaN(Date.parse(`${value}T00:00:00Z`));
}

function badRequest(message: string) {
  return NextResponse.json({ message }, { status: 400 });
}

export async function POST(request: Request) {
  let formData: FormData;

  try {
    formData = await request.formData();
  } catch {
    return badRequest("送信内容を読み取れませんでした。入力内容をご確認ください。");
  }

  if (stringValue(formData, "website", 200)) {
    return NextResponse.json({ ok: true });
  }

  const company = stringValue(formData, "company", 120);
  const name = stringValue(formData, "name", 80);
  const email = stringValue(formData, "email", 254);
  const phone = stringValue(formData, "phone", 50);
  const buildingUse = stringValue(formData, "building-use", 40);
  const floors = stringValue(formData, "floors", 20);
  const area = stringValue(formData, "area", 30);
  const seismicGrade = stringValue(formData, "seismic-grade", 20);
  const windGrade = stringValue(formData, "wind-grade", 20);
  const requestedService = stringValue(formData, "requested-service", 80);
  const deadline = stringValue(formData, "deadline", 20);
  const message = stringValue(formData, "message", 5000);
  const privacyConsent = stringValue(formData, "privacy-consent", 20);
  const submissionId = stringValue(formData, "submission-id", 80);

  if (!company || !name || !email || !buildingUse || !floors || !area || !seismicGrade || !windGrade || !requestedService || !deadline || !message) {
    return badRequest("必須項目をすべて入力してください。");
  }
  if (!isValidEmail(email)) return badRequest("メールアドレスの形式をご確認ください。");
  if (!ALLOWED_BUILDING_USES.has(buildingUse) || !ALLOWED_FLOORS.has(floors)) {
    return badRequest("建物概要の選択内容をご確認ください。");
  }
  if (!ALLOWED_SEISMIC_GRADES.has(seismicGrade) || !ALLOWED_WIND_GRADES.has(windGrade)) {
    return badRequest("耐震等級・耐風等級の選択内容をご確認ください。");
  }
  if (!ALLOWED_SERVICES.has(requestedService)) {
    return badRequest("希望業務の選択内容をご確認ください。");
  }
  const numericArea = Number(area);
  if (!Number.isFinite(numericArea) || numericArea <= 0 || numericArea > 100000) {
    return badRequest("延べ面積をご確認ください。");
  }
  if (!isIsoDate(deadline)) return badRequest("初回構造図送付希望日をご確認ください。");
  if (privacyConsent !== "agreed") {
    return badRequest("プライバシーポリシーへの同意が必要です。");
  }

  const files = formData
    .getAll("documents")
    .filter((item): item is File => item instanceof File && item.size > 0);
  if (files.length > MAX_FILE_COUNT) {
    return badRequest(`添付ファイルは${MAX_FILE_COUNT}件以内にしてください。`);
  }

  let totalFileBytes = 0;
  for (const file of files) {
    totalFileBytes += file.size;
    const extension = file.name.split(".").pop()?.toLowerCase() ?? "";
    if (!ALLOWED_EXTENSIONS.has(extension)) {
      return badRequest("添付できる形式はPDF・JWW・DWG・DXF・ZIPです。");
    }
  }
  if (totalFileBytes > MAX_TOTAL_FILE_BYTES) {
    return badRequest("添付資料の合計サイズを4MB以内にしてください。");
  }

  const apiKey = process.env.RESEND_API_KEY;
  if (!apiKey) {
    return NextResponse.json(
      { message: "現在フォームの送信設定を確認しています。お急ぎの場合は info@kouzoudesk.com までご連絡ください。" },
      { status: 503 },
    );
  }

  const attachmentPayload = await Promise.all(
    files.map(async (file) => ({
      filename: safeFilename(file.name),
      content: Buffer.from(await file.arrayBuffer()).toString("base64"),
    })),
  );
  const fileNames = files.length > 0 ? files.map((file) => safeFilename(file.name)).join("、") : "なし";
  const subject = `構造計算・構造図作成のご相談｜${company}`;
  const text = [
    "KouzouDesk 構造計算・構造図作成相談",
    "",
    `会社名：${company}`,
    `担当者名：${name}`,
    `メールアドレス：${email}`,
    `電話番号：${phone || "未記入"}`,
    "",
    `建物用途：${buildingUse}`,
    `階数：${floors}`,
    `延べ面積：${area}㎡`,
    `耐震等級：${seismicGrade}`,
    `耐風等級：${windGrade}`,
    `希望業務：${requestedService}`,
    `初回構造図送付希望日：${deadline}`,
    `添付資料：${fileNames}`,
    "",
    "案件概要・相談内容：",
    message,
  ].join("\n");

  const deliveryResponse = await fetch("https://api.resend.com/emails", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${apiKey}`,
      "Content-Type": "application/json",
      "Idempotency-Key": `kouzoudesk-${submissionId || crypto.randomUUID()}`.slice(0, 256),
    },
    body: JSON.stringify({
      from: process.env.CONTACT_FROM_EMAIL || "KouzouDesk <noreply@kouzoudesk.com>",
      to: [process.env.CONTACT_TO_EMAIL || "info@kouzoudesk.com"],
      reply_to: email,
      subject,
      text,
      attachments: attachmentPayload,
    }),
  });

  if (!deliveryResponse.ok) {
    console.error("[contact] Email delivery failed", {
      status: deliveryResponse.status,
      requestId: deliveryResponse.headers.get("x-request-id"),
    });
    return NextResponse.json(
      { message: "送信できませんでした。時間をおいて再度お試しいただくか、info@kouzoudesk.com までご連絡ください。" },
      { status: 502 },
    );
  }

  return NextResponse.json({ ok: true });
}
