import {
  Body,
  Controller,
  Get,
  Param,
  ParseUUIDPipe,
  Post,
  Put,
  Query,
  UseGuards,
} from '@nestjs/common';
import {
  IsDateString,
  IsEnum,
  IsInt,
  IsNumber,
  IsOptional,
  IsString,
  IsUUID,
  Min,
} from 'class-validator';
import {
  DeliveryFormStatus,
  DeliveryRequestStatus,
  DeliveryRequestType,
  InvoiceStatus,
  RevenueRecognitionStatus,
} from '@prisma/client';
import { JwtAuthGuard } from '@modules/organization/auth/guards/jwt-auth.guard';
import { PermissionsGuard } from '@modules/organization/auth/guards/permissions.guard';
import { RequirePermissions } from '@common/decorators/permissions.decorator';
import { CurrentUser } from '@common/decorators/current-user.decorator';
import type { CurrentUserPayload } from '@common/decorators/current-user.decorator';
import { NIL_ORG_ID } from '@common/constants/nil-uuid';
import { parsePositiveInt } from '@common/utils/query-parsers';
import { Auditable, Financial } from '@core/observability/audit/decorators/auditable.decorator';
import { DeliveryService } from './delivery.service';

class CreateDeliveryRequestDto {
  @IsString() deliveryNo!: string;
  @IsUUID() salesOrderId!: string;
  @IsUUID() customerId!: string;
  @IsEnum(DeliveryRequestType) requestType!: DeliveryRequestType;
  @IsDateString() expectedDate!: string;
  @IsOptional() @IsString() notes?: string;
}

class UpdateDeliveryRequestDto {
  @IsOptional() @IsEnum(DeliveryRequestStatus) status?: DeliveryRequestStatus;
  @IsOptional() @IsDateString() expectedDate?: string;
  @IsOptional() @IsString() notes?: string;
}

class CreateFulfillmentDto {
  @IsUUID() deliveryRequestId!: string;
  @IsUUID() robotUnitId!: string;
  @IsDateString() deliveredAt!: string;
  @IsOptional() @IsDateString() signedAt?: string;
  @IsOptional() @IsEnum(DeliveryFormStatus) signedFormStatus?: DeliveryFormStatus;
  @IsOptional() @IsEnum(DeliveryFormStatus) acceptanceFormStatus?: DeliveryFormStatus;
  @IsOptional() @IsEnum(DeliveryFormStatus) acceptanceFormPreDel?: DeliveryFormStatus;
  @IsOptional() @IsUUID() acceptanceFormAttachmentId?: string;
  @IsOptional() @IsString() sapPgiDocNo?: string;
  @IsOptional() @IsNumber() cost?: number;
  @IsOptional() @IsString() notePreDel?: string;
  @IsOptional() @IsString() additionalShippingNotes?: string;
}

class UpdateFulfillmentDto {
  @IsOptional() @IsEnum(DeliveryFormStatus) signedFormStatus?: DeliveryFormStatus;
  @IsOptional() @IsEnum(DeliveryFormStatus) acceptanceFormStatus?: DeliveryFormStatus;
  @IsOptional() @IsEnum(DeliveryFormStatus) acceptanceFormPreDel?: DeliveryFormStatus;
  @IsOptional() @IsEnum(RevenueRecognitionStatus) revenueRecognition?: RevenueRecognitionStatus;
  @IsOptional() @IsEnum(InvoiceStatus) invoiceStatus?: InvoiceStatus;
  @IsOptional() @IsNumber() cost?: number;
  @IsOptional() @IsNumber() grossMargin?: number;
  @IsOptional() @IsString() notePreDel?: string;
  @IsOptional() @IsString() additionalShippingNotes?: string;
}

@Controller('robot-manager')
@UseGuards(JwtAuthGuard, PermissionsGuard)
export class DeliveryController {
  constructor(private readonly service: DeliveryService) {}

  // ---- requests ----

  @Get('delivery-requests')
  @RequirePermissions('robot-manager:read')
  listRequests(
    @Query('salesOrderId') salesOrderId?: string,
    @Query('customerId') customerId?: string,
    @Query('status') status?: DeliveryRequestStatus,
    @Query('page') page?: string,
    @Query('limit') limit?: string,
  ) {
    return this.service.listRequests({
      salesOrderId,
      customerId,
      status,
      page: parsePositiveInt(page),
      limit: parsePositiveInt(limit),
    });
  }

  @Get('delivery-requests/:id')
  @RequirePermissions('robot-manager:read')
  findRequest(@Param('id', new ParseUUIDPipe()) id: string) {
    return this.service.findRequest(id);
  }

  @Post('delivery-requests')
  @Auditable()
  @RequirePermissions('robot-manager:create')
  createRequest(@Body() dto: CreateDeliveryRequestDto, @CurrentUser() user: CurrentUserPayload) {
    return this.service.createRequest(dto, user.userId, NIL_ORG_ID);
  }

  @Put('delivery-requests/:id')
  @Auditable()
  @RequirePermissions('robot-manager:update')
  updateRequest(
    @Param('id', new ParseUUIDPipe()) id: string,
    @Body() dto: UpdateDeliveryRequestDto,
    @CurrentUser() user: CurrentUserPayload,
  ) {
    return this.service.updateRequest(id, dto, user.userId);
  }

  // ---- fulfillments ----

  @Get('delivery-fulfillments/:id')
  @RequirePermissions('robot-manager:read')
  findFulfillment(@Param('id', new ParseUUIDPipe()) id: string) {
    return this.service.findFulfillment(id);
  }

  @Post('delivery-fulfillments')
  @Auditable()
  @Financial()
  @RequirePermissions('robot-manager:create')
  createFulfillment(@Body() dto: CreateFulfillmentDto, @CurrentUser() user: CurrentUserPayload) {
    return this.service.createFulfillment(dto, user.userId, NIL_ORG_ID);
  }

  @Put('delivery-fulfillments/:id')
  @Auditable()
  @Financial()
  @RequirePermissions('robot-manager:update')
  updateFulfillment(@Param('id', new ParseUUIDPipe()) id: string, @Body() dto: UpdateFulfillmentDto) {
    return this.service.updateFulfillment(id, dto);
  }
}
