// config/authConfig.ts (or wherever your authOptions live)
import { AuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { LOGIN_API_PATH } from "./api";
import { Session } from "next-auth";
// Extend the built-in types
declare module "next-auth" {
  interface Session {
    accessToken: string | null;
    refreshToken?: string;
    abilities: string[];
    id?: string;
    /** JWT expiry (seconds since epoch); used to avoid redirecting to dashboard when token is expired */
    exp?: number;
  }

  interface User {
    id?: string;
    accessToken: string | null;
    refreshToken?: string;
    abilities: string[];
  }
}

declare module "next-auth/jwt" {
  interface JWT {
    id?: string;
    accessToken: string | null;
    refreshToken?: string;
    abilities: string[];
  }
}

export const authOptions: AuthOptions = {
  debug: process.env.NODE_ENV === "development",
  providers: [
    CredentialsProvider({
      id: "credentials",
      name: "Credentials",
      credentials: {
        username: { label: "Username", type: "text" },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials) {
        if (!credentials?.username || !credentials?.password) return null;

        const res = await fetch(LOGIN_API_PATH, {
          method: "POST",
          body: JSON.stringify(credentials),
          headers: { "Content-Type": "application/json" },
        });

        if (!res.ok) return null;

        const user = await res.json();

        // Important: next-auth expects the user object returned here
        // to be serializable and contain the fields you want in token/session
        // Ensure your backend returns: { id, accessToken, abilities, ...other fields }
        if (user && user.abilities) {
          return user; // this will be passed to jwt callback as `user`
        }

        return null;
      },
    }),
  ],
  pages: {
    signIn: "/login",
  },
  callbacks: {
    // Persist custom fields into the JWT token
    async jwt({ token, user }) {
      // First sign-in: `user` is available
      if (user) {
        token.id = user.id ?? token.sub; // fallback to sub if no id
        token.accessToken = user.accessToken;
        token.refreshToken = user.refreshToken;
        token.abilities = user.abilities ?? [];
      }

      // On subsequent calls (token refresh, session access), user is not present
      // so we just return the existing token with custom fields preserved
      return token;
    },

    // Expose custom fields to the client session
    async session({ session, token }) {
      session.id = token.id as string | undefined;
      session.accessToken = token.accessToken as string | null;
      session.refreshToken = token.refreshToken as string | undefined;
      session.abilities = token.abilities as string[];
      session.exp = token.exp as number | undefined;

      // Also add abilities to session.user for easier client-side access
      if (session.user) {
        session.user.abilities = token.abilities as string[];
      }

      return session;
    },
  },
};
export type SessionWithTokens = Session & {
  accessToken: string | null;
  refreshToken?: string;
  abilities: string[];
  /** Backend / JWT subject — often numeric string or number */
  id?: string | number;
};
export default authOptions;