import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import * as _ from 'lodash';

/**
 * UserDataProps - Type representing user data stored in session
 *
 * This type defines the structure of user-specific data stored within
 * the session object. It uses a generic Record type to allow flexible
 * user data storage while maintaining type safety.
 *
 * Typical user data stored in session:
 * - User identification (id, email, username)
 * - Authentication status and roles
 * - User preferences and settings
 * - Recent activity or navigation state
 * - Temporary user-specific data
 *
 * @example
 * // User data in session might contain:
 * {
 *   id: 12345,
 *   email: 'user@example.com',
 *   roles: ['user', 'premium'],
 *   preferences: { theme: 'dark', language: 'en' },
 *   lastLogin: '2024-01-15T10:30:00.000Z'
 * }
 */
export type UserDataProps = Record<string, any>;

/**
 * UserData - Custom parameter decorator for extracting user data from session
 *
 * This decorator extracts user-specific data from the session object.
 * It assumes the session contains a `user` property with user-related data.
 *
 * Features:
 * - Provides direct access to user data stored in session
 * - Assumes session-based authentication (not JWT)
 * - Works with session middleware that stores user data in `req.session.user`
 * - Type-safe with UserDataProps type
 *
 * @example
 * // Usage in controller method
 * @Get('profile')
 * getProfile(@UserData() userData: UserDataProps) {
 *   return {
 *     id: userData.id,
 *     email: userData.email,
 *     name: userData.name
 *   };
 * }
 *
 * @example
 * // Usage with validation
 * @Post('update-preference')
 * updatePreference(
 *   @UserData() userData: UserDataProps,
 *   @Body() preference: PreferenceDto
 * ) {
 *   if (!userData.id) {
 *     throw new UnauthorizedException('User not authenticated');
 *   }
 *   return this.userService.updatePreference(userData.id, preference);
 * }
 *
 * @note Requires session middleware configured with user data
 * @note Different from ClientData decorator which extracts from JWT
 * @note Session must contain `user` property with user data
 */

export type UserDataType = {
  id: number;
  role?: string;
  email: string;
};

export const UserData = createParamDecorator(
  (data: unknown, ctx: ExecutionContext): any => {
    const request = ctx.switchToHttp().getRequest();
    const user = request.user;

    if (!user) {
      return null;
    }

    return { id: user.id, role: '2', email: user.email ?? user.first_name };
  },
);
