"use server";

import { revalidatePath } from "next/cache";
import { and, eq } from "drizzle-orm";
import { db } from "@/db";
import { alerts, forecasts } from "@/db/schema";
import { requireSession } from "@/lib/auth";
import { alertScope } from "@/lib/alerts-scope";
import { canEditCatalog, canViewAllStaff } from "@/lib/rbac";
import { isUuid } from "@/lib/route-params";
import { writeAudit } from "@/lib/audit";

// 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.
type Result = { ok?: string; error?: string };

/** Đánh dấu một cảnh báo đã xử lý — chỉ cảnh báo trong phạm vi của người xem. */
export async function acknowledgeAlertAction(formData: FormData): Promise<Result> {
  const session = await requireSession();
  if (!canViewAllStaff(session)) return { error: "Bạn không có quyền xử lý cảnh báo." };
  const id = String(formData.get("id") ?? "");
  if (!isUuid(id)) return { error: "Không tìm thấy cảnh báo." };

  const updated = await db
    .update(alerts)
    .set({ status: "ACKNOWLEDGED", acknowledgedBy: session.userId, acknowledgedAt: new Date() })
    .where(and(await alertScope(session), eq(alerts.id, id), eq(alerts.status, "OPEN")))
    .returning();
  if (updated.length === 0) return { error: "Cảnh báo đã được xử lý hoặc không còn — hãy tải lại trang." };

  await writeAudit(session, "UPDATE", "alert", id, { title: updated[0].title, changes: { status: { from: "OPEN", to: "ACKNOWLEDGED" } } });

  revalidatePath("/canh-bao");
  return { ok: "Đã đánh dấu đã xử lý." };
}

/**
 * Ghi đè số lượng dự báo bằng con số người dùng tự quyết.
 *
 * Cột `forecastQty` do máy tính giữ nguyên để đối chiếu về sau — muốn biết dự báo của hệ thống lệch bao nhiêu so với
 * quyết định thực tế thì phải còn cả hai con số. Bỏ trống ô nhập nghĩa là quay lại dùng số máy tính.
 */
export async function adjustForecastAction(formData: FormData): Promise<Result> {
  const session = await requireSession();
  if (!canEditCatalog(session)) return { error: "Bạn không có quyền chỉnh dự báo." };

  const id = String(formData.get("id") ?? "");
  if (!isUuid(id)) return { error: "Không tìm thấy dòng dự báo." };
  const raw = String(formData.get("adjustedQty") ?? "").trim();

  const adjustedQty = raw === "" ? null : Number(raw);
  // Trần 10 triệu: số lớn hơn làm tràn cột số nguyên của cơ sở dữ liệu và hiện ra là lỗi 500.
  if (adjustedQty != null && (!Number.isFinite(adjustedQty) || adjustedQty < 0 || adjustedQty > 10_000_000)) {
    return { error: "Số lượng điều chỉnh không hợp lệ (từ 0 đến 10.000.000)." };
  }

  const [before] = await db
    .select({ adjustedQty: forecasts.adjustedQty, forecastQty: forecasts.forecastQty, periodKey: forecasts.periodKey, productId: forecasts.productId })
    .from(forecasts)
    .where(and(eq(forecasts.tenantId, session.tenantId), eq(forecasts.id, id)))
    .limit(1);
  if (!before) return { error: "Dòng dự báo không còn tồn tại — hãy tải lại trang." };

  const next = adjustedQty == null ? null : Math.round(adjustedQty);
  await db
    .update(forecasts)
    .set({ adjustedQty: next })
    .where(and(eq(forecasts.tenantId, session.tenantId), eq(forecasts.id, id)));
  if (before.adjustedQty !== next) {
    await writeAudit(session, "UPDATE", "forecast", id, { periodKey: before.periodKey, productId: before.productId, forecastQty: before.forecastQty, changes: { adjustedQty: { from: before.adjustedQty, to: next } } });
  }

  revalidatePath("/canh-bao");
  return { ok: adjustedQty == null ? "Đã quay lại dùng số máy tính." : "Đã lưu số điều chỉnh." };
}
