import {
  Body,
  Controller,
  Get,
  Param,
  ParseUUIDPipe,
  Post,
  Put,
  UseGuards,
} from '@nestjs/common';
import {
  IsBoolean,
  IsDateString,
  IsEnum,
  IsInt,
  IsOptional,
  IsString,
  IsUUID,
  Min,
} from 'class-validator';
import {
  FccStatus,
  LogisticsStatus,
  QualityLabelStatus,
  RobotPhysicalStatus,
  StickerStatus,
} 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 { Auditable } from '@core/observability/audit/decorators/auditable.decorator';
import { RobotRecordsService } from './robot-records.service';

class UpsertQualityLabelDto {
  @IsString() labelTypeCode!: string;
  @IsOptional() @IsEnum(QualityLabelStatus) status?: QualityLabelStatus;
  @IsOptional() @IsUUID() appliedById?: string;
  @IsOptional() @IsUUID() verifiedById?: string;
  @IsOptional() @IsUUID() photoAttachmentId?: string;
}

class UpsertReadinessDto {
  @IsOptional() @IsUUID() specialistId?: string;
  @IsOptional() @IsEnum(RobotPhysicalStatus) physicalProductStatus?: RobotPhysicalStatus;
  // ⚠️ 必须 @IsBoolean()。global ValidationPipe whitelist:true 会 strip 没装饰器的字段，
  // 导致 service 端的「10 配件齐 → 自动 set completedAt」逻辑永远不触发。
  @IsOptional() @IsBoolean() hasRobot?: boolean;
  @IsOptional() @IsBoolean() hasBattery?: boolean;
  @IsOptional() @IsBoolean() hasRemote?: boolean;
  @IsOptional() @IsBoolean() hasUsaPowerCable?: boolean;
  @IsOptional() @IsBoolean() hasCnCableWithAdapter?: boolean;
  @IsOptional() @IsBoolean() hasPowerSupply?: boolean;
  @IsOptional() @IsBoolean() hasChargingDock?: boolean;
  @IsOptional() @IsBoolean() hasFootPads?: boolean;
  @IsOptional() @IsBoolean() hasToolsKit?: boolean;
  @IsOptional() @IsBoolean() hasPaperwork?: boolean;
}

class AddInspectionDto {
  /// 可选；未传时 service 在事务内派生 max+1。
  /// 前端切勿用 stale 本地 state 派生（W1 PDI 重测会撞 (robotUnitId, inspectionNo) unique）。
  @IsOptional() @IsInt() @Min(1) inspectionNo?: number;
  @IsOptional() @IsUUID() inspectorId?: string;
  @IsOptional() @IsString() issue?: string;
  @IsOptional() @IsString() issueTagCode?: string;
  @IsOptional() @IsDateString() resolvedAt?: string;
  @IsOptional() @IsUUID() resolvedById?: string;
}

class AddLogisticsLegDto {
  @IsInt() @Min(1) legNo!: number;
  @IsOptional() @IsUUID() fromLocationId?: string;
  @IsOptional() @IsUUID() toLocationId?: string;
  @IsOptional() @IsDateString() departedAt?: string;
  @IsOptional() @IsDateString() arrivedAt?: string;
  @IsEnum(LogisticsStatus) logisticsStatus!: LogisticsStatus;
  @IsOptional() @IsString() importDeclarationTypeCode?: string;
  @IsOptional() @IsString() tariffTypeCode?: string;
  @IsOptional() @IsUUID() shippingReceiptAttachmentId?: string;
  @IsOptional() @IsString() additionalNotes?: string;
}

class UpsertComplianceDto {
  @IsOptional() @IsDateString() dateReady?: string;
  @IsOptional() @IsEnum(StickerStatus) stickerStatus?: StickerStatus;
  @IsOptional() @IsEnum(FccStatus) fccStatus?: FccStatus;
  @IsOptional() @IsString() complianceNotes?: string;
}

@Controller('robot-manager/:robotId')
@UseGuards(JwtAuthGuard, PermissionsGuard)
export class RobotRecordsController {
  constructor(private readonly service: RobotRecordsService) {}

  // QualityLabels
  @Get('quality-labels')
  @RequirePermissions('robot-manager:read')
  listLabels(@Param('robotId', new ParseUUIDPipe()) robotId: string) {
    return this.service.listQualityLabels(robotId);
  }

  @Put('quality-labels')
  @Auditable()
  @RequirePermissions('robot-manager:update')
  upsertLabel(
    @Param('robotId', new ParseUUIDPipe()) robotId: string,
    @Body() dto: UpsertQualityLabelDto,
    @CurrentUser() user: CurrentUserPayload,
  ) {
    return this.service.upsertQualityLabel(robotId, dto.labelTypeCode, dto, user.userId, NIL_ORG_ID);
  }

  // Readiness
  @Get('readiness')
  @RequirePermissions('robot-manager:read')
  findReadiness(@Param('robotId', new ParseUUIDPipe()) robotId: string) {
    return this.service.findReadiness(robotId);
  }

  @Put('readiness')
  @Auditable()
  @RequirePermissions('robot-manager:update')
  upsertReadiness(
    @Param('robotId', new ParseUUIDPipe()) robotId: string,
    @Body() dto: UpsertReadinessDto,
    @CurrentUser() user: CurrentUserPayload,
  ) {
    return this.service.upsertReadiness(robotId, dto, user.userId, NIL_ORG_ID);
  }

  // Inspections
  @Get('inspections')
  @RequirePermissions('robot-manager:read')
  listInspections(@Param('robotId', new ParseUUIDPipe()) robotId: string) {
    return this.service.listInspections(robotId);
  }

  @Post('inspections')
  @Auditable()
  @RequirePermissions('robot-manager:update')
  addInspection(
    @Param('robotId', new ParseUUIDPipe()) robotId: string,
    @Body() dto: AddInspectionDto,
    @CurrentUser() user: CurrentUserPayload,
  ) {
    return this.service.addInspection(robotId, dto, user.userId, NIL_ORG_ID);
  }

  // LogisticsLegs
  @Get('logistics-legs')
  @RequirePermissions('robot-manager:read')
  listLegs(@Param('robotId', new ParseUUIDPipe()) robotId: string) {
    return this.service.listLogisticsLegs(robotId);
  }

  @Post('logistics-legs')
  @Auditable()
  @RequirePermissions('robot-manager:update')
  addLeg(
    @Param('robotId', new ParseUUIDPipe()) robotId: string,
    @Body() dto: AddLogisticsLegDto,
    @CurrentUser() user: CurrentUserPayload,
  ) {
    return this.service.addLogisticsLeg(robotId, dto, user.userId, NIL_ORG_ID);
  }

  // Compliance
  @Get('compliance')
  @RequirePermissions('robot-manager:read')
  findCompliance(@Param('robotId', new ParseUUIDPipe()) robotId: string) {
    return this.service.findCompliance(robotId);
  }

  @Put('compliance')
  @Auditable()
  @RequirePermissions('robot-manager:update')
  upsertCompliance(
    @Param('robotId', new ParseUUIDPipe()) robotId: string,
    @Body() dto: UpsertComplianceDto,
    @CurrentUser() user: CurrentUserPayload,
  ) {
    return this.service.upsertCompliance(robotId, dto, user.userId, NIL_ORG_ID);
  }
}
