"use server";

/**
 * ورود به پنل مدیریت با شماره موبایل و رمز.
 * - پیام خطا برای «شماره نامعتبر» و «رمز اشتباه» یکسان است تا وجود حساب لو نرود
 * - ۵ تلاش ناموفق ← قفل ۱۵ دقیقه‌ای حساب؛ هر IP حداکثر ۲۰ تلاش در ۱۵ دقیقه
 * - نشست پنل جدا از نشست فروشگاه است و ۱۲ ساعت اعتبار دارد
 */
import { headers } from "next/headers";
import { db } from "@/lib/db";
import { faNumber } from "@/lib/format";
import { mobileSchema } from "@/validation/common";
import { createSession, destroySession } from "@/server/auth/session";
import { verifyPassword } from "@/server/auth/password";
import { isStaffRole } from "@/server/admin/guard";

const MAX_FAILS = 5;
const LOCK_MINUTES = 15;
const IP_WINDOW_MS = 15 * 60_000;
const IP_MAX = 20;
const ipHits = new Map<string, number[]>();

function ipLimited(ip: string) {
  const now = Date.now();
  const list = (ipHits.get(ip) ?? []).filter((t) => now - t < IP_WINDOW_MS);
  list.push(now);
  ipHits.set(ip, list);
  return list.length > IP_MAX;
}

const GENERIC = "شماره موبایل یا رمز اشتباه است";

export async function adminLoginAction(input: { phone: string; password: string }): Promise<{ ok: true } | { ok: false; error: string }> {
  const h = await headers();
  const ip = (h.get("x-forwarded-for") ?? "").split(",")[0].trim() || h.get("x-real-ip") || "local";
  if (ipLimited(ip)) return { ok: false, error: "تلاش‌های زیادی انجام شد؛ ۱۵ دقیقه دیگر دوباره امتحان کنید" };

  const phone = mobileSchema.safeParse(input.phone ?? "");
  const password = String(input.password ?? "").slice(0, 128);
  if (!phone.success || !password) return { ok: false, error: GENERIC };

  const user = await db.user.findUnique({ where: { phone: phone.data } });
  if (user?.lockedUntil && user.lockedUntil > new Date()) {
    const mins = Math.ceil((user.lockedUntil.getTime() - Date.now()) / 60_000);
    return { ok: false, error: `به‌دلیل تلاش‌های ناموفق، ورود این حساب ${faNumber(mins)} دقیقه قفل است` };
  }
  const valid = await verifyPassword(password, user?.passwordHash);
  if (!user || !valid || !isStaffRole(user.role)) {
    if (user && isStaffRole(user.role)) {
      const fails = user.failedLogins + 1;
      await db.user.update({
        where: { id: user.id },
        data: fails >= MAX_FAILS ? { failedLogins: 0, lockedUntil: new Date(Date.now() + LOCK_MINUTES * 60_000) } : { failedLogins: fails },
      });
    }
    return { ok: false, error: GENERIC };
  }

  await db.user.update({ where: { id: user.id }, data: { failedLogins: 0, lockedUntil: null, lastLoginAt: new Date() } });
  await destroySession(); // نشست قبلی (مثلاً ورود پیامکی فروشگاه) جایگزین می‌شود
  await createSession(user.id, { adminAuth: true });
  return { ok: true };
}
