// file: ~/server/api/auth/[...].ts
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { NuxtAuthHandler } from '#auth'
import CredentialsProvider from 'next-auth/providers/credentials';
import GithubProvider from 'next-auth/providers/github'
import GoogleProvider from 'next-auth/providers/google';

export default NuxtAuthHandler({
    // @ts-ignore
    secret: useRuntimeConfig().authSecret,

    providers: [
        // @ts-expect-error
        GithubProvider.default({
            clientId: useRuntimeConfig().githubClientId,
            clientSecret: useRuntimeConfig().githubClientSecret
        }),
        // @ts-expect-error
        GoogleProvider.default({
            clientId: useRuntimeConfig().googleClientId,
            clientSecret: useRuntimeConfig().googleClientSecret
        }),
        // @ts-expect-error
        CredentialsProvider.default({
            name: 'credentials',
            credentials: {
                email: { label: 'email', type: 'email' },
                password: { type: 'password', label: 'password' }
            },
            async authorize(credentials: { email: string; password: string } | undefined) {
                if (!credentials) return null;

                const config = useRuntimeConfig();
                const apiUrl = config.public.BASE_API_URL || 'http://127.0.0.1:8000';

                try {
                    const tokenResponse = await fetch(`${apiUrl}/api/v1/auth/jwt/create/`, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({
                            email: credentials.email,
                            password: credentials.password
                        })
                    });

                    if (!tokenResponse.ok) {
                        return null;
                    }

                    const tokenData = await tokenResponse.json();
                    const { access, refresh } = tokenData;

                    const userResponse = await fetch(`${apiUrl}/api/v1/auth/users/me/`, {
                        headers: {
                            'Authorization': `Bearer ${access}`
                        }
                    });

                    if (!userResponse.ok) {
                        return null;
                    }

                    const userData = await userResponse.json();

                    // Return a user object with tokens and user data
                    return {
                        ...userData,
                        accessToken: access,
                        refreshToken: refresh
                    };
                } catch (error) {
                    console.error('Authorize error:', error);
                    return null;
                }
            }
        })
    ],
    callbacks: {
        // @ts-ignore
        jwt: async ({ token, user, account }) => {
            // The `user` object is from the `authorize` callback.
            if (user) {
                // @ts-ignore
                token.id = user.id;
                // @ts-ignore
                token.email = user.email;
                // @ts-ignore
                token.name = user.name;
                // @ts-ignore
                token.role = user.role;
                // @ts-ignore
                token.image = user.image;
                // @ts-ignore
                token.is_active = user.is_active;
                // Persist the tokens in the JWT
                // @ts-ignore
                token.accessToken = user.accessToken;
                // @ts-ignore
                token.refreshToken = user.refreshToken;
            }

            // Social login: exchange provider access_token for backend JWT tokens
            // This runs only on initial sign-in where `account` is present.
            if (
                account &&
                (account.provider === 'google' || account.provider === 'github') &&
                // @ts-ignore
                account.access_token
            ) {
                try {
                    const config = useRuntimeConfig();
                    const apiUrl = config.public.BASE_API_URL || 'http://127.0.0.1:8000';

                    const endpoint =
                        account.provider === 'google'
                            ? `${apiUrl}/api/v1/auth/social/google-oauth2/`
                            : `${apiUrl}/api/v1/auth/social/github/`;

                    // @ts-ignore
                    const accessToken = account.access_token;
                    const response = await fetch(endpoint, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({ access_token: accessToken }),
                    });

                    if (response.ok) {
                        const data = await response.json();
                        // Expected shape (per docs): { access, refresh, user }
                        // Persist backend JWTs on token so client can call protected APIs.
                        // @ts-ignore
                        token.accessToken = data.access;
                        // @ts-ignore
                        token.refreshToken = data.refresh;

                        if (data.user) {
                            // @ts-ignore
                            token.id = data.user.id ?? token.id;
                            // @ts-ignore
                            token.email = data.user.email ?? token.email;
                            // @ts-ignore
                            token.name =
                                (data.user.name ??
                                    [data.user.first_name, data.user.last_name].filter(Boolean).join(' ')) ||
                                token.name;
                            // @ts-ignore
                            token.image = data.user.image ?? token.image;
                            // @ts-ignore
                            token.role = data.user.role ?? token.role;
                            // @ts-ignore
                            token.is_active = data.user.is_active ?? token.is_active;
                        }
                    } else {
                        const text = await response.text().catch(() => '');
                        console.error('Social token exchange failed:', response.status, text);
                    }
                } catch (e) {
                    console.error('Social token exchange error:', e);
                }
            }

            return token;
        },
        // @ts-ignore
        session: async ({ session, token }) => {
            if (token && session.user) {
                // @ts-ignore
                session.user.id = token.id;
                // @ts-ignore
                session.user.name = token.name;
                // @ts-ignore
                session.user.role = token.role;
                // @ts-ignore
                session.user.email = token.email;
                // @ts-ignore
                session.user.image = token.image;
                // @ts-ignore
                session.user.is_active = token.is_active;
            }

            // Expose backend JWTs to the client session (optional but useful)
            // @ts-ignore
            session.accessToken = token.accessToken;
            // @ts-ignore
            session.refreshToken = token.refreshToken;

            return session;
        },
    },
    // Disable verbose NextAuth logs to avoid DEBUG_ENABLED warning
    // @ts-ignore
    debug: false,
    pages: {
        signIn: '/auth/login'
    },
    session: {
        strategy: 'jwt'
    }
})
