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

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

// Import the service containing business logic
import { SubAgentCommissionService } from './sub-agent-commission.service';

// Import multiple DTOs for request validation (11 different DTOs!)
import { SearchVisaCountriesDto } from './dto/search-visa-countries-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 { SearchInstitutesDto } from './dto/search-institutes-dto';
import { SearchIntakesDto } from './dto/search-intakes-dto';
import { SearchCommissionInstancesDto } from './dto/search-commission-instances-dto';
import { SearchSubAgentCommissionDto } from './dto/search-dto';
import { SearchAssociateBanksDto } from './dto/search-associate-banks-dto';
import { AnyFileUpload } from 'src/interceptors/file-upload.interceptor';
import { AddAttachmentDto } from './dto/add-attachment.dto';
import { RemoveAttachmentDto } from './dto/remove-attachment.dto';
import { CreateSubAgentCommissionDto } from './dto/create.dto';
import { SearchCommissionReceivedDto } from './dto/search-commission-received-dto';
import {
  UserData,
  UserDataProps,
} from 'src/utils/decorators/user-data.decorator';

// Type alias for Multer file uploads
type MulterFile = Express.Multer.File;

/**
 * SubAgentCommissionController - Handles HTTP requests for sub-agent visa commission management
 *
 * This controller manages the complete lifecycle of visa commission processing for sub-agents.
 * It's a comprehensive controller with 27 endpoints covering various aspects of commission management.
 *
 * Business Context:
 * - Part of an education/visa consultancy commission system
 * - Manages commissions paid to sub-agents for student visa cases
 * - Tracks commission calculations, payments, and documentation
 * - Integrates with multiple reference data systems (countries, institutes, intakes)
 *
 * Key Features:
 * - Comprehensive CRUD operations with file attachments
 * - Multiple reference data endpoints for dropdowns
 * - Advanced search and filtering capabilities
 * - Commission calculation and tracking
 * - File attachment management
 * - User activity tracking
 *
 * @ApiTags('Sub-Agent Visa Commission') - Groups all endpoints in Swagger UI
 * @Controller('') - Base route for this controller
 * @UseGuards(SessionGuard) - Protects all endpoints with session authentication
 */
@ApiTags('Sub-Agent Visa Commission')
@Controller('')
// @UseGuards(AuthGuard) - Commented out alternative authentication guard
// @ApiBearerAuth('defaultBearerAuth') - Commented out bearer auth documentation
@UseGuards(SessionGuard)
export class SubAgentCommissionController {
  /**
   * Constructor with dependency injection
   *
   * @param vcsAgentService - Injected service containing all commission business logic
   * Note: Variable name 'vcsAgentService' might stand for "Visa Commission Sub-Agent Service"
   */
  constructor(private readonly vcsAgentService: SubAgentCommissionService) {}

  /**
   * POST /all - Retrieves paginated sub-agent commissions with advanced filtering
   *
   * This is the main search endpoint for commission records.
   * Uses POST for complex search criteria.
   *
   * @param searchDto - Comprehensive search parameters for commission filtering
   * @returns Paginated list of commission records with metadata
   */
  @Post('all')
  async findAllSubAgentCommission(
    @Body() searchDto: SearchSubAgentCommissionDto,
  ): Promise<any> {
    return await handleServiceRequest(this.vcsAgentService.findAll(searchDto));
  }

  /**
   * POST /visa-service-countries - Retrieves countries for specific visa services
   *
   * Used to get countries where a particular visa service/product is available.
   *
   * @param params - Contains product ID to filter countries
   * @returns List of countries for the specified visa service
   */
  @Post('visa-service-countries')
  async getVisaServiceCountries(
    @Body(new ValidationPipe()) params: SearchVisaCountriesDto,
  ) {
    return await handleServiceRequest(
      this.vcsAgentService.getVisaCountryList(params.product_id),
    );
  }

  /**
   * POST /associate-list - Retrieves list of associates (sub-agents)
   *
   * @returns List of active sub-agents eligible for commissions
   */
  @Post('associate-list')
  async getAssociates() {
    return await handleServiceRequest(this.vcsAgentService.getAssociateList());
  }

  /**
   * POST /institute-list - Retrieves educational institutes
   *
   * Used for commission calculations based on institute partnerships.
   *
   * @param params - Search parameters for institutes (may include country, type, etc.)
   * @returns List of institutes with commission agreements
   */
  @Post('institute-list')
  async getInstitutes(@Body(new ValidationPipe()) params: SearchInstitutesDto) {
    return await handleServiceRequest(
      this.vcsAgentService.getInstituteList(params),
    );
  }

