"use server";

import { and, eq } from "drizzle-orm";
import { z } from "zod";
import { db } from "@/db";
import { users, auditLogs } from "@/db/schema";
import { requireSession, createSession } from "@/lib/auth";
import { hashPassword, verifyPassword } from "@/lib/password";
import { diffFields } from "@/lib/audit";
import { validAvatar } from "@/lib/avatar";
import { birthDateField, phoneField } from "@/lib/user-fields";
import { revalidatePath } from "next/cache";

const changeSchema = z
  .object({
    currentPassword: z.string().min(1, "Nhập mật khẩu hiện tại."),
    newPassword: z.string().min(8, "Mật khẩu mới phải có ít nhất 8 ký tự."),
    confirm: z.string(),
  })
  .refine((data) => data.newPassword === data.confirm, {
    message: "Mật khẩu mới nhập lại không khớp.",
    path: ["confirm"],
  });

export type ChangePasswordState = { error?: string; ok?: string };

export async function changePasswordAction(
  _prev: ChangePasswordState,
  formData: FormData,
): Promise<ChangePasswordState> {
  const session = await requireSession();

  const parsed = changeSchema.safeParse({
    currentPassword: formData.get("currentPassword"),
    newPassword: formData.get("newPassword"),
    confirm: formData.get("confirm"),
  });
  if (!parsed.success) return { error: parsed.error.issues[0].message };

  const [row] = await db
    .select({ passwordHash: users.passwordHash })
    .from(users)
    .where(and(eq(users.tenantId, session.tenantId), eq(users.id, session.userId)))
    .limit(1);
  if (!row) return { error: "Không tìm thấy tài khoản." };

  if (!(await verifyPassword(parsed.data.currentPassword, row.passwordHash))) {
    return { error: "Mật khẩu hiện tại không đúng." };
  }

  const passwordHash = await hashPassword(parsed.data.newPassword);
  await db
    .update(users)
    // Mốc đổi mật khẩu: các phiên đăng nhập khác (điện thoại cũ, máy người khác) hết hiệu lực; phiên hiện tại được cấp lại ngay bên dưới.
    .set({ passwordHash, passwordChangedAt: new Date() })
    .where(and(eq(users.tenantId, session.tenantId), eq(users.id, session.userId)));

  await db.insert(auditLogs).values({
    tenantId: session.tenantId,
    userId: session.userId,
    action: "UPDATE",
    entityType: "password_change",
    entityId: session.userId,
  });

  // Cấp lại phiên cho chính thiết bị này để người dùng không bị đăng xuất giữa chừng.
  await createSession(session);

  return { ok: "Đã đổi mật khẩu. Các thiết bị khác đã được đăng xuất." };
}

const profileSchema = z.object({
  fullName: z.string().trim().min(2, "Họ tên quá ngắn.").max(120),
  phone: phoneField,
  birthDate: birthDateField,
  gender: z.enum(["M", "F", "O"]).optional().or(z.literal("")),
});

export type ProfileState = { error?: string; ok?: string };

/** Nhân viên tự cập nhật thông tin cá nhân của mình (yêu cầu mục 2). */
export async function updateMyProfileAction(_prev: ProfileState, formData: FormData): Promise<ProfileState> {
  const session = await requireSession();

  const parsed = profileSchema.safeParse({
    fullName: formData.get("fullName"),
    phone: formData.get("phone") || undefined,
    birthDate: formData.get("birthDate") || "",
    gender: formData.get("gender") || "",
  });
  if (!parsed.success) return { error: parsed.error.issues[0].message };

  const avatar = String(formData.get("avatar") ?? "");
  const removeAvatar = formData.get("removeAvatar") === "1";
  if (avatar && !validAvatar(avatar)) return { error: "Ảnh đại diện không hợp lệ hoặc quá lớn." };

  const [current] = await db
    .select({
      fullName: users.fullName,
      phone: users.phone,
      birthDate: users.birthDate,
      gender: users.gender,
      hasAvatar: users.avatarDataUrl,
    })
    .from(users)
    .where(and(eq(users.tenantId, session.tenantId), eq(users.id, session.userId)))
    .limit(1);
  if (!current) return { error: "Không tìm thấy tài khoản." };

  const next = {
    fullName: parsed.data.fullName,
    phone: parsed.data.phone || null,
    birthDate: parsed.data.birthDate || null,
    gender: parsed.data.gender || null,
  };
  const changes = diffFields(
    { fullName: current.fullName, phone: current.phone, birthDate: current.birthDate, gender: current.gender },
    next,
  );
  if (avatar) changes.avatar = { from: current.hasAvatar ? "đã có" : "chưa có", to: "đã đổi" };
  else if (removeAvatar && current.hasAvatar) changes.avatar = { from: "đã có", to: "đã gỡ" };

  await db
    .update(users)
    .set({ ...next, ...(avatar ? { avatarDataUrl: avatar } : removeAvatar ? { avatarDataUrl: null } : {}) })
    .where(and(eq(users.tenantId, session.tenantId), eq(users.id, session.userId)));

  if (Object.keys(changes).length > 0) {
    await db.insert(auditLogs).values({
      tenantId: session.tenantId,
      userId: session.userId,
      action: "UPDATE",
      entityType: "user",
      entityId: session.userId,
      payload: { changes },
    });
  }

  revalidatePath("/tai-khoan");
  revalidatePath("/", "layout");
  return { ok: "Đã lưu thông tin cá nhân." };
}
