"use server";

import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { writeFile, mkdir } from "fs/promises";
import path from "path";
import crypto from "crypto";
import { prisma } from "@/lib/prisma";
import { getCurrentCustomerId } from "@/lib/customer-auth";
import { isValidPhone } from "@/lib/phone";

const ALLOWED_IMAGE_TYPES: Record<string, string> = {
  "image/jpeg": "jpg",
  "image/png": "png",
  "image/webp": "webp",
  "image/gif": "gif",
};
const MAX_IMAGE_SIZE = 5 * 1024 * 1024;

async function requireCustomerId(): Promise<string> {
  const customerId = await getCurrentCustomerId();
  if (!customerId) redirect("/account/login");
  return customerId;
}

// ---------- Profile ----------

export async function updateProfile(formData: FormData) {
  const customerId = await requireCustomerId();
  const name = String(formData.get("name") ?? "").trim() || null;
  const phone = String(formData.get("phone") ?? "").trim() || null;
  if (phone && !isValidPhone(phone)) {
    redirect("/account/profile?error=Enter+a+valid+10-digit+mobile+number");
  }
  if (name && name.length > 100) {
    redirect("/account/profile?error=Name+is+too+long");
  }
  await prisma.customer.update({ where: { id: customerId }, data: { name, phone } });
  revalidatePath("/account/profile");
  redirect("/account/profile?success=Profile+updated.");
}

// ---------- Addresses ----------

function addressFieldsError(fields: {
  name: string;
  addressLine1: string;
  addressLine2: string | null;
  landmark: string | null;
  city: string;
  state: string;
  district: string | null;
  pincode: string;
}): string | null {
  if (!/^\d{6}$/.test(fields.pincode)) return "Enter+a+valid+6-digit+pincode";
  if (
    fields.name.length > 100 ||
    fields.addressLine1.length > 200 ||
    (fields.addressLine2?.length ?? 0) > 200 ||
    (fields.landmark?.length ?? 0) > 100 ||
    fields.city.length > 100 ||
    fields.state.length > 100 ||
    (fields.district?.length ?? 0) > 100
  ) {
    return "One+of+the+fields+is+too+long";
  }
  return null;
}

export async function createAddress(formData: FormData) {
  const customerId = await requireCustomerId();
  const name = String(formData.get("name") ?? "").trim();
  const phone = String(formData.get("phone") ?? "").trim();
  const addressLine1 = String(formData.get("addressLine1") ?? "").trim();
  const city = String(formData.get("city") ?? "").trim();
  const state = String(formData.get("state") ?? "").trim();
  const pincode = String(formData.get("pincode") ?? "").trim();
  if (!name || !phone || !addressLine1 || !city || !state || !pincode) {
    redirect("/account/addresses?error=Fill+in+all+required+fields");
  }
  if (!isValidPhone(phone)) redirect("/account/addresses?error=Enter+a+valid+10-digit+mobile+number");
  const label = String(formData.get("label") ?? "").trim() || null;
  const addressLine2 = String(formData.get("addressLine2") ?? "").trim() || null;
  const landmark = String(formData.get("landmark") ?? "").trim() || null;
  const district = String(formData.get("district") ?? "").trim() || null;
  const fieldsError = addressFieldsError({ name, addressLine1, addressLine2, landmark, city, state, district, pincode });
  if (fieldsError) redirect(`/account/addresses?error=${fieldsError}`);

  const existingCount = await prisma.customerAddress.count({ where: { customerId } });
  await prisma.customerAddress.create({
    data: { customerId, label, name, phone, addressLine1, addressLine2, landmark, city, district, state, pincode, isDefault: existingCount === 0 },
  });
  revalidatePath("/account/addresses");
  redirect("/account/addresses?success=Address+added.");
}

