// Import necessary decorators and utilities from NestJS
import {
  Body,
  Controller,
  Get,
  Param,
  Post,
  UseGuards,
  ValidationPipe,
} from '@nestjs/common';

// Import Swagger decorator for API documentation
import { ApiTags } from '@nestjs/swagger';

// Import the service that contains business logic
import { UserService } from './user.service';

// Import DTOs for request validation
import { UpdateThemeDto } from './dto/update-theme.dto';

// Import Redis service for session management
import { RedisService } from '../redis/redis.service';

// Import authentication guard
import { SessionGuard } from 'src/config/guards/session.guard';

// Import custom decorators for session data extraction
import { SessionData, SessionDataProps } from 'src/utils/decorators';
import { UpdateMenuViewDto } from './dto/update-menu-view.dto';
import {
  UserData,
  UserDataType,
} from 'src/utils/decorators/user-data.decorator';
import { handleServiceRequest } from 'src/utils/response/response-handler';
import { GlobalService } from '../global/global.service';
import { DEFAULT_USER_ID } from 'src/constants/auth';

/**
 * UserController - Handles HTTP requests for user profile and preferences
 *
 * This controller manages user-specific operations including:
 * - User profile retrieval
 * - User preferences (theme, menu view)
 * - Table settings management
 * - User organization structure (branches, divisions)
 *
 * Key Characteristics:
 * - Mix of public and protected endpoints
 * - Session-based preference management
 * - Integration with Redis for session persistence
 * - User experience customization features
 *
 * Business Context:
 * - Part of user management and personalization system
 * - Manages UI/UX preferences for individual users
 * - Integrates with organizational structure
 * - Supports multi-session preference synchronization
 *
 * @ApiTags('User') - Groups all endpoints under "User" in Swagger UI
 * @Controller('') - Base route for this controller
 */
@ApiTags('User')
@Controller('')
export class UserController {
  /**
   * Constructor with dependency injection
   *
   * @param userService - Injected service containing user business logic
   * @param redisService - Injected Redis service for session management
   */
  constructor(
    private readonly userService: UserService,
    private readonly redisService: RedisService,
    private readonly globalService: GlobalService,
  ) {}

  /**
   * GET /:id - Retrieves a single user by ID
   *
   * Public endpoint (no @UseGuards annotation).
   * Should be used carefully as it exposes user data.
   *
   * @param id - User ID from URL parameter
   * @returns User entity with profile information
   *
   * Security Consideration:
   * - Should add authorization to prevent users from accessing other users' data
   * - Consider adding @UseGuards(SessionGuard) and ownership validation
   */
  @Get(':id')
  findOne(@Param('id') id: number) {
    return this.userService.findOne(id);
  }

  /**
   * GET /user-branches/:id - Retrieves functional branches for a user
   *
   * Functional branches likely represent organizational units or
   * business units the user has access to.
   *
   * @param id - User ID
   * @returns List of functional branches associated with the user
   */
  @Get('user-branches/:id')
  fetchFunctionalBranches(@Param('id') id: number) {
    return this.userService.getFunctionalBranches(DEFAULT_USER_ID);
  }

  /**
   * GET /user-divisions/:id - Retrieves divisions for a user
   *
   * Divisions likely represent departments or teams within the organization.
   *
   * @param id - User ID
   * @returns List of divisions associated with the user
   */
  @Get('user-divisions/:id')
  fetchUserDivisions(@Param('id') id: number) {
    return this.userService.getUserDivisionByUserId(DEFAULT_USER_ID);
  }

  /**
   * POST /save-table-settings - Stores user's table preferences
   *
   * This endpoint saves user-specific table configurations such as:
   * - Column visibility and order
   * - Sorting preferences
   * - Filter presets
   * - Pagination settings
   *
   * Use Case:
   * - User customizes a data table view and wants to save it
   * - Different users have different preferred table layouts
   *
   * @param body - Table configuration data (likely column settings, filters, etc.)
   * @returns Saved table settings
   */
  @Post('save-table-settings')
  storeTableSettings(@Body() body: any) {
    return this.userService.storeTableSettings(body);
  }

