import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { AuthenticatedUser } from '../interfaces/jwt-payload.interface';

/**
 * Decorator para acessar o token JWT raw
 */
export const Token = createParamDecorator(
  (data: unknown, ctx: ExecutionContext): string | null => {
    const request = ctx.switchToHttp().getRequest();
    const user: AuthenticatedUser = request.user;
    return user?.rawToken || null;
  },
);

/**
 * Decorator para acessar dados específicos extraídos do token
 */
export const TokenData = createParamDecorator(
  (
    field: keyof AuthenticatedUser['tokenData'] | undefined,
    ctx: ExecutionContext,
  ): any => {
    const request = ctx.switchToHttp().getRequest();
    const user: AuthenticatedUser = request.user;

    if (!user?.tokenData) {
      return null;
    }

    return field ? user.tokenData[field] : user.tokenData;
  },
);

/**
 * Decorator para acessar o payload completo do JWT
 */
export const JwtPayload = createParamDecorator(
  (field: string | undefined, ctx: ExecutionContext): any => {
    const request = ctx.switchToHttp().getRequest();
    const user: AuthenticatedUser = request.user;

    if (!user?.payload) {
      return null;
    }

    return field
      ? user.payload[field as keyof typeof user.payload]
      : user.payload;
  },
);

/**
 * Decorator para acessar o UUID do usuário (se disponível no token)
 */
export const UserUuid = createParamDecorator(
  (data: unknown, ctx: ExecutionContext): string | null => {
    const request = ctx.switchToHttp().getRequest();
    const user: AuthenticatedUser = request.user;
    return user?.tokenData?.uuid || null;
  },
);

/**
 * Decorator para acessar o email do usuário (se disponível no token)
 */
export const UserEmail = createParamDecorator(
  (data: unknown, ctx: ExecutionContext): string | null => {
    const request = ctx.switchToHttp().getRequest();
    const user: AuthenticatedUser = request.user;
    return user?.tokenData?.email || null;
  },
);

/**
 * Decorator para acessar o nome do usuário (se disponível no token)
 */
export const UserName = createParamDecorator(
  (data: unknown, ctx: ExecutionContext): string | null => {
    const request = ctx.switchToHttp().getRequest();
    const user: AuthenticatedUser = request.user;
    return user?.tokenData?.name || null;
  },
);
