import {
  Body,
  Controller,
  Get,
  Param,
  Post,
  UploadedFiles,
  UseGuards,
  UseInterceptors,
  ValidationPipe,
} from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { VisaCommissionReceivedService } from './visa-commission-received.service';
import { SearchDto } from './dto/search-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 { FetchByAssociationTypesDto } from './dto/fetch-by-association-types.dto';
import { RemoveAttachmentDto } from './dto/remove-attachment.dto';
import { AnyFileUpload } from 'src/interceptors/file-upload.interceptor';
import { AddAttachmentDto } from './dto/add-attachment.dto';
import { MulterFile } from 'src/constants/types/multer-file.type';
import { ReceivedInfoDto } from './dto/received-info-dto';
import {
  UserData,
  UserDataProps,
} from 'src/utils/decorators/user-data.decorator';

/**
 * VisaCommissionReceivedController - REST API controller for commission received management
 *
 * This controller handles all HTTP endpoints related to tracking and managing
 * commission payments that have been received from institutes and master agents.
 * It focuses on the post-enquiry phase where commissions are actually paid and received.
 *
 * Business Domain: Commission Payment Tracking & Reconciliation System
 * - Tracks actual commission payments received from institutes and agents
 * - Manages payment proofs and documentation
 * - Handles attachment management for payment verification
 * - Provides comprehensive filtering for payment tracking
 * - Supports reconciliation between expected and received commissions
 *
 * Key Features:
 * - Commission payment tracking with multiple filter criteria
 * - File attachment management for payment proofs (receipts, bank statements)
 * - Comprehensive reference data endpoints for filtering
 * - Dual workflow support (institute vs master agent payments)
 * - Audit trail with user tracking
 *
 * Security: Protected by SessionGuard for user authentication
 * File Upload: Supports file attachments for payment documentation
 */
@ApiTags('Visa Commission Received') // Swagger API documentation grouping
@Controller('') // Root path controller
// @UseGuards(AuthGuard) // Alternative authentication guard (commented out)
// @ApiBearerAuth('defaultBearerAuth') // Swagger authentication documentation
@UseGuards(SessionGuard) // Session-based authentication guard
export class VisaCommissionReceivedController {
  constructor(
    private readonly vcReceivedService: VisaCommissionReceivedService,
  ) {}

  /**
   * Get all received commission payments with advanced filtering
   *
   * POST endpoint for paginated search of received commission payments
   * Supports comprehensive filtering including:
   * - Date range filtering for payment dates
   * - Association type filtering (institute vs master agent)
   * - Payment status and mode filtering
   * - Institute/agent filtering
   * - Country and intake filtering
   *
   * @param searchDto - Comprehensive search parameters including:
   *   - Pagination (page, per_page)
   *   - Date range filters for payment dates
   *   - Association type filtering (1=Institute, 2=Master Agent)
   *   - Payment mode and status filtering
   *   - Reference ID filtering
   *
   * @returns Paginated list of received commission payments
   */
  @Post('all')
  async findAllInstituteCommissions(
    @Body() searchDto: SearchDto,
  ): Promise<any> {
    return await handleServiceRequest(
      this.vcReceivedService.findAll(searchDto),
    );
  }

  /**
   * Get distinct visa service countries by association type for filtering
   *
   * Used to populate filter dropdowns in the commission received interface
   * Shows only countries where commission payments have been received
   *
   * @param params - Contains association type for filtering
   * @returns Distinct visa service countries where commissions were received
   */
  @Post('fetch-service-countries')
  async getServiceCountriesByList(
    @Body(new ValidationPipe()) params: FetchByAssociationTypesDto,
  ) {
    return await handleServiceRequest(
      this.vcReceivedService.fetchServiceCountriesByList(params.type),
    );
  }

  /**
   * Get distinct client countries by association type for filtering
   *
   * Shows client countries (student nationalities) for which commissions were received
   *
   * @param params - Contains association type for filtering
   * @returns Distinct client countries of students for whom commissions were received
   */
  @Post('fetch-client-countries')
  async getClientCountriesByList(
    @Body(new ValidationPipe()) params: FetchByAssociationTypesDto,
  ) {
    return await handleServiceRequest(
      this.vcReceivedService.fetchClientCountriesByList(params.type),
    );
  }

  /**
   * Get distinct institutes by association type for filtering
   *
   * Shows institutes that have made commission payments
   *
   * @param params - Contains association type for filtering
   * @returns Distinct institutes that have paid commissions
   */
  @Post('fetch-institutes')
  async getInstitutesByList(
    @Body(new ValidationPipe()) params: FetchByAssociationTypesDto,
  ) {
    return await handleServiceRequest(
      this.vcReceivedService.fetchInstitutesByList(params.type),
    );
  }

  /**
   * Get distinct associates (master agents) by association type for filtering
   *
   * Shows master agents who have made commission payments
   *
   * @param params - Contains association type for filtering
   * @returns Distinct master agents that have paid commissions
   */
  @Post('fetch-associates')
  async getAssociatesByList(
    @Body(new ValidationPipe()) params: FetchByAssociationTypesDto,
  ) {
    return await handleServiceRequest(
      this.vcReceivedService.fetchAssociatesByList(params.type),
    );
  }

