"use server";

import { revalidatePath } from "next/cache";
import { eq } from "drizzle-orm";
import { z } from "zod";
import { db } from "@/lib/db/client";
import { users } from "@/lib/db/schema";
import { requireUser } from "@/lib/auth/admin-guard";
import { saveAvatarUpload } from "@/lib/uploads/avatar";

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

const updateSchema = z.object({
  name: z.string().trim().min(2).max(120),
  country: z.string().trim().min(2).max(80),
  institution: z.string().trim().min(2).max(160),
  professionalRole: z.string().trim().min(2).max(80),
  bio: z.string().trim().max(600).optional().default(""),
  specialty: z.string().trim().max(120).optional().default(""),
  yearsExperience: z
    .string()
    .optional()
    .transform((v) => (v && v.length > 0 ? Number(v) : null))
    .refine(
      (v) => v === null || (Number.isFinite(v) && v >= 0 && v <= 80),
      "Must be 0–80",
    ),
  orcidUrl: z
    .string()
    .trim()
    .url()
    .startsWith("https://orcid.org/")
    .or(z.literal(""))
    .optional(),
  linkedinUrl: z
    .string()
    .trim()
    .url()
    .includes("linkedin.com")
    .or(z.literal(""))
    .optional(),
  websiteUrl: z.string().trim().url().or(z.literal("")).optional(),
  twitterUrl: z.string().trim().url().or(z.literal("")).optional(),
  visibleInDirectory: z.string().optional(),
  removeAvatar: z.string().optional(),
});

export async function updateProfile(
  _prev: ProfileFormState,
  formData: FormData,
): Promise<ProfileFormState> {
  const session = await requireUser();
  const userId = (session.user as { id?: string }).id;
  if (!userId) return { ok: false, message: "Session expired." };

  const raw = Object.fromEntries(formData);
  delete (raw as Record<string, unknown>).avatar;
  const parsed = updateSchema.safeParse(raw);
  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;

  // Avatar handling: explicit remove > new upload > leave alone.
  let avatarPathPatch: { avatarPath: string | null } | Record<string, never> = {};
  if (data.removeAvatar === "1") {
    avatarPathPatch = { avatarPath: null };
  } else {
    const avatarFile = formData.get("avatar");
    if (avatarFile instanceof File && avatarFile.size > 0) {
      const saved = await saveAvatarUpload(avatarFile);
      if (saved.ok) avatarPathPatch = { avatarPath: saved.path };
      else
        return {
          ok: false,
          message: saved.error || "Couldn't save that image.",
        };
    }
  }

  await db
    .update(users)
    .set({
      name: data.name,
      country: data.country,
      institution: data.institution,
      professionalRole: data.professionalRole,
      bio: data.bio ?? "",
      specialty: data.specialty ?? "",
      yearsExperience: data.yearsExperience ?? null,
      orcidUrl: data.orcidUrl || null,
      linkedinUrl: data.linkedinUrl || null,
      websiteUrl: data.websiteUrl || null,
      twitterUrl: data.twitterUrl || null,
      visibleInDirectory: data.visibleInDirectory === "on",
      ...avatarPathPatch,
    })
    .where(eq(users.id, userId));

  revalidatePath("/account");
  revalidatePath("/account/profile");
  revalidatePath("/account/directory");
  return { ok: true, message: "Profile saved." };
}