export async function updateAddress(id: string, formData: FormData) {
  const customerId = await requireCustomerId();
  const existing = await prisma.customerAddress.findUnique({ where: { id } });
  if (!existing || existing.customerId !== customerId) redirect("/account/addresses?error=Address+not+found");

  const label = String(formData.get("label") ?? "").trim() || null;
  const name = String(formData.get("name") ?? "").trim();
  const phone = String(formData.get("phone") ?? "").trim();
  const addressLine1 = String(formData.get("addressLine1") ?? "").trim();
  const addressLine2 = String(formData.get("addressLine2") ?? "").trim() || null;
  const landmark = String(formData.get("landmark") ?? "").trim() || null;
  const district = String(formData.get("district") ?? "").trim() || null;
  const city = String(formData.get("city") ?? "").trim();
  const state = String(formData.get("state") ?? "").trim();
  const pincode = String(formData.get("pincode") ?? "").trim();
  if (!name || !phone || !addressLine1 || !city || !state || !pincode) {
    redirect("/account/addresses?error=Fill+in+all+required+fields");
  }
  if (!isValidPhone(phone)) redirect("/account/addresses?error=Enter+a+valid+10-digit+mobile+number");
  const fieldsError = addressFieldsError({ name, addressLine1, addressLine2, landmark, city, state, district, pincode });
  if (fieldsError) redirect(`/account/addresses?error=${fieldsError}`);

  await prisma.customerAddress.update({
    where: { id },
    data: { label, name, phone, addressLine1, addressLine2, landmark, city, district, state, pincode },
  });
  revalidatePath("/account/addresses");
  redirect("/account/addresses?success=Address+updated.");
}

export async function deleteAddress(id: string) {
  const customerId = await requireCustomerId();
  const existing = await prisma.customerAddress.findUnique({ where: { id } });
  if (!existing || existing.customerId !== customerId) redirect("/account/addresses?error=Address+not+found");

  await prisma.customerAddress.delete({ where: { id } });
  if (existing.isDefault) {
    const next = await prisma.customerAddress.findFirst({ where: { customerId } });
    if (next) await prisma.customerAddress.update({ where: { id: next.id }, data: { isDefault: true } });
  }
  revalidatePath("/account/addresses");
  redirect("/account/addresses?success=Address+deleted.");
}

export async function setDefaultAddress(id: string) {
  const customerId = await requireCustomerId();
  const existing = await prisma.customerAddress.findUnique({ where: { id } });
  if (!existing || existing.customerId !== customerId) redirect("/account/addresses?error=Address+not+found");

  await prisma.$transaction([
    prisma.customerAddress.updateMany({ where: { customerId }, data: { isDefault: false } }),
    prisma.customerAddress.update({ where: { id }, data: { isDefault: true } }),
  ]);
  revalidatePath("/account/addresses");
  redirect("/account/addresses?success=Default+address+updated.");
}

// ---------- Custom order self-service ----------

const VALID_TYPES = ["name_engraving", "laser_engraving", "3d_printing"];

export async function submitCustomOrderRequest(formData: FormData) {
  const customerId = await requireCustomerId();
  const customer = await prisma.customer.findUniqueOrThrow({ where: { id: customerId } });

  const phone = String(formData.get("phone") ?? "").trim();
  const type = String(formData.get("type") ?? "");
  const quantityRaw = String(formData.get("quantity") ?? "").trim();
  const quantity = quantityRaw ? Math.max(1, Math.round(Number(quantityRaw))) : null;
  const details = String(formData.get("details") ?? "").trim();

  if (!phone || !VALID_TYPES.includes(type) || !details) {
    redirect("/account/custom-orders?error=Fill+in+phone%2C+type%2C+and+details");
  }
  if (!isValidPhone(phone)) redirect("/account/custom-orders?error=Enter+a+valid+10-digit+mobile+number");
  if (details.length > 2000) redirect("/account/custom-orders?error=Details+are+too+long");

  let referenceImage: string | null = null;
  const file = formData.get("image");
  if (file instanceof File && file.size > 0) {
    const ext = ALLOWED_IMAGE_TYPES[file.type];
    if (!ext) redirect("/account/custom-orders?error=Only+JPG%2C+PNG%2C+WEBP%2C+or+GIF+images+are+allowed");
    if (file.size > MAX_IMAGE_SIZE) redirect("/account/custom-orders?error=Image+must+be+under+5MB");

    const uploadDir = path.join(process.cwd(), "public", "uploads", "custom-orders");
    await mkdir(uploadDir, { recursive: true });
    const filename = `${crypto.randomUUID()}.${ext}`;
    const bytes = Buffer.from(await file.arrayBuffer());
    await writeFile(path.join(uploadDir, filename), bytes);
    referenceImage = `/uploads/custom-orders/${filename}`;
  }

  await prisma.customOrderRequest.create({
    data: {
      customerId,
      customerName: customer.name || customer.email,
      email: customer.email,
      phone,
      type,
      quantity,
      details,
      referenceImage,
    },
  });

  revalidatePath("/account/custom-orders");
  revalidatePath("/iv-manage-84x2/custom-orders");
  redirect("/account/custom-orders?success=Custom+order+request+submitted.");
}

