import "server-only";
import { db } from "@/server/db";
import { writeAudit } from "@/server/audit";
import { hashPassword, verifyPassword } from "@/server/auth/password";

export type ChangePasswordResult =
  { ok: true } | { ok: false; code: "WRONG_CURRENT" | "SAME_AS_CURRENT" };

/**
 * Cambia la contraseña del propio usuario y cierra todas sus OTRAS sesiones
 * (la sesión actual se mantiene para no expulsarlo).
 */
export async function changeOwnPassword(params: {
  userId: string;
  currentSessionId: string;
  currentPassword: string;
  newPassword: string;
  ip: string;
  userAgent: string | null;
}): Promise<ChangePasswordResult> {
  const user = await db.user.findUniqueOrThrow({
    where: { id: params.userId },
    select: { id: true, email: true, passwordHash: true },
  });

  if (!(await verifyPassword(user.passwordHash, params.currentPassword))) {
    await writeAudit({
      userId: user.id,
      action: "auth.password_change_failed",
      entity: "user",
      entityId: user.id,
      summary: "Cambio de contraseña rechazado: contraseña actual incorrecta",
      ip: params.ip,
      userAgent: params.userAgent,
    });
    return { ok: false, code: "WRONG_CURRENT" };
  }
  if (params.currentPassword === params.newPassword) {
    return { ok: false, code: "SAME_AS_CURRENT" };
  }

  const passwordHash = await hashPassword(params.newPassword);
  const now = new Date();
  await db.$transaction(async (tx) => {
    await tx.user.update({
      where: { id: user.id },
      data: { passwordHash, passwordChangedAt: now, mustChangePassword: false },
    });
    await tx.session.updateMany({
      where: { userId: user.id, revokedAt: null, id: { not: params.currentSessionId } },
      data: { revokedAt: now, revokeReason: "password_changed" },
    });
    await writeAudit(
      {
        userId: user.id,
        action: "auth.password_changed",
        entity: "user",
        entityId: user.id,
        summary: `Cambio de contraseña (${user.email}); otras sesiones cerradas`,
        ip: params.ip,
        userAgent: params.userAgent,
      },
      tx,
    );
  });
  return { ok: true };
}
