import { NextResponse } from "next/server";
import { PrismaClient } from "@prisma/client";
import type { FormBlockProps, FormFieldConfig } from "@/features/editor/state/editorStore";
import { encryptJson } from "@/features/auth/authCrypto";

const prisma = new PrismaClient() as any;

function buildSensitiveFieldNameSet(config: FormBlockProps | null): Set<string> {
  const result = new Set<string>();
  const fields: FormFieldConfig[] = Array.isArray(config?.fields) ? (config!.fields as FormFieldConfig[]) : [];

  for (const field of fields) {
    const name = (field.name ?? "").toLowerCase();
    const label = (field.label ?? "").toLowerCase();
    if (!name) continue;

    const isEmail =
      field.type === "email" ||
      name.includes("email") ||
      label.includes("email") ||
      label.includes("이메일");

    if (isEmail) {
      result.add(field.name);
      continue;
    }

    const isPhone =
      name.includes("phone") ||
      name.includes("tel") ||
      name.includes("mobile") ||
      label.includes("전화") ||
      label.includes("연락처") ||
      label.includes("휴대폰");

    if (isPhone) {
      result.add(field.name);
      continue;
    }

    const isBirth =
      name.includes("birth") ||
      name.includes("birthday") ||
      name.includes("dob") ||
      label.includes("생년월일") ||
      label.includes("생일");

    if (isBirth) {
      result.add(field.name);
      continue;
    }
  }

  return result;
}

async function persistFormSubmission(formData: FormData, config: FormBlockProps | null) {
  const projectSlugRaw = formData.get("__projectSlug");
  let projectSlug: string | null = null;

  if (typeof projectSlugRaw === "string" && projectSlugRaw.trim() !== "") {
    projectSlug = projectSlugRaw.trim();
  } else if (config?.extraParams && typeof config.extraParams.projectSlug === "string") {
    const v = config.extraParams.projectSlug.trim();
    if (v !== "") {
      projectSlug = v;
    }
  }

  const sensitiveNames = buildSensitiveFieldNameSet(config);

  formData.forEach((_, key) => {
    if (key === "__config" || key === "__projectSlug") {
      return;
    }

    const lower = key.toLowerCase();

    const isEmailField =
      lower.includes("email") ||
      lower.includes("e-mail") ||
      lower.includes("이메일");

    const isPhoneField =
      lower.includes("phone") ||
      lower.includes("tel") ||
      lower.includes("mobile") ||
      lower.includes("전화") ||
      lower.includes("연락처") ||
      lower.includes("휴대폰");

    const isBirthField =
      lower.includes("birth") ||
      lower.includes("birthday") ||
      lower.includes("birthdate") ||
      lower.includes("dob") ||
      lower.includes("생년월일") ||
      lower.includes("생일");

    if (isEmailField || isPhoneField || isBirthField) {
      sensitiveNames.add(key);
    }
  });
  const payloadJson: Record<string, string> = {};
  const sensitivePayload: Record<string, string> = {};

  formData.forEach((value, key) => {
    if (key === "__config" || key === "__projectSlug") {
      return;
    }

    const strValue = String(value);

    if (sensitiveNames.has(key)) {
      sensitivePayload[key] = strValue;
    } else {
      payloadJson[key] = strValue;
    }
  });

  let sensitiveEnc: string | null = null;
  if (Object.keys(sensitivePayload).length > 0) {
    sensitiveEnc = await encryptJson(sensitivePayload);
  }

  let projectId: string | null = null;
  let userId: string | null = null;

  if (projectSlug) {
    const project = await prisma.project.findUnique({ where: { slug: projectSlug } });
    if (project) {
      projectId = project.id;
      userId = project.userId ?? null;
    }
  }

  await prisma.formSubmission.create({
    data: {
      projectSlug: projectSlug ?? "",
      projectId,
      userId,
      payloadJson,
      sensitiveEnc,
      metaJson: null,
    },
  });
}

export async function POST(req: Request) {
  const formData = await req.formData();

  const name = formData.get("name");
  const email = formData.get("email");
  const message = formData.get("message");

  const rawConfig = formData.get("__config");
  let config: FormBlockProps | null = null;
  if (typeof rawConfig === "string") {
    try {
      config = JSON.parse(rawConfig) as FormBlockProps;
    } catch {
      config = null;
    }
  }

  const submitTarget = config?.submitTarget ?? "internal";
  const successMessage = config?.successMessage;
  const errorMessage = config?.errorMessage;

  if (submitTarget === "internal") {
    await persistFormSubmission(formData, config);
    console.log("[forms/submit][internal]", { name, email, message });
    return NextResponse.json({ ok: true, message: successMessage });
  }

  if (submitTarget === "both") {
    await persistFormSubmission(formData, config);
    console.log("[forms/submit][internal]", { name, email, message });
  }

  if (submitTarget === "webhook" || submitTarget === "both") {
    const destinationUrl = config?.destinationUrl;
    if (!destinationUrl) {
      return NextResponse.json(
        { ok: false, error: "destinationUrl_missing", message: errorMessage },
        { status: 400 },
      );
    }

    const payloadFormat = config?.payloadFormat ?? "form";

    let body: string;
    const headers: Record<string, string> = {
      ...(config?.headers ?? {}),
    };

    if (payloadFormat === "json") {
      const jsonPayload: Record<string, string> = {};
      formData.forEach((value, key) => {
        if (key !== "__config") {
          jsonPayload[key] = String(value);
        }
      });

      if (config?.extraParams) {
        Object.entries(config.extraParams).forEach(([k, v]) => {
          jsonPayload[k] = v;
        });
      }

      headers["Content-Type"] = "application/json";
      body = JSON.stringify(jsonPayload);
    } else {
      // 기본 동작: FormData -> x-www-form-urlencoded 로 변환 (많은 webhook/Apps Script가 이 형식을 사용)
      const payload = new URLSearchParams();
      formData.forEach((value, key) => {
        if (key !== "__config") {
          payload.append(key, String(value));
        }
      });

      if (config?.extraParams) {
        Object.entries(config.extraParams).forEach(([k, v]) => {
          payload.append(k, v);
        });
      }

      headers["Content-Type"] = "application/x-www-form-urlencoded";
      body = payload.toString();
    }

    try {
      const res = await fetch(destinationUrl, {
        method: config?.method ?? "POST",
        headers,
        body,
      });

      if (!res.ok) {
        console.error("[forms/submit][webhook] remote error", res.status, await res.text().catch(() => ""));
        return NextResponse.json(
          { ok: false, error: "webhook_failed", message: errorMessage },
          { status: 502 },
        );
      }
    } catch (error) {
      console.error("[forms/submit][webhook] fetch error", error);
      return NextResponse.json(
        { ok: false, error: "webhook_exception", message: errorMessage },
        { status: 500 },
      );
    }

    console.log("[forms/submit][webhook] forwarded", { name, email, message, destinationUrl });
    return NextResponse.json({ ok: true, message: successMessage });
  }

  // 그 외 알 수 없는 모드는 internal 과 동일하게 처리
  console.warn("[forms/submit] unknown submitTarget, fallback to internal", submitTarget);
  console.log("[forms/submit][internal]", { name, email, message });
  return NextResponse.json({ ok: true, message: successMessage });
}
