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

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

// Import the service that contains business logic
import { MenusService } from './menus.service';

// Import DTOs (Data Transfer Objects) for request validation
import { CreateMenuDto } from './dto/create.dto';
import { MenusEntity } from 'src/entities/Menus.entity';
import { SearchMenuDto } from './dto/search-dto';
import { UpdateMenuDto } from './dto/update.dto';

// Import custom pagination response type
import { Response } from 'src/config/pagination/paginationDto';

// Import utility for consistent error handling
import { handleServiceRequest } from 'src/utils/response/response-handler';

// Import additional DTOs
import { FetchByUsersDto } from './dto/fetch-by-users.dto';
import { UpdateStatusDto } from './dto/update-status.dto';

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

// Import custom decorator for session data extraction
import { SessionData, SessionDataProps } from 'src/utils/decorators';

/**
 * MenusController - Handles all HTTP requests for menu management
 *
 * This controller manages the CRUD operations and additional business logic
 * for menus in the system. It follows RESTful conventions and includes
 * comprehensive filtering, audit tracking, and status management.
 *
 * Features:
 * - Complete CRUD operations
 * - Paginated search with filters
 * - User activity tracking (created by/updated by)
 * - Bulk status updates
 * - Session-based authentication
 *
 * @ApiTags('Menus') - Groups all endpoints under "Menus" in Swagger UI
 * @Controller('') - Base route for this controller (empty string uses module prefix)
 * @UseGuards(SessionGuard) - Protects all endpoints with session authentication
 */
@ApiTags('Menus')
@Controller('')
@UseGuards(SessionGuard)
export class MenusController {
  /**
   * Constructor with dependency injection
   *
   * @param menuService - Injected service containing all business logic for menus
   */
  constructor(private readonly menuService: MenusService) {}

  /**
   * POST /all - Retrieves paginated menus with advanced filtering
   *
   * This endpoint uses POST instead of GET to support complex search criteria
   * in the request body (better for complex filters than query parameters).
   *
   * @param searchDto - Contains search criteria, filters, pagination, and sorting parameters
   * @returns Promise<Response<MenusEntity>> - Paginated response with menus and metadata
   */
  @Post('all')
  async findAll(
    @Body() searchDto: SearchMenuDto,
  ): Promise<Response<MenusEntity>> {
    return await handleServiceRequest(this.menuService.findAll(searchDto));
  }

  /**
   * GET /:id - Retrieves a single menu by ID
   *
   * @param id - The numeric ID of the menu to retrieve (from URL parameter)
   * @returns The requested menu entity with related data
   */
  @Get(':id')
  async findOne(@Param('id') id: number) {
    return await handleServiceRequest(this.menuService.findOne(id));
  }

  /**
   * POST / - Creates a new menu
   *
   * Uses ValidationPipe to automatically validate the request body
   * against the CreateMenuDto validation rules. Tracks the creator.
   *
   * @param body - Validated creation data from request body
   * @param sessionData - Current user's session data extracted via custom decorator
   * @returns Promise<MenusEntity> - The newly created menu entity
   */
  @Post()
  async create(
    @Body(new ValidationPipe()) body: CreateMenuDto,
    @SessionData() sessionData: SessionDataProps,
  ): Promise<MenusEntity> {
    return await handleServiceRequest(
      this.menuService.create(sessionData?.user?.id, body),
    );
  }

  /**
   * PUT / - Updates an existing menu
   *
   * Uses ValidationPipe for request body validation. Tracks the user
   * who performed the update for audit purposes.
   *
   * @param body - Validated update data including the menu ID
   * @param sessionData - Current user's session data
   * @returns Update result or the updated menu entity
   */
  @Put()
  async update(
    @Body(new ValidationPipe()) body: UpdateMenuDto,
    @SessionData() sessionData: SessionDataProps,
  ) {
    return await handleServiceRequest(
      this.menuService.update(sessionData?.user?.id, body),
    );
  }

  /**
   * DELETE /:id - Deletes a menu by ID
   *
   * Note: Typically implements soft delete rather than hard delete
   * (might be implemented at the entity or service level).
   *
   * @param id - The numeric ID of the menu to delete
   * @returns Delete result
   */
  @Delete(':id')
  async delete(@Param('id') id: number) {
    return await handleServiceRequest(this.menuService.delete(id));
  }

  /**
   * POST /fetch-menu-groups - Retrieves menu groups for selection/dropdown
   *
   * This endpoint provides a list of menu groups, likely for:
   * - Associating menus with menu groups during creation/update
   * - Filtering menus by menu group
   * - Displaying in UI dropdowns
   *
   * @returns List of menu groups with minimal data (id, name)
   */
  @Post('fetch-menu-groups')
  async getMenuGroupsByList() {
    return await handleServiceRequest(this.menuService.fetchMenuGroupsByList());
  }

  /**
   * POST /fetch-users - Retrieves users involved in menu creation/updates
   *
   * Useful for:
   * - Audit reports showing which users created/updated menus
   * - Filter dropdowns in admin interfaces
   * - User activity tracking
   *
   * @param params - Contains the filter type: 'created_by' or 'updated_by'
   * @returns List of users with formatted display information
   */
  @Post('fetch-users')
  async getCreatedByOrUpdatedByUsers(
    @Body(new ValidationPipe()) params: FetchByUsersDto,
  ) {
    return await handleServiceRequest(
      this.menuService.fetchCreatedByOrUpdatedByUsers(params.by),
    );
  }

  /**
   * POST /update-status - Bulk updates status of multiple menus
   *
   * Typically used for:
   * - Activating/deactivating menus in bulk
   * - Batch operations in admin interfaces
   * - Menu lifecycle management
   *
   * @param body - Contains menu IDs and action (activate/deactivate)
   * @param sessionData - Current user's session data for audit tracking
   * @returns Bulk update result
   */
  @Post('update-status')
  async updateStatus(
    @Body() body: UpdateStatusDto,
    @SessionData() sessionData: SessionDataProps,
  ) {
    return await handleServiceRequest(
      this.menuService.updateStatus(sessionData?.user?.id, body),
    );
  }
}
