import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { eq } from "drizzle-orm";
import bcrypt from "bcrypt";
import { db } from "~/server/db";
import * as schema from "~/database/schema";
import { generateFlagConfig } from "~/lib/flag-generator";
import { sendEmail, wrapInEmailTemplate, emailButton, emailParagraph } from "~/lib/email.server";

if (!process.env.BETTER_AUTH_SECRET) {
  throw new Error("BETTER_AUTH_SECRET is required");
}

const googleProvider = process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET
  ? { google: { clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET } }
  : {};

const discordProvider = process.env.DISCORD_CLIENT_ID && process.env.DISCORD_CLIENT_SECRET
  ? { discord: { clientId: process.env.DISCORD_CLIENT_ID, clientSecret: process.env.DISCORD_CLIENT_SECRET } }
  : {};

const appBaseUrl = process.env.APP_URL ?? process.env.BETTER_AUTH_URL;

export const auth = betterAuth({
  baseURL: appBaseUrl,
  database: drizzleAdapter(db, {
    provider: "pg",
    usePlural: true,
  }),
  databaseHooks: {
    user: {
      create: {
        before: async (data) => {
          return {
            data: {
              ...data,
              flagConfig: generateFlagConfig(data.id),
            } as typeof data,
          };
        },
      },
      update: {
        before: async (data) => {
          const incomingImage =
            "imageUrl" in data ? data.imageUrl : "image" in data ? data.image : undefined;
          const userId = typeof data.id === "string" ? data.id : null;

          if (!incomingImage || !userId) return;

          const existing = await db.query.users.findFirst({
            where: eq(schema.users.id, userId),
          });

          if (existing?.avatarType === "uploaded" || existing?.avatarType === "flag") {
            const next = { ...data };
            delete next.imageUrl;
            delete next.image;
            return { data: next };
          }
        },
      },
    },
  },
  advanced: {
    database: {
      generateId: () => crypto.randomUUID(),
    },
  },
  user: {
    fields: {
      name: "displayName",
      image: "imageUrl",
    },
    additionalFields: {
      username: { type: "string", required: false, fieldName: "username" },
      isAdmin: { type: "boolean", defaultValue: false, fieldName: "isAdmin" },
    },
  },
  emailAndPassword: {
    enabled: true,
    password: {
      hash: (password: string) => bcrypt.hash(password, 10),
      verify: ({ hash, password }: { hash: string; password: string }) =>
        bcrypt.compare(password, hash),
    },
    sendResetPassword: async ({ user, url }) => {
      const { error } = await sendEmail({
        to: user.email,
        subject: "Reset your Brackt password",
        html: wrapInEmailTemplate(
          emailParagraph("Click the button below to reset your Brackt password. This link expires in 1 hour.") +
          emailButton(url, "Reset My Password") +
          emailParagraph(`Or copy this link: <a href="${url}" style="color:#adf661;word-break:break-all;">${url}</a>`),
          "Reset your Brackt password — link expires in 1 hour."
        ),
      });
      if (error) throw error;
    },
  },
  emailVerification: {
    sendOnSignUp: true,
    requireEmailVerification: true,
    autoSignInAfterVerification: true,
    sendVerificationEmail: async ({ user, url }) => {
      const { error } = await sendEmail({
        to: user.email,
        subject: "Verify your Brackt email",
        html: wrapInEmailTemplate(
          emailParagraph("Thanks for signing up for Brackt! Click the button below to verify your email address. This link expires in 24 hours.") +
          emailButton(url, "Verify My Email") +
          emailParagraph(`Or copy this link: <a href="${url}" style="color:#adf661;word-break:break-all;">${url}</a>`),
          "Verify your email to start using Brackt."
        ),
      });
      if (error) throw error;
    },
  },
  socialProviders: {
    ...googleProvider,
    ...discordProvider,
  },
  account: {
    accountLinking: {
      enabled: true,
      trustedProviders: ["google", "discord"],
    },
  },
});