  /**
   * Get distinct intake periods by association type for filtering
   *
   * Shows academic intake periods for which commissions were received
   *
   * @param params - Contains association type for filtering
   * @returns Distinct intake periods with commission payments
   */
  @Post('fetch-intakes')
  async getIntakesByList(
    @Body(new ValidationPipe()) params: FetchByAssociationTypesDto,
  ) {
    return await handleServiceRequest(
      this.vcReceivedService.fetchIntakesByList(params.type),
    );
  }

  /**
   * Get distinct commission instances by association type for filtering
   *
   * Shows specific commission contract instances for which payments were received
   *
   * @param params - Contains association type for filtering
   * @returns Distinct commission instances with received payments
   */
  @Post('fetch-instances')
  async getInstancesByList(
    @Body(new ValidationPipe()) params: FetchByAssociationTypesDto,
  ) {
    return await handleServiceRequest(
      this.vcReceivedService.fetchInstancesByList(params.type),
    );
  }

  /**
   * Get distinct payment modes by association type for filtering
   *
   * Shows payment methods used for commission payments (bank transfer, cash, etc.)
   *
   * @param params - Contains association type for filtering
   * @returns Distinct payment modes used for commission payments
   */
  @Post('fetch-payment-modes')
  async getPaymentModesByList(
    @Body(new ValidationPipe()) params: FetchByAssociationTypesDto,
  ) {
    return await handleServiceRequest(
      this.vcReceivedService.fetchPaymentModesByList(params.type),
    );
  }

  /**
   * Get distinct bank accounts by association type for filtering
   *
   * Shows bank accounts into which commission payments were received
   *
   * @param params - Contains association type for filtering
   * @returns Distinct bank accounts used for commission receipts
   */
  @Post('fetch-received-bank-accounts')
  async getReceivedBankAccountsByList(
    @Body(new ValidationPipe()) params: FetchByAssociationTypesDto,
  ) {
    return await handleServiceRequest(
      this.vcReceivedService.fetchReceivedBankAccountsByList(params.type),
    );
  }

  /**
   * Get distinct users who created or updated commission received records
   *
   * Used for audit trail and filtering by responsible users
   *
   * @param params - Contains filter type ('created_by' or 'updated_by') and association type
   * @returns Distinct users with formatted names who handled commission receipts
   */
  @Post('fetch-users')
  async getCreatedByOrUpdatedByUsers(
    @Body(new ValidationPipe()) params: FetchByUsersDto,
  ) {
    return await handleServiceRequest(
      this.vcReceivedService.fetchCreatedByOrUpdatedByUsers(
        params.by,
        params.type,
      ),
    );
  }

  /**
   * View attachment files for a specific commission received record
   *
   * Retrieves all attachment files (payment proofs, receipts, bank statements)
   * associated with a commission received record
   *
   * @param id - Commission received record ID
   * @returns List of attachment file names and details
   */
  @Get('view-attachments/:id')
  async getAttachments(@Param('id') id: string) {
    return await handleServiceRequest(
      this.vcReceivedService.getAttachments(id),
    );
  }

  /**
   * Remove an attachment file from a commission received record
   *
   * Supports removal of attachment files with audit tracking
   * Also physically removes the file from storage
   *
   * @param attachment - Contains file information and target record ID
   * @param userData - Authenticated user information for audit tracking
   * @returns Removal result
   */
  @Post('remove-attachment')
  async removeAttachments(
    @Body(new ValidationPipe()) attachment: RemoveAttachmentDto,
    @UserData() userData: UserDataProps,
  ) {
    return await handleServiceRequest(
      this.vcReceivedService.removeAttachments(attachment, userData),
    );
  }

  /**
   * Add attachment files to a commission received record
   *
   * Supports file uploads for payment proofs and documentation
   * Uses file interceptor for handling uploaded files
   *
   * @param body - Contains target record ID and file information
   * @param files - Uploaded file attachments
   * @param userData - Authenticated user information for audit tracking
   * @returns Addition result
   */
  @Post('add-attachment')
  @UseInterceptors(AnyFileUpload()) // File upload interceptor
  async addAttachments(
    @Body(new ValidationPipe()) body: AddAttachmentDto,
    @UploadedFiles() files: MulterFile[],
    @UserData() userData: UserDataProps,
  ) {
    // Extract filenames from uploaded files
    body.attachment_file = files?.map((file) => file.filename) || null;

    return await handleServiceRequest(
      this.vcReceivedService.addAttachments(body, userData),
    );
  }

  /**
   * Get detailed commission received information for specific cases
   *
   * Used for reconciliation and detailed payment tracking
   * Shows per-case commission received details including amounts, dates, and status
   *
   * @param params - Search parameters for commission received details
   * @returns Detailed commission received information
   */
  @Post('received-info')
  async getReceivedInfo(@Body(new ValidationPipe()) params: ReceivedInfoDto) {
    return await handleServiceRequest(
      this.vcReceivedService.findDetails(params),
    );
  }
}
