import { PrismaAdapter } from "@next-auth/prisma-adapter";
import { compare, hashSync } from "bcryptjs";
import type { NextAuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";

import { prisma } from "@/lib/db/prisma";
import { loginSchema } from "@/lib/validation/auth";

const loginAttempts = new Map<string, number[]>();
const dummyPasswordHash = hashSync("webku-invalid-user-timing-value", 12);

function loginRateLimited(email: string) {
  const now = Date.now();
  const recent = (loginAttempts.get(email) ?? []).filter((time) => now - time < 15 * 60_000);
  if (recent.length >= 8) return true;
  recent.push(now);
  loginAttempts.set(email, recent);
  return false;
}

export const authOptions: NextAuthOptions = {
  adapter: PrismaAdapter(prisma),
  session: { strategy: "jwt", maxAge: 8 * 60 * 60 },
  pages: { signIn: "/login" },
  providers: [
    CredentialsProvider({
      name: "Email dan kata sandi",
      credentials: { email: { label: "Email", type: "email" }, password: { label: "Kata sandi", type: "password" } },
      async authorize(credentials) {
        const result = loginSchema.safeParse(credentials);
        if (!result.success) return null;
        if (loginRateLimited(result.data.email)) return null;
        const user = await prisma.user.findUnique({ where: { email: result.data.email } });
        const passwordValid = await compare(result.data.password, user?.passwordHash ?? dummyPasswordHash);
        if (!user?.passwordHash || user.status !== "ACTIVE" || !passwordValid) return null;
        loginAttempts.delete(result.data.email);
        return { id: user.id, name: user.name, email: user.email, image: user.image, role: user.role };
      },
    }),
  ],
  callbacks: {
    jwt({ token, user }) {
      if (user) { token.id = user.id; token.role = user.role; }
      return token;
    },
    session({ session, token }) {
      if (session.user) { session.user.id = token.id; session.user.role = token.role; }
      return session;
    },
  },
};
