import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  ParseUUIDPipe,
  Post,
  Put,
  Query,
  UseGuards,
} from '@nestjs/common';
import { IsBoolean, IsNumber, IsOptional, IsString, IsUUID } from 'class-validator';
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 { Auditable, Sensitive } from '@core/observability/audit/decorators/auditable.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 { RobotSystemConfigService } from './services/robot-system-config.service';
import { RobotModelService } from './services/robot-model.service';
import { RobotSkuService } from './services/robot-sku.service';

class UpsertConfigDto {
  value!: unknown;
  @IsOptional() @IsString() description?: string;
}

class CreateModelDto {
  @IsString() code!: string;
  @IsString() name!: string;
  @IsOptional() @IsString() brand?: string;
  @IsOptional() @IsString() description?: string;
  @IsOptional() @IsString() imageUrl?: string;
  @IsOptional() @IsBoolean() enabled?: boolean;
  @IsOptional() metadata?: Record<string, unknown>;
}

class UpdateModelDto {
  @IsOptional() @IsString() name?: string;
  @IsOptional() @IsString() brand?: string;
  @IsOptional() @IsString() description?: string;
  @IsOptional() @IsString() imageUrl?: string;
  @IsOptional() @IsBoolean() enabled?: boolean;
  @IsOptional() metadata?: Record<string, unknown>;
}

class CreateSkuDto {
  @IsUUID() modelId!: string;
  @IsString() code!: string;
  @IsString() name!: string;
  @IsOptional() @IsString() variant?: string;
  @IsOptional() @IsNumber() defaultPrice?: number;
  @IsOptional() @IsNumber() defaultCost?: number;
  @IsOptional() @IsString() currencyCode?: string;
  @IsOptional() @IsString() description?: string;
  @IsOptional() @IsBoolean() enabled?: boolean;
}

class UpdateSkuDto {
  @IsOptional() @IsString() name?: string;
  @IsOptional() @IsString() variant?: string;
  @IsOptional() @IsNumber() defaultPrice?: number;
  @IsOptional() @IsNumber() defaultCost?: number;
  @IsOptional() @IsString() currencyCode?: string;
  @IsOptional() @IsString() description?: string;
  @IsOptional() @IsBoolean() enabled?: boolean;
}

/**
 * robot-manager 管理台 — Model / SKU / 系统配置
 * 路由前缀：/robot-manager/admin
 *
 * v3 重构后 Customer/Supplier/Location/Partner/Attachment 已迁到 platform-master，
 * 管理端走 /platform-master/* CRUD endpoints。
 */
@Controller('robot-manager/admin')
@UseGuards(JwtAuthGuard, PermissionsGuard)
export class RobotAdminController {
  constructor(
    private readonly configService: RobotSystemConfigService,
    private readonly modelService: RobotModelService,
    private readonly skuService: RobotSkuService,
  ) {}

  // ============ RobotSystemConfig ============

  @Get('config')
  @RequirePermissions('robot-manager:read')
  async listConfig() {
    return this.configService.list();
  }

  @Get('config/:key')
  @RequirePermissions('robot-manager:read')
  async getConfig(@Param('key') key: string) {
    return { key, value: await this.configService.get(key) };
  }

  @Put('config/:key')
  @Auditable()
  @RequirePermissions('robot-manager:manage:fields')
  async setConfig(@Param('key') key: string, @Body() body: UpsertConfigDto) {
    return this.configService.set(key, body.value, body.description);
  }

  @Delete('config/:key')
  @Auditable()
  @Sensitive()
  @RequirePermissions('robot-manager:manage:fields')
  async deleteConfig(@Param('key') key: string) {
    return this.configService.delete(key);
  }

  // ============ RobotModel ============

  @Get('models')
  @RequirePermissions('robot-manager:read')
  async listModels(@Query('search') search?: string, @Query('enabledOnly') enabledOnly?: string) {
    return this.modelService.list({ search, enabledOnly: enabledOnly === 'true' });
  }

  @Get('models/:id')
  @RequirePermissions('robot-manager:read')
  async getModel(@Param('id', new ParseUUIDPipe()) id: string) {
    return this.modelService.findOne(id);
  }

  @Post('models')
  @Auditable()
  @RequirePermissions('robot-manager:manage:models')
  async createModel(@Body() dto: CreateModelDto, @CurrentUser() user: CurrentUserPayload) {
    return this.modelService.create(dto, user.userId, NIL_ORG_ID);
  }

  @Put('models/:id')
  @Auditable()
  @RequirePermissions('robot-manager:manage:models')
  async updateModel(@Param('id', new ParseUUIDPipe()) id: string, @Body() dto: UpdateModelDto) {
    return this.modelService.update(id, dto);
  }

  @Delete('models/:id')
  @Auditable()
  @Sensitive()
  @RequirePermissions('robot-manager:manage:models')
  async deleteModel(@Param('id', new ParseUUIDPipe()) id: string) {
    return this.modelService.delete(id);
  }

  // ============ RobotSku ============

  @Get('skus')
  @RequirePermissions('robot-manager:read')
  async listSkus(
    @Query('modelId') modelId?: string,
    @Query('search') search?: string,
    @Query('enabledOnly') enabledOnly?: string,
  ) {
    return this.skuService.list({ modelId, search, enabledOnly: enabledOnly === 'true' });
  }

  @Get('skus/:id')
  @RequirePermissions('robot-manager:read')
  async getSku(@Param('id', new ParseUUIDPipe()) id: string) {
    return this.skuService.findOne(id);
  }

  @Post('skus')
  @Auditable()
  @RequirePermissions('robot-manager:manage:models')
  async createSku(@Body() dto: CreateSkuDto, @CurrentUser() user: CurrentUserPayload) {
    return this.skuService.create(dto, user.userId, NIL_ORG_ID);
  }

  @Put('skus/:id')
  @Auditable()
  @RequirePermissions('robot-manager:manage:models')
  async updateSku(@Param('id', new ParseUUIDPipe()) id: string, @Body() dto: UpdateSkuDto) {
    return this.skuService.update(id, dto);
  }

  @Delete('skus/:id')
  @Auditable()
  @Sensitive()
  @RequirePermissions('robot-manager:manage:models')
  async deleteSku(@Param('id', new ParseUUIDPipe()) id: string) {
    return this.skuService.delete(id);
  }
}