  /**
   * GET /client-countries - Retrieves client countries
   *
   * Client countries = Countries where students/clients come from.
   * Used for commission calculations based on client nationality.
   *
   * @returns List of client countries
   */
  @Get('client-countries')
  async getClientCountries() {
    return await handleServiceRequest(
      this.vcsAgentService.getClientCountryList(),
    );
  }

  /**
   * POST /intake-list - Retrieves academic intakes
   *
   * Intakes = Academic sessions/semesters (Fall, Spring, Summer).
   * Used for commission calculations based on intake timing.
   *
   * @param params - Search parameters for intakes (institute, year, etc.)
   * @returns List of academic intakes
   */
  @Post('intake-list')
  async getIntakes(@Body(new ValidationPipe()) params: SearchIntakesDto) {
    return await handleServiceRequest(
      this.vcsAgentService.getIntakeList(params),
    );
  }

  /**
   * POST /instance-list - Retrieves commission instances
   *
   * Commission instances = Specific commission calculation scenarios/rules.
   * Used for determining commission rates and structures.
   *
   * @param params - Search parameters for commission instances
   * @returns List of commission calculation rules/scenarios
   */
  @Post('instance-list')
  async getCommissionInstances(
    @Body(new ValidationPipe()) params: SearchCommissionInstancesDto,
  ) {
    return await handleServiceRequest(
      this.vcsAgentService.getCommissionInstanceList(params),
    );
  }

  /**
   * GET /company-bank-list - Retrieves company bank accounts
   *
   * Source accounts for commission payments.
   *
   * @returns List of company bank accounts
   */
  @Get('company-bank-list')
  async getCompanyBanks() {
    return await handleServiceRequest(
      this.vcsAgentService.getCompanyBankList(),
    );
  }

  /**
   * POST /associate-bank-list - Retrieves bank accounts for specific associates
   *
   * Destination accounts for commission payments.
   *
   * @param params - Contains associate ID to filter bank accounts
   * @returns Bank accounts for the specified associate
   */
  @Post('associate-bank-list')
  async getAssociateBanks(
    @Body(new ValidationPipe()) params: SearchAssociateBanksDto,
  ) {
    return await handleServiceRequest(
      this.vcsAgentService.getAssociateBankList(params),
    );
  }

  /**
   * POST /save-commission - Creates a new commission record with file attachments
   *
   * Main endpoint for creating commission records.
   * Supports file uploads for documentation.
   *
   * @param params - Validated commission creation data
   * @param files - Uploaded documentation files
   * @param userData - Current user's data for audit trail
   * @returns Created commission record
   */
  @Post('save-commission')
  @UseInterceptors(AnyFileUpload()) // File upload interceptor
  async create(
    @Body(new ValidationPipe()) params: CreateSubAgentCommissionDto,
    @UploadedFiles() files: MulterFile[], // Array of uploaded files
    @UserData() userData: UserDataProps, // User data from session
  ) {
    // Map uploaded files to filenames
    params.attachment_file = files?.map((file) => file.filename) || null;
    return await handleServiceRequest(
      this.vcsAgentService.create(params, userData.id),
    );
  }

  // ==================== FETCH BY LIST ENDPOINTS ====================
  // These endpoints return distinct values from existing commission records
  // Used for filter dropdowns in search interfaces

  /**
   * GET /fetch-service-countries - Retrieves distinct service countries from commissions
   *
   * Only returns countries that have existing commission records.
   */
  @Get('fetch-service-countries')
  async getServiceCountriesByList() {
    return await handleServiceRequest(
      this.vcsAgentService.fetchServiceCountriesByList(),
    );
  }

  /**
   * GET /fetch-client-countries - Retrieves distinct client countries from commissions
   */
  @Get('fetch-client-countries')
  async getClientCountriesByList() {
    return await handleServiceRequest(
      this.vcsAgentService.fetchClientCountriesByList(),
    );
  }

  /**
   * GET /fetch-institutes - Retrieves distinct institutes from commissions
   */
  @Get('fetch-institutes')
  async getInstitutesByList() {
    return await handleServiceRequest(
      this.vcsAgentService.fetchInstitutesByList(),
    );
  }

  /**
   * GET /fetch-associates - Retrieves distinct associates from commissions
   */
  @Get('fetch-associates')
  async getAssociatesByList() {
    return await handleServiceRequest(
      this.vcsAgentService.fetchAssociatesByList(),
    );
  }

