import {
  Body,
  Controller,
  Get,
  Param,
  Post,
  Put,
  UseGuards,
  ValidationPipe,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiBearerAuth,
  ApiParam,
  ApiResponse,
} from '@nestjs/swagger';
import { CreateDto } from './dto/create.dto';
import { SearchDto } from './dto/search-dto';
import { UpdateDto } from './dto/update.dto';
import { Response } from 'src/config/pagination/paginationDto';
import { UpdateStatusDto } from './dto/update-status.dto';
import { FetchByUsersDto } from './dto/fetch-by-users.dto';
import { handleServiceRequest } from 'src/utils/response/response-handler';
import { SessionGuard } from 'src/config/guards/session.guard';
import { CommissionDifferenceReasonService } from './commission-difference-reason.service';
import { VcmCommissionDifferenceReasonEntity } from 'src/entities/VcmCommissionDifferenceReason.entity';
import {
  UserData,
  UserDataProps,
} from 'src/utils/decorators/user-data.decorator';

/**
 * Commission Difference Reason Controller
 *
 * This controller manages CRUD operations for commission difference reasons.
 * Commission difference reasons are used to categorize and explain discrepancies
 * or variances in commission calculations within the visa commission management system.
 *
 * All endpoints are protected by SessionGuard to ensure only authenticated users
 * can access commission difference reason data.
 *
 * @ApiTags('Commission Difference Reason') - Groups endpoints in Swagger UI
 * @Controller('') - No path prefix, consider adding one like 'commission-difference-reasons'
 * @UseGuards(SessionGuard) - Requires valid session for all endpoints
 *
 * @example
 * // Typical endpoints:
 * // POST /all - Search with filters and pagination
 * // GET /active - Get all active reasons
 * // GET /:id - Get specific reason by ID
 * // POST / - Create new reason
 * // PUT / - Update existing reason
 * // POST /fetch-users - Get users who created/updated reasons
 * // POST /update-status - Bulk activate/deactivate reasons
 */
@ApiTags('Commission Difference Reason')
@Controller('') // Consider adding path prefix: @Controller('commission-difference-reasons')
@UseGuards(SessionGuard)
@ApiBearerAuth() // Indicates endpoints require Bearer token
export class CommissionDifferenceReasonController {
  constructor(private readonly rsService: CommissionDifferenceReasonService) {}

  /**
   * Search commission difference reasons with filtering and pagination.
   *
   * This endpoint allows searching through commission difference reasons with
   * various filters, sorting options, and pagination support.
   *
   * @param searchDto - Search criteria, filters, and pagination parameters
   * @returns Paginated response of commission difference reasons
   *
   * @note Missing ValidationPipe on searchDto parameter
   */
  @Post('all')
  @ApiOperation({
    summary: 'Search commission difference reasons',
    description:
      'Search and filter commission difference reasons with pagination',
  })
  @ApiResponse({
    status: 200,
    description: 'Commission difference reasons retrieved',
  })
  @ApiResponse({ status: 400, description: 'Invalid search parameters' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  async findAll(
    @Body() searchDto: SearchDto, // Missing ValidationPipe
  ): Promise<Response<VcmCommissionDifferenceReasonEntity>> {
    return await handleServiceRequest(this.rsService.findAll(searchDto));
  }

  /**
   * Get all active commission difference reasons.
   *
   * Returns only reasons that are currently marked as active (active = 1).
   * Typically used for dropdowns or selection lists in forms.
   *
   * @returns Response containing all active commission difference reasons
   */
  @Get('active')
  @ApiOperation({
    summary: 'Get all active reasons',
    description:
      'Retrieve all commission difference reasons that are currently active',
  })
  @ApiResponse({ status: 200, description: 'Active reasons retrieved' })
  async findAllActive(): Promise<
    Response<VcmCommissionDifferenceReasonEntity>
  > {
    return await handleServiceRequest(this.rsService.findAllActive());
  }

  /**
   * Get a specific commission difference reason by ID.
   *
   * @param id - Numeric ID of the commission difference reason
   * @returns Single commission difference reason entity
   *
   * @note Consider adding @ParseIntPipe to ensure ID is parsed as number
   */
  @Get(':id')
  @ApiOperation({
    summary: 'Get reason by ID',
    description: 'Retrieve a specific commission difference reason by its ID',
  })
  @ApiParam({
    name: 'id',
    type: Number,
    description: 'Commission difference reason ID',
  })
  @ApiResponse({ status: 200, description: 'Reason retrieved' })
  @ApiResponse({ status: 404, description: 'Reason not found' })
  async findOne(@Param('id') id: number) {
    return await handleServiceRequest(this.rsService.findOne(id));
  }

  /**
   * Create a new commission difference reason.
   *
   * @param body - Commission difference reason data
   * @param userData - Current authenticated user information
   * @returns Newly created commission difference reason entity
   */
  @Post()
  @ApiOperation({
    summary: 'Create new reason',
    description: 'Create a new commission difference reason',
  })
  @ApiResponse({ status: 201, description: 'Reason created successfully' })
  @ApiResponse({ status: 400, description: 'Invalid input data' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  async create(
    @Body(new ValidationPipe()) body: CreateDto,
    @UserData() userData: UserDataProps,
  ): Promise<VcmCommissionDifferenceReasonEntity> {
    return await handleServiceRequest(this.rsService.create(userData.id, body));
  }

  /**
   * Update an existing commission difference reason.
   *
   * @param body - Updated commission difference reason data
   * @param userData - Current authenticated user information
   * @returns Updated commission difference reason entity
   */
  @Put()
  @ApiOperation({
    summary: 'Update reason',
    description: 'Update an existing commission difference reason',
  })
  @ApiResponse({ status: 200, description: 'Reason updated successfully' })
  @ApiResponse({ status: 404, description: 'Reason not found' })
  async update(
    @Body(new ValidationPipe()) body: UpdateDto,
    @UserData() userData: UserDataProps,
  ) {
    return await handleServiceRequest(this.rsService.update(userData.id, body));
  }

  /**
   * Get users who created or updated commission difference reasons.
   *
   * This endpoint is useful for audit trails and filtering by user activity.
   *
   * @param params - Filter specifying whether to fetch creators or updaters
   * @returns List of users who created or updated commission difference reasons
   */
  @Post('fetch-users')
  @ApiOperation({
    summary: 'Get creators/updaters',
    description:
      'Get users who created or updated commission difference reasons',
  })
  @ApiResponse({ status: 200, description: 'Users retrieved' })
  async getCreatedByOrUpdatedByUsers(
    @Body(new ValidationPipe()) params: FetchByUsersDto,
  ) {
    return await handleServiceRequest(
      this.rsService.fetchCreatedByOrUpdatedByUsers(params.by),
    );
  }

  /**
   * Bulk update status of commission difference reasons.
   *
   * Allows activating or deactivating multiple reasons at once.
   *
   * @param body - Status update action and record IDs
   * @param userData - Current authenticated user information
   * @returns Result of the bulk status update operation
   *
   * @note Missing ValidationPipe on body parameter
   */
  @Post('update-status')
  @ApiOperation({
    summary: 'Bulk update status',
    description:
      'Activate or deactivate multiple commission difference reasons',
  })
  @ApiResponse({ status: 200, description: 'Status updated successfully' })
  @ApiResponse({ status: 400, description: 'Invalid request data' })
  async updateStatus(
    @Body() body: UpdateStatusDto, // Missing ValidationPipe
    @UserData() userData: UserDataProps,
  ) {
    return await handleServiceRequest(
      this.rsService.updateStatus(userData.id, body),
    );
  }
}
