import { Body, Controller, Get, Post, Put, Delete, Param, UseGuards, Request, Query } from '@nestjs/common';
import { ApiTags, ApiBearerAuth, ApiOperation, ApiResponse, ApiParam, ApiQuery } from '@nestjs/swagger';
import { ConfigurableFareService } from './configurable-fare.service';
import { 
  CreateFareConfigurationDto, 
  UpdateFareConfigurationDto,
  FareTestScenarioDto,
  FareCalculationResultDto,
  MigrateLegacyDto,
  CreateNewFormulaDto,
  ToggleFeatureDto
} from './configurable-fare.dto';
import { IamGuard } from '../../common/iam-adapter';
import { Roles } from '../../common/roles.decorator';

@ApiTags('Configurable Fares')
@Controller('admin/fare-configurations')
@ApiBearerAuth('IAM-auth')
@UseGuards(IamGuard)
@Roles('ADMIN')
export class ConfigurableFareController {
  constructor(private service: ConfigurableFareService) {}

  @Get()
  @ApiOperation({ summary: 'List all fare configurations' })
  @ApiResponse({ status: 200, description: 'List of all configurations with summary counts' })
  async getAllConfigurations() {
    return this.service.getAllConfigurations();
  }

  @Post()
  @ApiOperation({ summary: 'Create new fare configuration' })
  @ApiResponse({ status: 201, description: 'Configuration created successfully' })
  @ApiResponse({ status: 400, description: 'Invalid configuration data' })
  async createConfiguration(
    @Body() dto: CreateFareConfigurationDto,
    @Request() req: any
  ) {
    const createdBy = req.user?.id || req.user?.sub;
    return this.service.createConfiguration(dto, createdBy);
  }

  @Get(':id')
  @ApiOperation({ summary: 'Get configuration details' })
  @ApiParam({ name: 'id', description: 'Configuration ID' })
  @ApiResponse({ status: 200, description: 'Configuration details with all rules' })
  @ApiResponse({ status: 404, description: 'Configuration not found' })
  async getConfigurationById(@Param('id') id: string) {
    return this.service.getConfigurationById(id);
  }

  @Put(':id')
  @ApiOperation({ summary: 'Update configuration' })
  @ApiParam({ name: 'id', description: 'Configuration ID' })
  @ApiResponse({ status: 200, description: 'Configuration updated successfully' })
  @ApiResponse({ status: 404, description: 'Configuration not found' })
  async updateConfiguration(
    @Param('id') id: string,
    @Body() dto: UpdateFareConfigurationDto,
    @Request() req: any
  ) {
    const updatedBy = req.user?.id || req.user?.sub;
    return this.service.updateConfiguration(id, dto, updatedBy);
  }

  @Post(':id/activate')
  @ApiOperation({ summary: 'Activate configuration' })
  @ApiParam({ name: 'id', description: 'Configuration ID' })
  @ApiResponse({ status: 200, description: 'Configuration activated successfully' })
  @ApiResponse({ status: 404, description: 'Configuration not found' })
  async activateConfiguration(@Param('id') id: string, @Request() req: any) {
    const activatedBy = req.user?.id || req.user?.sub;
    return this.service.activateConfiguration(id, activatedBy);
  }

  @Delete(':id')
  @ApiOperation({ summary: 'Delete configuration' })
  @ApiParam({ name: 'id', description: 'Configuration ID' })
  @ApiResponse({ status: 200, description: 'Configuration deleted successfully' })
  @ApiResponse({ status: 404, description: 'Configuration not found' })
  @ApiResponse({ status: 409, description: 'Cannot delete active configuration' })
  async deleteConfiguration(@Param('id') id: string, @Request() req: any) {
    const deletedBy = req.user?.id || req.user?.sub;
    return this.service.deleteConfiguration(id, deletedBy);
  }

  @Post(':id/test')
  @ApiOperation({ summary: 'Test fare calculation with configuration' })
  @ApiParam({ name: 'id', description: 'Configuration ID' })
  @ApiResponse({ status: 200, type: FareCalculationResultDto, description: 'Fare calculation result' })
  @ApiResponse({ status: 400, description: 'Invalid test scenario or missing rate rules' })
  async testConfiguration(
    @Param('id') id: string,
    @Body() scenario: FareTestScenarioDto
  ): Promise<FareCalculationResultDto> {
    return this.service.testConfiguration(id, scenario);
  }

  @Get(':id/audit')
  @ApiOperation({ summary: 'Get configuration audit trail' })
  @ApiParam({ name: 'id', description: 'Configuration ID' })
  @ApiResponse({ status: 200, description: 'Audit trail entries' })
  async getAuditTrail(@Param('id') id: string) {
    return this.service.getAuditTrail(id);
  }
}

@ApiTags('Configurable Fares')
@Controller('admin/fare-migration')
@ApiBearerAuth('IAM-auth')
@UseGuards(IamGuard)
@Roles('ADMIN')
export class FareMigrationController {
  constructor(private service: ConfigurableFareService) {}

