import type { NextAuthOptions, User } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import GoogleProvider from "next-auth/providers/google";
import { jwtDecode } from "jwt-decode";
import { cookies } from "next/headers";

const API_URL = process.env.NEXT_PUBLIC_API_URL;

interface DecodedToken {
    sub: number;
    email: string;
    name: string;
    role: string;
    iat: number;
    exp: number;
}
interface AuthUser extends User {
    id: number;
    email: string;
    role: string;
    accessToken: string;
    refreshToken: string;
}

export const authOptions: NextAuthOptions = {
    providers: [
        GoogleProvider({
            clientId: process.env.GOOGLE_CLIENT_ID || "",
            clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
        }),
        CredentialsProvider({
            name: "Credentials",
            credentials: {
                email: { label: "Email", type: "text" },
                password: { label: "Password", type: "password" },
                accessToken: { label: "Token", type: "hidden" },
                refreshToken: { label: "Refresh", type: "hidden" },
            },
            async authorize(credentials): Promise<AuthUser | null> {
                if (credentials?.accessToken && credentials?.refreshToken) {
                    try {
                        const decoded: DecodedToken = jwtDecode(credentials.accessToken);
                        return {
                            id: decoded.sub,
                            email: decoded.email,
                            role: decoded.role,
                            accessToken: credentials.accessToken,
                            refreshToken: credentials.refreshToken,
                        } as AuthUser;
                    } catch (e) {
                        return null;
                    }
                }
                if (!credentials?.email || !credentials?.password) return null;
                try {
                    const res = await fetch(`${API_URL}/auth/login`, {
                        method: "POST",
                        headers: {
                            "Content-Type": "application/json",
                        },
                        body: JSON.stringify({
                            email: credentials.email,
                            password: credentials.password,
                        }),
                    });
                    const data = await res.json();
                    if (!res.ok || !data?.access_token) {
                        const message = Array.isArray(data?.message)
                            ? data.message[0]
                            : data?.message;

                        const errorMessage = message || "Authentication failed. Please check your credentials.";
                        throw new Error(errorMessage);
                    }
                    const decoded: DecodedToken = jwtDecode(data.access_token);
                    return {
                        id: decoded.sub,
                        email: decoded.email,
                        role: decoded.role,
                        accessToken: data.access_token,
                        refreshToken: data.refresh_token,
                    } as AuthUser;
                } catch (error: any) {
                    throw new Error(error.message || "An unexpected login error occurred.");
                }
            },
        }),
    ],

    pages: {
        signIn: "/auth/login",
        error: "/auth/error", // Branded error page
    },

    session: {
        strategy: "jwt",
    },

    callbacks: {
        async signIn({ user, account, profile }) {
            if (account?.provider === "google") {
                try {
                    const cookieStore = await cookies();
                    const role = cookieStore.get("pending_role")?.value;

                    const res = await fetch(`${API_URL}/auth/social-login`, {
                        method: "POST",
                        headers: { "Content-Type": "application/json" },
                        body: JSON.stringify({
                            email: user.email,
                            name: user.name,
                            image: user.image,
                            provider: "google",
                            role: role,
                        }),
                    });

                    if (res.ok) {
                        const data = await res.json();
                        cookieStore.delete("pending_role");

                        cookieStore.set("access_token", data.access_token, {
                            maxAge: 30 * 24 * 60 * 60,
                            path: "/",
                            secure: process.env.NODE_ENV === "production",
                            sameSite: "lax",
                        });

                        (user as any).accessToken = data.access_token;
                        (user as any).refreshToken = data.refresh_token;

                        const decoded: DecodedToken = jwtDecode(data.access_token);
                        (user as any).id = decoded.sub;
                        (user as any).role = decoded.role;

                        return true;
                    }
                    console.error("Backend sync failed for Google login");
                    return false;
                } catch (error) {
                    console.error("Error syncing Google user with backend:", error);
                    return `/auth/error?error=AuthSyncError&message=${encodeURIComponent(error instanceof Error ? error.message : 'Unknown error')}`;
                }
            }
            return true;
        },

        async jwt({ token, user, trigger, session }) {
            const cookieStore = await cookies();

            if (user) {
                const authorizedUser = user as AuthUser;
                token.accessToken = authorizedUser.accessToken;
                token.refreshToken = authorizedUser.refreshToken;
                token.user = {
                    id: authorizedUser.id,
                    email: authorizedUser.email,
                    name: authorizedUser.name || (authorizedUser.email ? authorizedUser.email.split('@')[0] : 'User'),
                    role: authorizedUser.role,
                };

                cookieStore.set("access_token", authorizedUser.accessToken, {
                    maxAge: 30 * 24 * 60 * 60, // 30 days
                    path: "/",
                    secure: process.env.NODE_ENV === "production",
                    sameSite: "lax",
                });
            }

            if (trigger === "update" && session) {
                if (session.accessToken) {
                    token.accessToken = session.accessToken;

                    const decoded: DecodedToken = jwtDecode(session.accessToken);
                    token.user = {
                        id: decoded.sub,
                        email: decoded.email,
                        name: decoded.name || decoded.email.split('@')[0],
                        role: decoded.role,
                    };

                    cookieStore.set("access_token", session.accessToken, {
                        maxAge: 30 * 24 * 60 * 60,
                        path: "/",
                        secure: process.env.NODE_ENV === "production",
                        sameSite: "lax",
                    });
                } else if (session.user) {
                    token.user = { ...token.user, ...session.user };
                }
            }

            return token;
        },

        async session({ session, token }) {
            session.accessToken = token.accessToken as string;
            session.refreshToken = token.refreshToken as string;
            session.user = token.user;
            return session;
        },
    },

    secret: process.env.NEXTAUTH_SECRET,
};