import nodemailer from "nodemailer";
import { z } from "zod";
import prisma from "@/server/db/prisma";
import { HttpError } from "@/server/http/errors";
import { parseJson } from "@/server/http/parse";
import { ok } from "@/server/http/response";
import { withErrorHandling } from "@/server/http/withErrorHandling";

async function verifyRecaptcha(token: string, secretKey: string) {
  const response = await fetch("https://www.google.com/recaptcha/api/siteverify", {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
    body: `secret=${secretKey}&response=${token}`,
  });

  const data = await response.json();
  return data.success;
}

/**
 * Escapes HTML special characters to prevent XSS/injection in email templates.
 */
function escapeHtml(str: string): string {
  return str
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#039;");
}

const ContactRequestSchema = z.object({
  name: z.string().min(1).max(100),
  email: z.string().email().max(254),
  subject: z.string().min(1).max(200),
  message: z.string().min(1).max(5000),
  recaptchaToken: z.string().min(1),
});

export const POST = withErrorHandling(async (request: Request) => {
  const { name, email, subject, message, recaptchaToken } = await parseJson(request, ContactRequestSchema);

  const settings = await prisma.emailSettings.findFirst({
    select: {
      smtpHost: true,
      smtpPort: true,
      smtpUser: true,
      smtpPassword: true,
      companyEmail: true,
      companyName: true,
      confirmationTemplate: true,
      notificationTemplate: true,
    },
  });
  if (!settings) throw new HttpError("Email settings not configured", { status: 500 });

  const googleSettings = await prisma.googleSettings.findFirst({
    select: {
      recaptchaSecretKey: true,
    },
  });
  if (!googleSettings?.recaptchaSecretKey) throw new HttpError("reCAPTCHA not configured", { status: 500 });

  const isValidRecaptcha = await verifyRecaptcha(recaptchaToken, googleSettings.recaptchaSecretKey);
  if (!isValidRecaptcha) throw new HttpError("Invalid reCAPTCHA token", { status: 400 });

  const transporter = nodemailer.createTransport({
    host: settings.smtpHost,
    port: settings.smtpPort,
    secure: settings.smtpPort === 465,
    auth: {
      user: settings.smtpUser,
      pass: settings.smtpPassword,
    },
  });

  // Sanitize user input before inserting into HTML templates
  const safeName = escapeHtml(name);
  const safeEmail = escapeHtml(email);
  const safeSubject = escapeHtml(subject);
  const safeMessage = escapeHtml(message);

  const confirmationTemplate = settings.confirmationTemplate
    .replace("{name}", safeName)
    .replace("{email}", safeEmail)
    .replace("{subject}", safeSubject)
    .replace("{message}", safeMessage);

  await transporter.sendMail({
    from: `"${settings.companyName}" <${settings.smtpUser}>`,
    to: email,
    subject: `Thank you for contacting ${settings.companyName}`,
    html: confirmationTemplate,
  });

  const notificationTemplate = settings.notificationTemplate
    .replace("{name}", safeName)
    .replace("{email}", safeEmail)
    .replace("{subject}", safeSubject)
    .replace("{message}", safeMessage);

  await transporter.sendMail({
    from: `"${settings.companyName}" <${settings.smtpUser}>`,
    to: settings.companyEmail,
    subject: `New Contact Form Submission: ${subject}`,
    html: notificationTemplate,
  });

  return ok({ message: "Message sent successfully" });
});
