import { Body, Controller, Delete, Get, HttpCode, Param, ParseUUIDPipe, Patch, Post, Query } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';

import { BookingStaff } from '../../common/booking-guards';
import { FREIGHT_PERMS } from '../../seed/freight-permissions.registry';
import {
  AllocationPreviewDto,
  CreateAllocationRuleDto,
  UpdateAllocationRuleDto,
} from './dto/allocation-rule.dto';
import { CreateFeeRuleDto, UpdateFeeRuleDto } from './dto/fee-rule.dto';
import { AcknowledgeAccrualDto } from './dto/acknowledge-accrual.dto';
import { WarehouseAllocationService } from './warehouse-allocation.service';
import { WarehouseFeeService } from './warehouse-fee.service';

@ApiTags('warehouse-rules')
@ApiBearerAuth()
@Controller()
export class WarehouseRulesController {
  constructor(
    private readonly allocationService: WarehouseAllocationService,
    private readonly feeService: WarehouseFeeService,
  ) {}

  // ── Allocation rules ───────────────────────────────────────────────────────
  @Get('warehouse-allocation-rules')
  @BookingStaff(FREIGHT_PERMS.warehouseAllocationRules.view)
  @ApiOperation({ summary: 'List warehouse allocation rules' })
  listAllocationRules() {
    return this.allocationService.listRules();
  }

  @Post('warehouse-allocation-rules')
  @BookingStaff(FREIGHT_PERMS.warehouseAllocationRules.create)
  @ApiOperation({ summary: 'Create a warehouse allocation rule' })
  createAllocationRule(@Body() dto: CreateAllocationRuleDto) {
    return this.allocationService.createRule(dto);
  }

  @Patch('warehouse-allocation-rules/:id')
  @BookingStaff(FREIGHT_PERMS.warehouseAllocationRules.update)
  @ApiOperation({ summary: 'Update a warehouse allocation rule' })
  updateAllocationRule(@Param('id', ParseUUIDPipe) id: string, @Body() dto: UpdateAllocationRuleDto) {
    return this.allocationService.updateRule(id, dto);
  }

  @Delete('warehouse-allocation-rules/:id')
  @HttpCode(204)
  @BookingStaff(FREIGHT_PERMS.warehouseAllocationRules.delete)
  @ApiOperation({ summary: 'Delete a warehouse allocation rule' })
  deleteAllocationRule(@Param('id', ParseUUIDPipe) id: string) {
    return this.allocationService.deleteRule(id);
  }

  @Post('warehouse-allocation/preview')
  @BookingStaff(FREIGHT_PERMS.warehouseAllocationRules.view)
  @ApiOperation({ summary: 'Preview the yard/warehouse/zone a booking would be allocated to' })
  previewAllocation(@Body() dto: AllocationPreviewDto) {
    return this.allocationService.resolveLocation(dto);
  }

  // ── Fee rules ────────────────────────────────────────────────────────────────
  @Get('warehouse-fee-rules')
  @BookingStaff(FREIGHT_PERMS.warehouseFeeRules.view)
  @ApiOperation({ summary: 'List storage / demurrage fee rules' })
  listFeeRules() {
    return this.feeService.listRules();
  }

  @Post('warehouse-fee-rules')
  @BookingStaff(FREIGHT_PERMS.warehouseFeeRules.create)
  @ApiOperation({ summary: 'Create a storage / demurrage fee rule' })
  createFeeRule(@Body() dto: CreateFeeRuleDto) {
    return this.feeService.createRule(dto);
  }

  @Patch('warehouse-fee-rules/:id')
  @BookingStaff(FREIGHT_PERMS.warehouseFeeRules.update)
  @ApiOperation({ summary: 'Update a fee rule' })
  updateFeeRule(@Param('id', ParseUUIDPipe) id: string, @Body() dto: UpdateFeeRuleDto) {
    return this.feeService.updateRule(id, dto);
  }

  @Delete('warehouse-fee-rules/:id')
  @HttpCode(204)
  @BookingStaff(FREIGHT_PERMS.warehouseFeeRules.delete)
  @ApiOperation({ summary: 'Delete a fee rule' })
  deleteFeeRule(@Param('id', ParseUUIDPipe) id: string) {
    return this.feeService.deleteRule(id);
  }

  @Get('warehouse-fees/accrual-dashboard')
  @BookingStaff(FREIGHT_PERMS.warehouseFeeRules.view)
  @ApiOperation({ summary: 'Live per-item fee accrual (storage/demurrage) with alerts' })
  accrualDashboard(@Query('billingCurrency') billingCurrency?: string) {
    return this.feeService.accrualDashboard(billingCurrency);
  }

  @Get('warehouse-fees/on-time-dispatch')
  @BookingStaff(FREIGHT_PERMS.warehouseFeeRules.view)
  @ApiOperation({ summary: 'On-time dispatch rate — items that left before storage free-days expired' })
  onTimeDispatch() {
    return this.feeService.onTimeDispatchStats();
  }

  @Post('warehouse-fees/accrual/:inventoryId/acknowledge')
  @BookingStaff(FREIGHT_PERMS.warehouseFeeRules.update)
  @ApiOperation({ summary: 'Acknowledge / snooze an item fee-accrual alert' })
  acknowledgeAccrual(
    @Param('inventoryId', ParseUUIDPipe) inventoryId: string,
    @Body() dto: AcknowledgeAccrualDto,
  ) {
    return this.feeService.acknowledgeAccrual(inventoryId, {
      snoozeDays: dto.snoozeDays,
      note: dto.note,
    });
  }

  @Delete('warehouse-fees/accrual/:inventoryId/acknowledge')
  @HttpCode(204)
  @BookingStaff(FREIGHT_PERMS.warehouseFeeRules.update)
  @ApiOperation({ summary: 'Remove an accrual acknowledgement (re-surface for alerts)' })
  unacknowledgeAccrual(@Param('inventoryId', ParseUUIDPipe) inventoryId: string) {
    return this.feeService.unacknowledgeAccrual(inventoryId);
  }

  @Get('warehouse-inventory/:id/fee-preview')
  @BookingStaff(FREIGHT_PERMS.warehouseFeeRules.view)
  @ApiOperation({ summary: 'Preview demurrage + storage fees for an inventory item' })
  feePreview(
    @Param('id', ParseUUIDPipe) id: string,
    @Query('billingCurrency') billingCurrency?: string,
  ) {
    return this.feeService.previewForInventory(id, billingCurrency);
  }

  @Get('last-mile/:id/truck-detention-preview')
  @BookingStaff(FREIGHT_PERMS.warehouseFeeRules.view)
  @ApiOperation({ summary: 'Preview truck detention for a last-mile leg (per truck per day after grace)' })
  truckDetentionPreview(
    @Param('id', ParseUUIDPipe) id: string,
    @Query('billingCurrency') billingCurrency?: string,
  ) {
    return this.feeService.previewTruckDetention(id, billingCurrency);
  }
}