  /**
   * GET /fetch-intakes - Retrieves distinct intakes from commissions
   */
  @Get('fetch-intakes')
  async getIntakesByList() {
    return await handleServiceRequest(
      this.vcsAgentService.fetchIntakesByList(),
    );
  }

  /**
   * GET /fetch-instances - Retrieves distinct commission instances from commissions
   */
  @Get('fetch-instances')
  async getInstancesByList() {
    return await handleServiceRequest(
      this.vcsAgentService.fetchInstancesByList(),
    );
  }

  /**
   * GET /fetch-payment-modes - Retrieves distinct payment modes from commissions
   */
  @Get('fetch-payment-modes')
  async getPaymentModesByList() {
    return await handleServiceRequest(
      this.vcsAgentService.fetchPaymentModesByList(),
    );
  }

  /**
   * GET /fetch-from-bank-accounts - Retrieves distinct source bank accounts from commissions
   */
  @Get('fetch-from-bank-accounts')
  async getFromBankAccountsByList() {
    return await handleServiceRequest(
      this.vcsAgentService.fetchFromBankAccountsByList(),
    );
  }

  /**
   * GET /fetch-to-bank-accounts - Retrieves distinct destination bank accounts from commissions
   */
  @Get('fetch-to-bank-accounts')
  async getToBankAccountsByList() {
    return await handleServiceRequest(
      this.vcsAgentService.fetchToBankAccountsByList(),
    );
  }

  /**
   * POST /fetch-users - Retrieves users involved in commission operations
   *
   * Used for filter dropdowns in admin interfaces.
   *
   * @param params - Filter type: 'created_by' or 'updated_by'
   * @returns List of users with their activity
   */
  @Post('fetch-users')
  async getCreatedByOrUpdatedByUsers(
    @Body(new ValidationPipe()) params: FetchByUsersDto,
  ) {
    return await handleServiceRequest(
      this.vcsAgentService.fetchCreatedByOrUpdatedByUsers(params.by),
    );
  }

  // ==================== ATTACHMENT MANAGEMENT ENDPOINTS ====================

  /**
   * GET /view-attachments/:id - Retrieves attachments for a specific commission
   *
   * @param id - Commission record ID
   * @returns List of file attachments with metadata
   */
  @Get('view-attachments/:id')
  async getAttachments(@Param('id') id: string) {
    return await handleServiceRequest(this.vcsAgentService.getAttachments(id));
  }

  /**
   * POST /remove-attachment - Removes an attachment from a commission record
   *
   * @param attachment - Contains commission ID and file name to remove
   * @param userData - Current user's data for audit trail
   * @returns Removal result
   */
  @Post('remove-attachment')
  async removeAttachments(
    @Body(new ValidationPipe()) attachment: RemoveAttachmentDto,
    @UserData() userData: UserDataProps,
  ) {
    return await handleServiceRequest(
      this.vcsAgentService.removeAttachments(attachment, userData),
    );
  }

  /**
   * POST /add-attachment - Adds new attachments to an existing commission record
   *
   * @param body - Contains commission ID and file metadata
   * @param files - Uploaded files to attach
   * @param userData - Current user's data for audit trail
   * @returns Added attachments result
   */
  @Post('add-attachment')
  @UseInterceptors(AnyFileUpload())
  async addAttachments(
    @Body(new ValidationPipe()) body: AddAttachmentDto,
    @UploadedFiles() files: MulterFile[],
    @UserData() userData: UserDataProps,
  ) {
    // Map uploaded files to filenames
    body.attachment_file = files?.map((file) => file.filename) || null;
    return await handleServiceRequest(
      this.vcsAgentService.addAttachments(body, userData),
    );
  }

  /**
   * POST /case-commission-received - Retrieves commission received for specific cases
   *
   * Special endpoint for tracking commission receipt status.
   * Likely used for reconciliation and payment tracking.
   *
   * @param params - Search parameters for commission receipt tracking
   * @returns List of commission receipt records
   */
  @Post('case-commission-received')
  async getCaseCommissionReceived(
    @Body(new ValidationPipe()) params: SearchCommissionReceivedDto,
  ) {
    return await handleServiceRequest(
      this.vcsAgentService.getCaseCommissionReceivedList(params),
    );
  }

  @Post('details-by-id')
  async getDetailsById(
    @Body(new ValidationPipe()) body: Record<string, string>,
  ) {
    return await handleServiceRequest(
      this.vcsAgentService.findDetailsById(body.id),
    );
  }
}
