"use server";

import { headers } from "next/headers";
import { redirect } from "next/navigation";
import { eq } from "drizzle-orm";
import { z } from "zod";
import { db } from "@/lib/db/client";
import {
  researchApplications,
  researchProposals,
  researchStudiesTable,
} from "@/lib/db/schema";
import { sendTemplatedEmail } from "@/lib/email/send";
import { loadEnv } from "@/lib/env";
import { ipFromHeaders, rateLimitAsync } from "@/lib/rate-limit";

const applySchema = z.object({
  studySlug: z.string().max(200).optional().default(""),
  name: z.string().min(2).max(200),
  email: z.string().email().max(200),
  institution: z.string().max(300).optional().default(""),
  country: z.string().max(200).optional().default(""),
  professionalRole: z.string().max(200).optional().default(""),
  orcidUrl: z.string().max(500).optional().default(""),
  linkedinUrl: z.string().max(500).optional().default(""),
  rolePreference: z.string().max(200).optional().default(""),
  experience: z.string().max(4000).optional().default(""),
  motivation: z.string().min(10).max(4000),
  honeypot: z.string().max(500).optional().default(""),
});

export type ApplyState = {
  ok: boolean;
  message?: string;
  fieldErrors?: Record<string, string>;
};

/**
 * Member-facing action behind /products/research/studies/[slug]/apply.
 * Persists the application, emails the applicant a receipt and the admin
 * team a notification. Rate-limited by IP to discourage abuse.
 */
export async function submitStudyApplication(
  _prev: ApplyState,
  formData: FormData,
): Promise<ApplyState> {
  // Honeypot — bot form-fills usually populate the hidden "website" field.
  const honey = formData.get("website");
  if (typeof honey === "string" && honey.trim().length > 0) {
    return { ok: true, message: "Thanks — we'll be in touch." };
  }

  const ip = ipFromHeaders(await headers());
  const limit = await rateLimitAsync({
    key: `research-apply:${ip}`,
    max: 6,
    windowMs: 60 * 60 * 1000,
  });
  if (!limit.ok) {
    return {
      ok: false,
      message: "Too many applications from this location. Try again later.",
    };
  }

  const parsed = applySchema.safeParse({
    studySlug: formData.get("studySlug") ?? "",
    name: formData.get("name") ?? "",
    email: formData.get("email") ?? "",
    institution: formData.get("institution") ?? "",
    country: formData.get("country") ?? "",
    professionalRole: formData.get("professionalRole") ?? "",
    orcidUrl: formData.get("orcidUrl") ?? "",
    linkedinUrl: formData.get("linkedinUrl") ?? "",
    rolePreference: formData.get("rolePreference") ?? "",
    experience: formData.get("experience") ?? "",
    motivation: formData.get("motivation") ?? "",
  });
  if (!parsed.success) {
    const fieldErrors: Record<string, string> = {};
    for (const issue of parsed.error.issues) {
      fieldErrors[issue.path.join(".")] = issue.message;
    }
    return {
      ok: false,
      fieldErrors,
      message: "Please correct the highlighted fields.",
    };
  }
  const data = parsed.data;

  let studyId: string | null = null;
  let studyTitle = "general collaboration interest";
  if (data.studySlug) {
    const [s] = await db
      .select({ id: researchStudiesTable.id, title: researchStudiesTable.title })
      .from(researchStudiesTable)
      .where(eq(researchStudiesTable.slug, data.studySlug))
      .limit(1);
    if (s) {
      studyId = s.id;
      studyTitle = s.title;
    }
  }

  const [inserted] = await db
    .insert(researchApplications)
    .values({
      studyId,
      name: data.name,
      email: data.email.toLowerCase(),
      institution: data.institution,
      country: data.country,
      professionalRole: data.professionalRole,
      orcidUrl: data.orcidUrl || null,
      linkedinUrl: data.linkedinUrl || null,
      rolePreference: data.rolePreference,
      experience: data.experience,
      motivation: data.motivation,
      status: "pending",
    })
    .returning({ id: researchApplications.id });

  const env = loadEnv();
  const reviewUrl = `${env.nextAuthUrl}/admin/research/applications/${inserted.id}`;

  // Fire-and-forget: don't let a flaky mailer block the UX.
  try {
    await sendTemplatedEmail({
      to: data.email,
      templateSlug: "research-application-received",
      variables: {
        name: data.name,
        studyTitle,
        rolePreference: data.rolePreference || "collaborator",
      },
    });
    await sendTemplatedEmail({
      to: env.adminNotifyEmails,
      templateSlug: "research-application-admin-notify",
      variables: {
        name: data.name,
        email: data.email,
        institution: data.institution,
        country: data.country,
        studyTitle,
        rolePreference: data.rolePreference || "collaborator",
        motivation: data.motivation,
        reviewUrl,
      },
    });
  } catch (err) {
    console.error("[research-apply] email failed", err);
  }

  redirect("/products/research/applications/thanks");
}