export async function respondToDesignProof(id: string, formData: FormData) {
  const customerId = await requireCustomerId();
  const request = await prisma.customOrderRequest.findUnique({ where: { id } });
  if (!request || request.customerId !== customerId) redirect("/account/custom-orders?error=Request+not+found");

  const decision = String(formData.get("decision") ?? "");
  let successMessage = "Response+submitted.";
  if (decision === "approve") {
    await prisma.customOrderRequest.update({
      where: { id },
      data: { status: "production", customerFeedback: null },
    });
    successMessage = "Design+approved.";
  } else if (decision === "reject") {
    const feedback = (String(formData.get("feedback") ?? "").trim() || "Customer requested changes to the design.").slice(0, 2000);
    await prisma.customOrderRequest.update({ where: { id }, data: { customerFeedback: feedback } });
    successMessage = "Feedback+sent.";
  }
  revalidatePath("/account/custom-orders");
  revalidatePath("/iv-manage-84x2/custom-orders/design-approval");
  redirect(`/account/custom-orders?success=${successMessage}`);
}

// ---------- Return / refund requests ----------

const REFUNDABLE_STATUSES = ["paid", "shipped", "delivered"];

// ---------- Reviews ----------

const PURCHASE_STATUSES = ["paid", "shipped", "delivered"];

export async function submitReview(productId: string, formData: FormData) {
  const customerId = await requireCustomerId();
  const [customer, product] = await Promise.all([
    prisma.customer.findUniqueOrThrow({ where: { id: customerId } }),
    prisma.product.findUniqueOrThrow({ where: { id: productId } }),
  ]);

  const purchased = await prisma.orderItem.findFirst({
    where: { productId, order: { customerId, status: { in: PURCHASE_STATUSES } } },
  });
  if (!purchased) redirect(`/product/${product.slug}?error=You+can+review+a+product+after+purchasing+it`);

  const rating = Math.min(5, Math.max(1, Math.round(Number(formData.get("rating") ?? 0))));
  const title = String(formData.get("title") ?? "").trim().slice(0, 100) || null;
  const body = String(formData.get("body") ?? "").trim();
  if (!rating || !body) redirect(`/product/${product.slug}?error=Add+a+rating+and+a+review`);
  if (body.length > 2000) redirect(`/product/${product.slug}?error=Review+is+too+long`);

  await prisma.review.upsert({
    where: { productId_customerId: { productId, customerId } },
    update: { rating, title, body, status: "pending" },
    create: { productId, customerId, customerName: customer.name || customer.email, rating, title, body },
  });
  revalidatePath(`/product/${product.slug}`);
  revalidatePath("/iv-manage-84x2/reviews");
  redirect(`/product/${product.slug}?success=Review+submitted.`);
}

export async function deleteOwnReview(id: string, productSlug: string) {
  const customerId = await requireCustomerId();
  const review = await prisma.review.findUnique({ where: { id } });
  if (!review || review.customerId !== customerId) redirect(`/product/${productSlug}?error=Review+not+found`);

  await prisma.review.delete({ where: { id } });
  revalidatePath(`/product/${productSlug}`);
  revalidatePath("/iv-manage-84x2/reviews");
  redirect(`/product/${productSlug}?success=Review+deleted.`);
}

export async function requestRefund(orderId: string, formData: FormData) {
  const customerId = await requireCustomerId();
  const order = await prisma.order.findUnique({ where: { id: orderId } });
  if (!order || order.customerId !== customerId) redirect("/account?error=Order+not+found");
  if (!REFUNDABLE_STATUSES.includes(order.status)) redirect("/account?error=This+order+isn%27t+eligible+for+a+refund+request");
  if (order.refundRequestStatus === "pending") redirect("/account?error=A+refund+request+is+already+pending+for+this+order");

  const reason = String(formData.get("reason") ?? "").trim();
  if (!reason) redirect("/account?error=Please+describe+the+reason+for+your+request");
  if (reason.length > 2000) redirect("/account?error=Reason+is+too+long");

  await prisma.order.update({
    where: { id: orderId },
    data: { refundRequestStatus: "pending", refundRequestReason: reason, refundRequestedAt: new Date() },
  });
  revalidatePath("/account");
  revalidatePath("/iv-manage-84x2/payments/refunds");
  redirect("/account?success=Refund+request+submitted.");
}
