import { createClient, type GenericCtx } from '@convex-dev/better-auth';
import { convex } from '@convex-dev/better-auth/plugins';
import { components } from './_generated/api';
import { type DataModel } from './_generated/dataModel';
import { MutationCtx, query, QueryCtx } from './_generated/server';
import { betterAuth } from 'better-auth';

const siteUrl = process.env.SITE_URL!;

// The component client has methods needed for integrating Convex with Better Auth,
// as well as helper methods for general use.
export const authComponent = createClient<DataModel>(components.betterAuth);

export const createAuth = (
	ctx: GenericCtx<DataModel>,
	{ optionsOnly } = { optionsOnly: false }
) => {
	return betterAuth({
		// disable logging when createAuth is called just to generate options.
		// this is not required, but there's a lot of noise in logs without it.
		logger: {
			disabled: optionsOnly
		},
		baseURL: siteUrl,
		database: authComponent.adapter(ctx),
		// Configure simple, non-verified email/password to get started
		emailAndPassword: {
			enabled: true,
			requireEmailVerification: false
		},
		plugins: [
			// The Convex plugin is required for Convex compatibility
			convex()
		]
	});
};

// Example function for getting the current user
// Feel free to edit, omit, etc.
export const getCurrentUser = query({
	args: {},
	handler: async (ctx) => {
		const authUser = await authComponent.safeGetAuthUser(ctx);
		if (!authUser) {
			return;
		}

		const user = await ctx.db
			.query('usuarios')
			.withIndex('authId', (q) => q.eq('authId', authUser._id))
			.unique();

		if (!user) {
			return;
		}

		const fotoPerfilUrl = user.fotoPerfil ? await ctx.storage.getUrl(user.fotoPerfil) : null;

		if (!user.roleId) {
			return { ...user, role: null, fotoPerfilUrl };
		}

		const role = await ctx.db
			.query('roles')
			.withIndex('by_id', (q) => q.eq('_id', user.roleId))
			.unique();

		return { ...user, role, fotoPerfilUrl };
	}
});

export const getCurrentUserFunction = async (ctx: QueryCtx | MutationCtx) => {
	const authUser = await authComponent.safeGetAuthUser(ctx);
	if (!authUser) {
		return;
	}

	const user = await ctx.db
		.query('usuarios')
		.withIndex('authId', (q) => q.eq('authId', authUser._id))
		.unique();
	if (!user) {
		return;
	}
	return user;
};

export const createAuthUser = async (
	ctx: MutationCtx,
	args: { nome: string; email: string; password: string }
) => {
	const { auth, headers } = await authComponent.getAuth(createAuth, ctx);

	const result = await auth.api.signUpEmail({
		headers,
		body: {
			name: args.nome,
			email: args.email,
			password: args.password
		}
	});

	return result.user.id;
};

export const updatePassword = async (
	ctx: MutationCtx,
	args: { newPassword: string; currentPassword: string }
) => {
	const { auth, headers } = await authComponent.getAuth(createAuth, ctx);

	await auth.api.changePassword({
		headers,
		body: {
			currentPassword: args.currentPassword,
			newPassword: args.newPassword
		}
	});
};
