import { betterAuth } from "better-auth"
import { drizzleAdapter } from "better-auth/adapters/drizzle"
import { nextCookies } from "better-auth/next-js"
import { admin } from "better-auth/plugins"
import { db } from "@/lib/db"
import { user, session, account, verification, profiles, consent_log } from "@/lib/db/schema"
import { sendEmail, resetPasswordHtml, verifyEmailHtml } from "@/lib/email/send"
import { LEGAL } from "@/lib/legal"

// Bootstrap superadmins from env — no API path lets a user self-promote.
const ADMIN_USER_IDS = (process.env.ADMIN_USER_IDS ?? "")
  .split(",")
  .map((s) => s.trim())
  .filter(Boolean)

export const auth = betterAuth({
  baseURL: process.env.BETTER_AUTH_URL,
  secret: process.env.BETTER_AUTH_SECRET,
  database: drizzleAdapter(db, {
    provider: "pg",
    schema: { user, session, account, verification },
  }),
  emailAndPassword: {
    enabled: true,
    // Env-gated so production can require a verified email without breaking
    // local dev (where SMTP is typically unconfigured). Set
    // REQUIRE_EMAIL_VERIFICATION=true in production to enforce.
    requireEmailVerification: process.env.REQUIRE_EMAIL_VERIFICATION === "true",
    minPasswordLength: 8,
    sendResetPassword: async ({ user: u, url }) => {
      await sendEmail({
        to: u.email,
        subject: "Reset your Property Management Network password",
        html: resetPasswordHtml(url),
      })
    },
  },
  // Send a verification email on sign-up. Enforcement of verified-email login
  // is gated by REQUIRE_EMAIL_VERIFICATION (see emailAndPassword above).
  emailVerification: {
    sendOnSignUp: true,
    // After the user clicks the verification link, sign them in and send them
    // to the callbackURL (set to /dashboard on sign-up).
    autoSignInAfterVerification: true,
    sendVerificationEmail: async ({ user: u, url }) => {
      await sendEmail({
        to: u.email,
        subject: "Verify your email — Property Management Network",
        html: verifyEmailHtml(url),
      })
    },
  },
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID ?? "",
      clientSecret: process.env.GOOGLE_CLIENT_SECRET ?? "",
    },
  },
  // Throttle auth endpoints (per IP) to slow brute-force / credential stuffing.
  rateLimit: {
    enabled: true,
    window: 60,       // seconds
    max: 20,          // requests per window per IP for auth endpoints
    customRules: {
      // Tighter limit on the password sign-in endpoint to slow credential
      // stuffing / brute-force attempts.
      "/sign-in/email": { window: 60, max: 10 },
    },
  },
  // Auto-create the app `profiles` row whenever Better Auth creates a user
  // (replaces the old `handle_new_user` Postgres trigger).
  databaseHooks: {
    user: {
      create: {
        after: async (u) => {
          try {
            await db
              .insert(profiles)
              .values({ id: u.id, email: u.email, full_name: u.name ?? null })
              .onConflictDoNothing()
          } catch {
            // Never block sign-up on profile creation.
          }
          // GDPR proof of acceptance: the signup form states that creating an
          // account means agreeing to the Terms and Privacy Policy.
          try {
            await db.insert(consent_log).values([
              {
                user_id: u.id,
                email: u.email,
                kind: "terms" as const,
                granted: true,
                policy_version: LEGAL.lastUpdated,
                source: "signup",
              },
              {
                user_id: u.id,
                email: u.email,
                kind: "privacy" as const,
                granted: true,
                policy_version: LEGAL.lastUpdated,
                source: "signup",
              },
            ])
          } catch {
            // Never block sign-up on consent logging.
          }
        },
      },
    },
  },
  // `admin` enables role/ban/impersonation; `nextCookies` MUST stay last.
  plugins: [
    admin({ adminUserIds: ADMIN_USER_IDS }),
    nextCookies(),
  ],
})

