"use server";

import { revalidatePath } from "next/cache";
import { and, eq } from "drizzle-orm";
import { db } from "@/db";
import { companyDocuments, auditLogs } from "@/db/schema";
import { requireSession } from "@/lib/auth";
import { canUploadCompanyDocuments } from "@/lib/rbac";
import { deleteStored, saveImage } from "@/lib/storage";
import { isUuid } from "@/lib/route-params";
import { DEFAULT_DOCUMENT_CATEGORY, DOCUMENT_ALLOWED_MIME, DOCUMENT_MAX_MB, isDocumentCategory, resolveDocumentMime } from "@/lib/document-categories";

// Lỗi nghiệp vụ trả về dạng `{ error }` (không `throw`): bản production giấu nội dung lỗi ném ra từ server action nên người dùng chỉ thấy câu chung chung.
type Result = { ok?: string; error?: string };

/** Đọc và kiểm tên / loại / trích yếu chung cho cả tải lên và sửa. */
function readMeta(formData: FormData): { error: string } | { title: string; category: string; description: string | null } {
  const title = String(formData.get("title") ?? "").trim();
  if (title.length < 2) return { error: "Vui lòng nhập tên văn bản (ít nhất 2 ký tự)." };
  if (title.length > 200) return { error: "Tên văn bản tối đa 200 ký tự." };

  const categoryRaw = String(formData.get("category") ?? DEFAULT_DOCUMENT_CATEGORY);
  if (!isDocumentCategory(categoryRaw)) return { error: "Loại văn bản không hợp lệ." };

  const description = String(formData.get("description") ?? "").trim();
  if (description.length > 1000) return { error: "Trích yếu tối đa 1000 ký tự." };

  return { title, category: categoryRaw, description: description || null };
}

export async function uploadCompanyDocumentAction(formData: FormData): Promise<Result> {
  const session = await requireSession();
  if (!(await canUploadCompanyDocuments(session))) return { error: "Bạn không có quyền tải văn bản công ty lên." };

  const meta = readMeta(formData);
  if ("error" in meta) return meta;

  const picked = formData.get("file");
  if (!(picked instanceof File) || picked.size === 0) return { error: "Vui lòng chọn tệp văn bản." };
  if (picked.size > DOCUMENT_MAX_MB * 1024 * 1024) return { error: `Tệp vượt quá ${DOCUMENT_MAX_MB} MB.` };
  const mime = resolveDocumentMime(picked.name, picked.type);
  const file = mime === picked.type ? picked : new File([picked], picked.name, { type: mime });
  if (!(DOCUMENT_ALLOWED_MIME as readonly string[]).includes(file.type)) {
    return { error: "Chỉ nhận tệp PDF, ảnh PNG/JPEG, Word (.docx), Excel (.xlsx) hoặc PowerPoint (.pptx)." };
  }

  const saved = await saveImage(file, "van-ban");
  if (!saved.ok) return { error: saved.error };

  const fileName = file.name.slice(0, 200);
  const [created] = await db
    .insert(companyDocuments)
    .values({
      tenantId: session.tenantId,
      title: meta.title,
      category: meta.category,
      description: meta.description,
      fileName,
      mimeType: file.type,
      fileSize: file.size,
      filePath: saved.path,
      uploadedBy: session.userId,
    })
    .returning();

  await db.insert(auditLogs).values({
    tenantId: session.tenantId,
    userId: session.userId,
    action: "CREATE",
    entityType: "company_document",
    entityId: created.id,
    payload: { title: meta.title, category: meta.category, fileName, fileSize: file.size },
  });

  revalidatePath("/van-ban");
  revalidatePath("/");
  return { ok: "Đã tải văn bản lên." };
}

/** Sửa tên, loại và trích yếu — tệp đính kèm giữ nguyên (muốn đổi tệp thì xoá và tải lại). */
export async function updateCompanyDocumentAction(formData: FormData): Promise<Result> {
  const session = await requireSession();
  if (!(await canUploadCompanyDocuments(session))) return { error: "Bạn không có quyền sửa văn bản công ty." };

  const id = String(formData.get("id") ?? "");
  if (!isUuid(id)) return { error: "Không tìm thấy văn bản." };
  const meta = readMeta(formData);
  if ("error" in meta) return meta;

  const [before] = await db
    .select()
    .from(companyDocuments)
    .where(and(eq(companyDocuments.tenantId, session.tenantId), eq(companyDocuments.id, id)))
    .limit(1);
  if (!before) return { error: "Văn bản không còn tồn tại — hãy tải lại trang." };

  await db
    .update(companyDocuments)
    .set({ title: meta.title, category: meta.category, description: meta.description })
    .where(and(eq(companyDocuments.tenantId, session.tenantId), eq(companyDocuments.id, id)));

  await db.insert(auditLogs).values({
    tenantId: session.tenantId,
    userId: session.userId,
    action: "UPDATE",
    entityType: "company_document",
    entityId: id,
    payload: {
      before: { title: before.title, category: before.category, description: before.description },
      after: { title: meta.title, category: meta.category, description: meta.description },
    },
  });

  revalidatePath("/van-ban");
  revalidatePath("/");
  return { ok: "Đã cập nhật văn bản." };
}

export async function deleteCompanyDocumentAction(formData: FormData): Promise<Result> {
  const session = await requireSession();
  if (!(await canUploadCompanyDocuments(session))) return { error: "Bạn không có quyền xoá văn bản công ty." };

  const id = String(formData.get("id") ?? "");
  if (!isUuid(id)) return { error: "Không tìm thấy văn bản." };

  const [doc] = await db
    .select({ title: companyDocuments.title, fileName: companyDocuments.fileName, filePath: companyDocuments.filePath })
    .from(companyDocuments)
    .where(and(eq(companyDocuments.tenantId, session.tenantId), eq(companyDocuments.id, id)))
    .limit(1);
  if (!doc) return { error: "Văn bản đã được xoá trước đó — hãy tải lại trang." };

  await db.delete(companyDocuments).where(and(eq(companyDocuments.tenantId, session.tenantId), eq(companyDocuments.id, id)));
  // Xoá cả tệp trên ổ đĩa — trước đây tệp mồ côi nằm lại mãi và chiếm dung lượng máy chủ.
  await deleteStored(doc.filePath);

  await db.insert(auditLogs).values({
    tenantId: session.tenantId,
    userId: session.userId,
    action: "DELETE",
    entityType: "company_document",
    entityId: id,
    payload: { title: doc.title, fileName: doc.fileName },
  });

  revalidatePath("/van-ban");
  revalidatePath("/");
  return { ok: "Đã xoá văn bản." };
}
