// lib/auth.config.ts
import { SignInAction } from '@/feactures/auth/actions/login-action';
import { logoutAction } from '@/feactures/auth/actions/logout-action';
import { CredentialsSignin, NextAuthConfig, Session, User } from 'next-auth';
import { DefaultJWT, JWT } from 'next-auth/jwt';
import CredentialProvider from 'next-auth/providers/credentials';

// Define los tipos para tus respuestas de SignInAction
interface SignInSuccessResponse {
  message: string;
  user: {
    email: string;
    username: string;
    id: number;
    rol: Array<{ id: number; rol: string }>;
    fullname: string;
  };
  tokens: {
    access_token: string;
    access_expire_in: number;
    refresh_token: string;
    refresh_expire_in: number;
  };
}

// **CAMBIO AQUÍ**: `type: string;` en lugar de una unión de literales
interface SignInErrorResponse {
  type: string; // Si SignInAction puede devolver cualquier string aquí
  message: string;
  details?: any;
}

// Unión de tipos para el resultado de SignInAction, AHORA INCLUYE `null`
type SignInActionResult = SignInSuccessResponse | SignInErrorResponse | null;

const authConfig: NextAuthConfig = {
  providers: [
    CredentialProvider({
      credentials: {
        username: {
          type: 'username',
        },
        password: {
          type: 'password',
        },
      },
      async authorize(
        credentials: Partial<Record<'username' | 'password', unknown>>,
      ): Promise<User | null> {
        const credential = {
          username: credentials?.username as string,
          password: credentials?.password as string,
        };

        // Asigna el tipo `SignInActionResult` que ahora incluye `null`
        const response: SignInActionResult = await SignInAction(credential);

        // **NUEVO: Manejar el caso `null` primero**
        if (response === null) {
          console.error(
            'SignInAction returned null, indicating a potential issue before API call or generic error.',
          );
          throw new CredentialsSignin('Error de inicio de sesión inesperado.');
        }

        // Tipo Guarda: Verificar la respuesta de error
        if (
          'type' in response &&
          (response.type === 'API_ERROR' ||
            response.type === 'VALIDATION_ERROR' ||
            response.type === 'UNKNOWN_ERROR') // Incluye todos los tipos de error posibles
        ) {
          // Si es un error, lánzalo. Este camino termina aquí.
          throw new CredentialsSignin('Error en la API:' + response.message);
        }

        if (!('user' in response)) {
          // Esto solo ocurriría si SignInAction devolvió un objeto que no es null,
          // no es un error conocido por 'type', PERO tampoco tiene la propiedad 'user'.
          // Es un caso de respuesta inesperada del API.
          console.error(
            "Respuesta de SignInAction con formato inesperado: falta la propiedad 'user'.",
          );
          throw new CredentialsSignin(
            'Error en el formato de la respuesta del servidor.',
          );
        }

        return {
          id: response?.user.id?.toString() ?? '0',
          username: response?.user.username ?? '',
          fullname: response?.user.fullname ?? '',
          email: response?.user.email ?? '',
          role: response?.user.rol ?? [], // Add role array
          access_token: response?.tokens.access_token ?? '',
          access_expire_in: response?.tokens.access_expire_in ?? 0,
        };
      },
    }),
  ],
  pages: {
    signIn: '/', //sigin page
  },
  callbacks: {
    async jwt({ token, user }: { user: User; token: any }) {
      // 1. Manejar el inicio de sesión inicial
      // El `user` solo se proporciona en el primer inicio de sesión.
      if (user) {
        return {
          id: user.id,
          username: user.username,
          fullname: user.fullname,
          email: user.email,
          role: user.role,
          access_token: user.access_token,
          access_expire_in: user.access_expire_in,
        };
      }

      return token;
    },
    async session({ session, token }: { session: Session; token: DefaultJWT }) {
      session.access_token = token.access_token as string;
      session.access_expire_in = token.access_expire_in as number;
      session.user = {
        id: token.id as number,
        username: token.username as string,
        fullname: token.fullname as string,
        email: token.email as string,
        role: token.role as Array<{ id: number; rol: string }>,
      };
      return session;
    },
  },
  events: {
    async signOut(message) {
      // 1.  verificamos que venga token (puede no venir con algunos providers)
      const token = (message as { token?: JWT }).token;
      if (!token?.access_token) return;
      try {
        await logoutAction(String(token?.id));
      } catch {
        /* silencioso para que next-auth siempre cierre */
      }
    },
  },
} satisfies NextAuthConfig;

export default authConfig;