  /**
   * POST /reset-table-settings - Resets user's table preferences to defaults
   *
   * This endpoint allows users to reset their table configurations
   * back to system defaults.
   *
   * @param body - Likely contains table identifier and reset parameters
   * @param reset - Boolean flag passed to service indicating reset operation
   * @returns Reset table settings or confirmation
   */
  @Post('reset-table-settings')
  resetTableSettings(@Body() body: any) {
    // Calls same service method but with reset flag
    return this.userService.storeTableSettings(body, true);
  }

  /**
   * GET /countries/all - Retrieves all countries
   *
   * Public endpoint for country reference data.
   * Used for dropdowns, address forms, etc.
   *
   * @returns List of all countries
   */
  @Get('/countries/all')
  async getCountriesAll() {
    return this.userService.getCountries();
  }

  /**
   * POST /update-theme - Updates user's UI theme preference
   *
   * Protected endpoint that requires session authentication.
   * Updates both database and session cache for immediate effect.
   *
   * Implementation Pattern:
   * 1. Update theme in database via UserService
   * 2. Update theme in Redis session cache
   * 3. Return updated theme
   *
   * @param updateThemeDto - Validated theme update data
   * @param sessionData - Current user's session data
   * @returns Updated theme information
   */
  @Post('update-theme')
  @UseGuards(SessionGuard) // Requires authenticated session
  async updateTheme(
    @Body(new ValidationPipe()) updateThemeDto: UpdateThemeDto,
    @SessionData() sessionData: SessionDataProps,
  ) {
    // 1. Update theme in database
    const theme = await this.userService.updateTheme(updateThemeDto);

    // 2. Update theme in session cache for immediate effect
    // if (sessionData.session_id && theme) {
    //   const data = await this.redisService.getSession(sessionData.session_id);
    //   if (data) {
    //     data.panelTheme = theme; // Update theme in session data
    //     await this.redisService.setSession(sessionData.session_id, data);
    //   }
    // }

    return theme;
  }

  /**
   * POST /update-menu-view - Updates user's menu view preference
   *
   * Similar pattern to updateTheme but for menu display preferences.
   * Menu types could include: sidebar, topbar, hamburger, etc.
   *
   * @param updateMenuViewDto - Validated menu view update data
   * @param sessionData - Current user's session data
   * @returns Updated user information
   */
  @Post('update-menu-view')
  @UseGuards(SessionGuard)
  async updateMenuView(
    @Body(new ValidationPipe()) updateMenuViewDto: UpdateMenuViewDto,
    @UserData() userData: UserDataType,
  ) {
    // 1. Update menu view in database
    await this.userService.updateMenuView(
      userData.id as number, // Extract user ID from session
      updateMenuViewDto,
    );

    // 2. Update menu view in session cache for immediate effect
    // if (sessionData.session_id && user) {
    //   const data = await this.redisService.getSession(sessionData.session_id);
    //   if (data) {
    //     // Update menu type in session user data
    //     data.user.menu_type = String(updateMenuViewDto.menu_type);
    //     await this.redisService.setSession(sessionData.session_id, data);
    //   }
    // }

    // return user;

    const userInfo = await this.globalService.getUserInfo(userData.id);

    const user = {
      ...userInfo,
      role_id: userInfo.user_roles[0]?.role.id,
      role_permissions: userInfo.user_roles[0]?.role.permissions,
      menu_type: String(userInfo.menu_type),
    };

    const result = {
      user,
      session_id: 'req.sessionID',
      panelTheme: user.theme || {},
      timezone: user.user_timezone || {},
      menuBookmarks: user.favorite_menu || [],
      menu_type: user?.menu_type || '1',
    };

    if (result?.user) {
      delete result.user.favorite_menu;
      delete result.user.theme;
    }

    return result;
  }
}