const proposalSchema = z.object({
  title: z.string().min(8).max(300),
  proposerName: z.string().min(2).max(200),
  email: z.string().email().max(200),
  institution: z.string().max(300).optional().default(""),
  country: z.string().max(200).optional().default(""),
  orcidUrl: z.string().max(500).optional().default(""),
  specialty: z.string().max(200).optional().default(""),
  background: z.string().min(30).max(8000),
  hypothesis: z.string().min(10).max(4000),
  design: z.string().max(4000).optional().default(""),
  resourcesNeeded: z.string().max(4000).optional().default(""),
  fundingStatus: z.string().max(500).optional().default(""),
  honeypot: z.string().max(500).optional().default(""),
});

export type ProposeState = {
  ok: boolean;
  message?: string;
  fieldErrors?: Record<string, string>;
};

export async function submitStudyProposal(
  _prev: ProposeState,
  formData: FormData,
): Promise<ProposeState> {
  const honey = formData.get("website");
  if (typeof honey === "string" && honey.trim().length > 0) {
    return { ok: true, message: "Thanks — we'll be in touch." };
  }

  const ip = ipFromHeaders(await headers());
  const limit = await rateLimitAsync({
    key: `research-propose:${ip}`,
    max: 3,
    windowMs: 24 * 60 * 60 * 1000,
  });
  if (!limit.ok) {
    return {
      ok: false,
      message: "Too many proposals from this location. Try again tomorrow.",
    };
  }

  const parsed = proposalSchema.safeParse({
    title: formData.get("title") ?? "",
    proposerName: formData.get("proposerName") ?? "",
    email: formData.get("email") ?? "",
    institution: formData.get("institution") ?? "",
    country: formData.get("country") ?? "",
    orcidUrl: formData.get("orcidUrl") ?? "",
    specialty: formData.get("specialty") ?? "",
    background: formData.get("background") ?? "",
    hypothesis: formData.get("hypothesis") ?? "",
    design: formData.get("design") ?? "",
    resourcesNeeded: formData.get("resourcesNeeded") ?? "",
    fundingStatus: formData.get("fundingStatus") ?? "",
  });
  if (!parsed.success) {
    const fieldErrors: Record<string, string> = {};
    for (const issue of parsed.error.issues) {
      fieldErrors[issue.path.join(".")] = issue.message;
    }
    return {
      ok: false,
      fieldErrors,
      message: "Please correct the highlighted fields.",
    };
  }
  const data = parsed.data;

  const [row] = await db
    .insert(researchProposals)
    .values({
      title: data.title,
      proposerName: data.proposerName,
      email: data.email.toLowerCase(),
      institution: data.institution,
      country: data.country,
      orcidUrl: data.orcidUrl || null,
      specialty: data.specialty,
      background: data.background,
      hypothesis: data.hypothesis,
      design: data.design,
      resourcesNeeded: data.resourcesNeeded,
      fundingStatus: data.fundingStatus,
      status: "pending",
    })
    .returning({ id: researchProposals.id });

  const env = loadEnv();
  const reviewUrl = `${env.nextAuthUrl}/admin/research/proposals/${row.id}`;

  try {
    await sendTemplatedEmail({
      to: data.email,
      templateSlug: "research-proposal-received",
      variables: { name: data.proposerName, title: data.title },
    });
    await sendTemplatedEmail({
      to: env.adminNotifyEmails,
      templateSlug: "research-proposal-admin-notify",
      variables: {
        name: data.proposerName,
        email: data.email,
        institution: data.institution,
        country: data.country,
        title: data.title,
        specialty: data.specialty,
        hypothesis: data.hypothesis,
        reviewUrl,
      },
    });
  } catch (err) {
    console.error("[research-propose] email failed", err);
  }

  redirect("/products/research/proposals/thanks");
}