  @Post('migrate-legacy')
  @ApiOperation({ summary: 'Migrate existing fare rules to configurable system' })
  @ApiResponse({ status: 200, description: 'Migration completed successfully' })
  @ApiResponse({ status: 400, description: 'Migration failed' })
  async migrateLegacySystem(@Body() dto: MigrateLegacyDto) {
    return this.service.migrateLegacySystem(dto);
  }

  @Post('create-new-formula')
  @ApiOperation({ summary: 'Create new formula configuration with defaults' })
  @ApiResponse({ status: 201, description: 'New formula configuration created' })
  async createNewFormulaConfiguration(@Body() dto: CreateNewFormulaDto) {
    return this.service.createNewFormulaConfiguration(dto);
  }

  @Post('complete-setup')
  @ApiOperation({ 
    summary: 'Complete system setup (migrate + create + activate)',
    description: 'Performs full system migration and setup in one operation'
  })
  @ApiResponse({ status: 200, description: 'System setup completed successfully' })
  async completeSetup(@Body() body: { activateNewFormula?: boolean; enableFeature?: boolean }) {
    // Step 1: Migrate legacy system
    const migrationResult = await this.service.migrateLegacySystem({ dryRun: false });

    // Step 2: Create new formula configuration
    const newConfig = await this.service.createNewFormulaConfiguration({
      name: 'Default System Configuration',
      description: 'System-generated configuration with optimal defaults',
      activateImmediately: body.activateNewFormula !== false
    });

    // Step 3: Enable feature flag if requested
    if (body.enableFeature) {
      await this.service.toggleFeature({
        featureName: 'USE_CONFIGURABLE_FARES',
        enabled: true,
        config: { rollout_percentage: 100 }
      });
    }

    return {
      migration: migrationResult,
      newConfiguration: newConfig,
      featureEnabled: body.enableFeature || false,
      message: 'System setup completed successfully'
    };
  }

  @Get('status')
  @ApiOperation({ summary: 'Get migration and setup status' })
  @ApiResponse({ status: 200, description: 'Current system status' })
  async getStatus() {
    const featureStatus = await this.service.getFeatureStatus('USE_CONFIGURABLE_FARES');
    const configurations = await this.service.getAllConfigurations();
    
    const activeConfig = (configurations as any[]).find(config => config.is_active);
    
    return {
      configurableFaresEnabled: featureStatus.enabled,
      rolloutPercentage: featureStatus.config?.rollout_percentage || 0,
      totalConfigurations: (configurations as any[]).length,
      activeConfiguration: activeConfig?.id || null,
      activeConfigurationName: activeConfig?.name || null,
      systemReady: featureStatus.enabled && !!activeConfig
    };
  }
}

@ApiTags('Configurable Fares')
@Controller('admin/fare-configurations/system')
@ApiBearerAuth('IAM-auth')
@UseGuards(IamGuard)
@Roles('ADMIN')
export class FareSystemController {
  constructor(private service: ConfigurableFareService) {}

  @Get('feature-status')
  @ApiOperation({ summary: 'Check configurable fares feature status' })
  @ApiQuery({ name: 'feature', required: false, description: 'Feature name (defaults to USE_CONFIGURABLE_FARES)' })
  @ApiResponse({ status: 200, description: 'Feature status retrieved' })
  async getFeatureStatus(@Query('feature') featureName = 'USE_CONFIGURABLE_FARES') {
    return this.service.getFeatureStatus(featureName);
  }

  @Post('toggle-feature')
  @ApiOperation({ summary: 'Enable or disable configurable fares system' })
  @ApiResponse({ status: 200, description: 'Feature toggled successfully' })
  async toggleFeature(@Body() dto: ToggleFeatureDto) {
    return this.service.toggleFeature(dto);
  }

  @Post('enable-configurable-fares')
  @ApiOperation({ 
    summary: 'Enable configurable fares with rollout percentage',
    description: 'Quick endpoint to enable the configurable fares feature'
  })
  @ApiResponse({ status: 200, description: 'Configurable fares enabled successfully' })
  async enableConfigurableFares(@Body() body: { rolloutPercentage?: number }) {
    return this.service.toggleFeature({
      featureName: 'USE_CONFIGURABLE_FARES',
      enabled: true,
      config: { rollout_percentage: body.rolloutPercentage || 100 }
    });
  }

  @Post('disable-configurable-fares')
  @ApiOperation({ 
    summary: 'Disable configurable fares (fallback to legacy system)',
    description: 'Disables the configurable fares feature and falls back to legacy fare calculation'
  })
  @ApiResponse({ status: 200, description: 'Configurable fares disabled successfully' })
  async disableConfigurableFares() {
    return this.service.toggleFeature({
      featureName: 'USE_CONFIGURABLE_FARES',
      enabled: false,
      config: { rollout_percentage: 0 }
    });
  }
}