import {
  Controller,
  Get,
  Put,
  Body,
  Param,
  Query,
  HttpCode,
  HttpStatus,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBearerAuth,
  ApiParam,
  ApiQuery,
} from '@nestjs/swagger';
import { SystemSettingsService } from './system-settings.service';
import { UpdateSettingDto, BulkUpdateSettingsDto } from './dto';
import { RequirePermissions } from '../../auth/permissions/permissions.decorator';
import { Permission } from '../../auth/permissions/permissions.enum';

@ApiTags('System Settings')
@ApiBearerAuth('JWT-auth')
@Controller('system-settings')
export class SystemSettingsController {
  constructor(private readonly systemSettingsService: SystemSettingsService) {}

  @Get()
  @RequirePermissions(Permission.SYSTEM_SETTINGS_VIEW)
  @ApiOperation({ summary: 'Get all system settings, optionally filtered by category' })
  @ApiQuery({ name: 'category', required: false, description: 'Filter settings by category' })
  @ApiResponse({
    status: 200,
    description: 'Settings grouped by category. Secret values are masked.',
    schema: {
      type: 'object',
      properties: {
        settings: { type: 'array', items: { type: 'object' } },
        categories: { type: 'array', items: { type: 'string' } },
      },
    },
  })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden - insufficient permissions' })
  findAll(@Query('category') category?: string) {
    return this.systemSettingsService.findAll(category);
  }

  // IMPORTANT: This route must be declared BEFORE :key to prevent NestJS from
  // matching the literal string "bulk" as a :key parameter value.
  @Put('bulk')
  @RequirePermissions(Permission.SYSTEM_SETTINGS_MANAGE)
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Bulk upsert multiple settings in one transaction' })
  @ApiResponse({
    status: 200,
    description: 'All settings upserted successfully',
    schema: {
      type: 'array',
      items: { type: 'object' },
    },
  })
  @ApiResponse({ status: 400, description: 'Bad request - invalid data' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden - insufficient permissions' })
  bulkUpdate(@Body() dto: BulkUpdateSettingsDto) {
    return this.systemSettingsService.bulkUpsert(dto.settings.map((s) => ({
      key: s.key,
      value: s.value,
      category: s.category ?? 'general',
      description: s.description,
      valueType: s.valueType,
      isSecret: s.isSecret,
    })));
  }

  @Get(':key')
  @RequirePermissions(Permission.SYSTEM_SETTINGS_VIEW)
  @ApiOperation({ summary: 'Get a single setting by key' })
  @ApiParam({ name: 'key', description: 'Setting key (e.g. sync.interval.plentyone)' })
  @ApiResponse({
    status: 200,
    description: 'The setting. Secret value is masked.',
    schema: { type: 'object' },
  })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden - insufficient permissions' })
  @ApiResponse({ status: 404, description: 'Setting not found' })
  findOne(@Param('key') key: string) {
    return this.systemSettingsService.findByKey(key);
  }

  @Put(':key')
  @RequirePermissions(Permission.SYSTEM_SETTINGS_MANAGE)
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Create or update a setting by key' })
  @ApiParam({ name: 'key', description: 'Setting key (e.g. branding.appName)' })
  @ApiResponse({
    status: 200,
    description: 'Setting upserted successfully. Secret value is masked in the response.',
    schema: { type: 'object' },
  })
  @ApiResponse({ status: 400, description: 'Bad request - invalid data' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden - insufficient permissions' })
  update(@Param('key') key: string, @Body() dto: UpdateSettingDto) {
    return this.systemSettingsService.upsert(key, {
      value: dto.value,
      category: 'general', // category is derived from the key prefix or defaults to 'general'
      description: dto.description,
      valueType: dto.valueType,
      isSecret: dto.isSecret,
    });
  }
}
