import { betterAuth } from "better-auth";
import { Pool } from "pg";
import { nextCookies } from "better-auth/next-js";
import { EmailFactory, emailTemplates } from "./email";
import { I18N_CONFIG, USER_ROLES_CONFIG, TEAMS_CONFIG } from "./config";
import { getUserFlags } from "./services/user-flags.service";
import { TeamService } from "./services/team.service";
import { shouldSkipTeamCreation } from "./auth-context";
const isProd = process.env.NODE_ENV === "production";
const baseUrl = process.env.BETTER_AUTH_URL || process.env.NEXT_PUBLIC_APP_URL || "http://localhost:5173";
const emailService = EmailFactory.create();
const databaseUrl = process.env.DATABASE_URL;
const connectionString = databaseUrl.includes("?") ? `${databaseUrl}&pgbouncer=true` : `${databaseUrl}?pgbouncer=true`;
const pool = new Pool({
  connectionString,
  ssl: { rejectUnauthorized: false },
  connectionTimeoutMillis: 1e4,
  idleTimeoutMillis: 3e4,
  max: 20
});
const auth = betterAuth({
  database: pool,
  secret: process.env.BETTER_AUTH_SECRET,
  user: {
    modelName: "users",
    // Use plural table name instead of default "user"
    additionalFields: {
      firstName: {
        type: "string",
        required: false,
        input: true
        // Allow user to provide this during signup
      },
      lastName: {
        type: "string",
        required: false,
        input: true
        // Allow user to provide this during signup
      },
      language: {
        type: "string",
        required: false,
        input: true,
        // Allow user to provide this during signup
        defaultValue: I18N_CONFIG.defaultLocale
        // Set default language
      },
      role: {
        type: "string",
        required: false,
        input: false,
        // Don't allow users to set their own role
        defaultValue: USER_ROLES_CONFIG.defaultRole
        // Default role from config
      }
    }
  },
  emailAndPassword: {
    enabled: true,
    requireEmailVerification: true,
    minPasswordLength: 8,
    maxPasswordLength: 128,
    resetPasswordTokenExpiresIn: 60 * 60,
    // 1 hour
    sendResetPassword: async ({ user, url, token }) => {
      try {
        const resetUrl = `${url}?token=${token}`;
        const template = emailTemplates.resetPassword({
          userName: user.firstName || "",
          resetUrl,
          appName: process.env.NEXT_PUBLIC_APP_NAME || "Your App",
          expiresIn: "1 hour"
        });
        const response = await emailService.send({
          to: user.email,
          ...template
        });
        if (!response.success) {
          console.error("Failed to send reset password email:", response.error);
          throw new Error("Failed to send reset password email");
        }
      } catch (error) {
        console.error("Error sending reset password email:", error);
        throw error;
      }
    }
  },
  emailVerification: {
    sendVerificationEmail: async ({ user, token }) => {
      try {
        const verifyUrl = `${baseUrl}/api/auth/verify-email?token=${token}`;
        const template = emailTemplates.verifyEmail({
          userName: user.firstName || "",
          verificationUrl: verifyUrl,
          appName: process.env.NEXT_PUBLIC_APP_NAME || "Your App"
        });
        const response = await emailService.send({
          to: user.email,
          ...template
        });
        if (!response.success) {
          console.error("Failed to send verification email:", response.error);
          throw new Error("Failed to send verification email");
        }
      } catch (error) {
        console.error("Error sending verification email:", error);
        throw error;
      }
    },
    verifyTokenExpiresIn: 60 * 60 * 24
    // 24 hours
  },
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      mapProfileToUser: (profile) => {
        const firstName = profile.given_name || profile.name.split(" ")[0] || "";
        const lastName = profile.family_name || profile.name.split(" ").slice(1).join(" ") || "";
        return {
          email: profile.email,
          name: profile.name,
          // Better Auth expects 'name' field
          firstName,
          // Use given_name if available, otherwise split name
          lastName,
          // Use family_name if available, otherwise split name
          language: I18N_CONFIG.defaultLocale,
          // Assign default language for Google OAuth
          role: USER_ROLES_CONFIG.defaultRole,
          // Assign default role for Google OAuth users
          image: profile.picture,
          emailVerified: profile.email_verified || false
        };
      }
    }
  },
  baseURL: baseUrl,
  trustedOrigins: [
    baseUrl,
    process.env.NEXT_PUBLIC_APP_URL,
    // Additional public URL
    "http://localhost:5173",
    "http://localhost:3000",
    // Ionic app
    "http://localhost:3008",
    // Ionic app (puerto actual)
    "http://127.0.0.1:3000",
    // Alternative localhost
    "http://127.0.0.1:3008"
    // Alternative localhost actual
  ].filter((origin) => Boolean(origin)),
  plugins: [
    nextCookies()
    // MUST be the last plugin for Next.js cookie handling
  ],
  session: {
    expiresIn: 60 * 60 * 24 * 7,
    // 1 week
    updateAge: 60 * 60 * 24,
    // 1 day
    cookieCache: {
      enabled: true,
      maxAge: 60 * 5
      // 5 minutes
    }
  },
  // Database hooks for user lifecycle events (Better Auth API)
  databaseHooks: {
    user: {
      create: {
        // Create team when a new user signs up (email/password or OAuth)
        // Team type depends on configured teams mode
        after: async (user) => {
          try {
            if (shouldSkipTeamCreation()) {
              console.log(`[Teams] Skipping team creation for user ${user.id} (invite flow)`);
              return;
            }
            const teamsMode = TEAMS_CONFIG.mode;
            switch (teamsMode) {
              case "single-user":
              case "multi-tenant":
                await TeamService.create(user.id);
                console.log(`[Teams] Team created for user ${user.id} (mode: ${teamsMode})`);
                break;
              case "single-tenant":
                const existingTeam = await TeamService.getGlobal();
                if (!existingTeam) {
                  const teamName = user.name ? `${user.name}'s Company` : "Company";
                  await TeamService.create(user.id, teamName);
                  console.log(`[Teams] Global team created for first user ${user.id}`);
                } else {
                  console.warn(`[Teams] User ${user.id} created without team (single-tenant mode)`);
                }
                break;
              default:
                console.warn(`[Teams] Unknown teams mode: ${teamsMode}`);
            }
          } catch (error) {
            console.error(`[Teams] Failed to create team for user ${user.id}:`, error);
          }
        }
      }
    }
  },
  callbacks: {
    session: {
      // Add user flags to session data
      async onSignIn({ user, session }) {
        try {
          const flags = await getUserFlags(user.id);
          return {
            user: {
              ...user,
              flags
            },
            session
          };
        } catch (error) {
          console.error("Error loading user flags in session:", error);
          return {
            user: {
              ...user,
              flags: []
            },
            session
          };
        }
      },
      // Ensure flags are available in session retrieval
      async onSessionUpdate({ user, session }) {
        try {
          const flags = await getUserFlags(user.id);
          return {
            user: {
              ...user,
              flags
            },
            session
          };
        } catch (error) {
          console.error("Error loading user flags in session update:", error);
          return {
            user: {
              ...user,
              flags: user.flags || []
            },
            session
          };
        }
      }
    }
  },
  // Removed additionalFields - will use standard name and image fields
  advanced: {
    crossSubDomainCookies: {
      enabled: false
    },
    useSecureCookies: isProd,
    defaultCookieAttributes: {
      httpOnly: true,
      secure: isProd,
      sameSite: "lax",
      path: "/"
    }
  }
});
export {
  auth
};
