import {
  Body,
  Controller,
  Get,
  Param,
  ParseUUIDPipe,
  Patch,
  Post,
  Query,
  UseGuards,
} from '@nestjs/common';
import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard';
import { PermissionGuard } from '../../auth/guards/permission.guard';
import { Permissions } from '../../auth/decorators/permissions.decorator';
import { AccessLevel, ModuleName } from '../../entities/role-permission.entity';
import { successResponse } from '../../common/responses/api-response';
import { ServicePaymentCollectionService } from './service-payment-collection.service';
import { CreateServicePaymentCollectionDto } from './dto/create-service-payment-collection.dto';
import { UpdateServicePaymentCollectionDto } from './dto/update-service-payment-collection.dto';
import { ConfirmCollectionDto } from './dto/confirm-collection.dto';
import { VoidConfirmationDto } from './dto/void-confirmation.dto';
import { ListCollectionsQueryDto } from './dto/list-collections-query.dto';
import {
  SupplierCollectionDriversQueryDto,
  SupplierCollectionQueryDto,
} from './dto/collection-analytics-query.dto';
import { paginatedResponse } from '../../common/responses/api-response';

/**
 * MD Payment Collection HTTP surface.
 *
 * Perm gate:
 *   - GET (incl. by-supplier analytics) → :VIEW on PAYMENT_COLLECTION or
 *     SUPPLIER_COLLECTION respectively
 *   - POST + PATCH (fresh actions) → :EDIT on PAYMENT_COLLECTION
 *   - PATCH on COLLECTED / void-confirmation → :DELETE
 *     (enforced deeper in the service via PermissionCheckService.hasAtLeast
 *      so we don't need per-endpoint status juggling here)
 */
@Controller('service-payment-collections')
@UseGuards(JwtAuthGuard, PermissionGuard)
export class ServicePaymentCollectionController {
  constructor(private readonly service: ServicePaymentCollectionService) {}

  @Get()
  @Permissions({
    module: ModuleName.PAYMENT_COLLECTION,
    accessLevel: AccessLevel.VIEW,
  })
  async list(@Query() query: ListCollectionsQueryDto) {
    const { items } = await this.service.list(query);
    return successResponse(items, 'Service payment collections fetched');
  }

  /**
   * Supplier Collection page. Cash rows come from md_cash_collections.
   * Additional Cost rows come from booking_cash_collections expense columns.
   */
  @Get('by-supplier')
  @Permissions({
    module: ModuleName.SUPPLIER_COLLECTION,
    accessLevel: AccessLevel.VIEW,
  })
  async aggregateBySupplier(@Query() query: SupplierCollectionQueryDto) {
    const { items, meta } = await this.service.aggregateBySupplier({
      collection_kind: query.collection_kind,
      search: query.search,
      date_from: query.date_from,
      date_to: query.date_to,
      page: query.page,
      limit: query.limit,
    });
    return paginatedResponse(items, meta, 'Collections by supplier');
  }

  /**
   * Supplier Collection modal — driver breakdown for a selected supplier.
   * Pass supplier_id for master-linked rows, or supplier_name for
   * free-text suppliers.
   */
  @Get('by-supplier/drivers')
  @Permissions({
    module: ModuleName.SUPPLIER_COLLECTION,
    accessLevel: AccessLevel.VIEW,
  })
  async aggregateSupplierCollectionDrivers(@Query() query: SupplierCollectionDriversQueryDto) {
    const { items, meta } = await this.service.aggregateSupplierCollectionDrivers({
      collection_kind: query.collection_kind,
      collected_by_type: query.collected_by_type,
      collector_name: query.collector_name,
      supplier_id: query.supplier_id,
      supplier_name: query.supplier_name,
      search: query.search,
      date_from: query.date_from,
      date_to: query.date_to,
      page: query.page,
      limit: query.limit,
    });
    return paginatedResponse(items, meta, 'Collections by driver');
  }

  @Get(':id')
  @Permissions({
    module: ModuleName.PAYMENT_COLLECTION,
    accessLevel: AccessLevel.VIEW,
  })
  async findOne(@Param('id', ParseUUIDPipe) id: string) {
    const row = await this.service.findByIdWithDetail(id);
    return successResponse(row, 'Service payment collection fetched');
  }

  @Post()
  @Permissions({
    module: ModuleName.PAYMENT_COLLECTION,
    accessLevel: AccessLevel.EDIT,
  })
  async setRequired(@Body() dto: CreateServicePaymentCollectionDto) {
    const row = await this.service.setRequired(dto);
    return successResponse(row, 'Payment collection required — status PENDING');
  }

  @Patch(':id')
  @Permissions({
    module: ModuleName.PAYMENT_COLLECTION,
    accessLevel: AccessLevel.EDIT,
  })
  async update(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: UpdateServicePaymentCollectionDto,
  ) {
    const row = await this.service.update(id, dto);
    return successResponse(row, 'Payment collection updated');
  }

  @Patch(':id/cancel')
  @Permissions({
    module: ModuleName.PAYMENT_COLLECTION,
    accessLevel: AccessLevel.EDIT,
  })
  async cancel(@Param('id', ParseUUIDPipe) id: string) {
    const row = await this.service.cancel(id);
    return successResponse(row, 'Payment collection cancelled');
  }

  @Post(':id/confirm')
  @Permissions({
    module: ModuleName.PAYMENT_COLLECTION,
    accessLevel: AccessLevel.EDIT,
  })
  async confirm(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: ConfirmCollectionDto,
  ) {
    const row = await this.service.confirm(id, dto);
    return successResponse(row, 'Payment collection confirmed');
  }

  @Post(':id/void-confirmation')
  @Permissions({
    module: ModuleName.PAYMENT_COLLECTION,
    accessLevel: AccessLevel.DELETE,
  })
  async voidConfirmation(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: VoidConfirmationDto,
  ) {
    const row = await this.service.voidLatestConfirmation(id, dto);
    return successResponse(row, 'Confirmation voided — status PENDING');
  }
}
