import {
  Controller,
  Post,
  Body,
  HttpStatus,
  HttpException,
  Logger,
  BadRequestException,
  ServiceUnavailableException,
  InternalServerErrorException,
} from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
import { EnhancedScanService } from './monitoring.service';
import { ScanWebsiteDto } from './dto/scan-website.dto';
import { FindingsResponseDto } from './dto/findings.dto';

@ApiTags('dark-web-scan')
@Controller({ path: 'darkweb/scan', version: '1' })

// @Controller('darkweb/scan')
export class ScanController {
  private readonly logger = new Logger(ScanController.name);

  constructor(private readonly scanService: EnhancedScanService) {}

  @Post()
  @ApiOperation({
    summary: 'Enhanced dark web scan for a website',
    description: 'Submit a website URL to perform comprehensive dark web analysis with optional deep scraping and image extraction',
  })
  @ApiResponse({
    status: HttpStatus.OK,
    description: 'Scan completed successfully',
    type: FindingsResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    description: 'Invalid request parameters',
    schema: {
      type: 'object',
      properties: {
        statusCode: { type: 'number', example: 400 },
        message: { type: 'string', example: 'Invalid website URL format' },
        error: { type: 'string', example: 'Bad Request' },
      },
    },
  })
  @ApiResponse({
    status: HttpStatus.SERVICE_UNAVAILABLE,
    description: 'Tor service unavailable',
    schema: {
      type: 'object',
      properties: {
        statusCode: { type: 'number', example: 503 },
        message: { type: 'string', example: 'Dark web scanning service is currently unavailable' },
        error: { type: 'string', example: 'Service Unavailable' },
      },
    },
  })
  @ApiResponse({
    status: HttpStatus.INTERNAL_SERVER_ERROR,
    description: 'Internal server error',
    schema: {
      type: 'object',
      properties: {
        statusCode: { type: 'number', example: 500 },
        message: { type: 'string', example: 'An unexpected error occurred during scanning' },
        error: { type: 'string', example: 'Internal Server Error' },
      },
    },
  })
  async scanWebsite(@Body() dto: ScanWebsiteDto): Promise<FindingsResponseDto> {
    try {
      // Input validation
      if (!dto.websiteUrl) {
        this.logger.warn('Scan request received without website URL');
        throw new BadRequestException('Website URL is required');
      }

      // Basic URL validation
      try {
        new URL(dto.websiteUrl);
      } catch (urlError) {
        this.logger.warn(`Invalid URL format provided: ${dto.websiteUrl}`);
        throw new BadRequestException('Invalid website URL format');
      }

      // Validate amount parameter if provided
      if (dto.amount !== undefined && (dto.amount < 1 || dto.amount > 100)) {
        this.logger.warn(`Invalid amount parameter: ${dto.amount}`);
        throw new BadRequestException('Amount must be between 1 and 100');
      }

      this.logger.log(`Initiating scan request for: ${dto.websiteUrl}`, {
        amount: dto.amount,
        scrapeContent: dto.scrapeContent,
        scrapeImages: dto.scrapeImages,
        debugMode: dto.debugMode,
      });

      // Perform the scan
      const result = await this.scanService.scanWebsite(dto);

      // Check if scan returned any results or if there were issues
      if (result.totalFindings === 0 && result.executionTime < 1000) {
        // This might indicate a service issue rather than no findings
        this.logger.warn(`Scan completed suspiciously quickly with no results for ${dto.websiteUrl}`);
      }

      this.logger.log(`Scan completed successfully for ${dto.websiteUrl}. Found ${result.totalFindings} results in ${result.executionTime}ms`);

      return result;
    } catch (error) {
      // Handle known exceptions
      if (error instanceof BadRequestException) {
        throw error;
      }

      // Handle specific service errors
      if (error.message?.includes('tor') || error.message?.includes('Tor')) {
        this.logger.error(`Tor service error during scan: ${error.message}`);
        throw new ServiceUnavailableException('Dark web scanning service is currently unavailable. Please try again later.');
      }

      if (error.message?.includes('timeout') || error.message?.includes('TIMEOUT')) {
        this.logger.error(`Scan timeout for ${dto.websiteUrl}: ${error.message}`);
        throw new ServiceUnavailableException('Scan request timed out. The website may be unreachable or the service is overloaded.');
      }

      if (error.message?.includes('network') || error.message?.includes('connection')) {
        this.logger.error(`Network error during scan: ${error.message}`);
        throw new ServiceUnavailableException('Network connection error. Please check your connection and try again.');
      }

      // Log unexpected errors
      this.logger.error(`Unexpected error during website scan for ${dto.websiteUrl}:`, {
        error: error.message,
        stack: error.stack,
        dto,
      });

      // Return a generic error response
      throw new InternalServerErrorException('An unexpected error occurred during scanning. Please try again later.');
    }
  }

  @Post('health')
  @ApiOperation({
    summary: 'Check scanner service health',
    description: 'Verify that the dark web scanning service and Tor connection are operational',
  })
  @ApiResponse({
    status: HttpStatus.OK,
    description: 'Health check completed',
    schema: {
      type: 'object',
      properties: {
        status: { type: 'string', example: 'healthy' },
        torConnection: { type: 'boolean', example: true },
        timestamp: { type: 'string', format: 'date-time' },
      },
    },
  })
  @ApiResponse({
    status: HttpStatus.SERVICE_UNAVAILABLE,
    description: 'Service is unhealthy',
    schema: {
      type: 'object',
      properties: {
        statusCode: { type: 'number', example: 503 },
        message: { type: 'string', example: 'Service is currently unhealthy' },
        error: { type: 'string', example: 'Service Unavailable' },
      },
    },
  })
  async healthCheck() {
    try {
      this.logger.log('Performing health check');

      const healthStatus = await this.scanService.healthCheck();

      // If the service reports as unhealthy, return appropriate HTTP status
      if (healthStatus.status === 'unhealthy') {
        this.logger.warn('Health check indicates service is unhealthy', healthStatus);
        throw new ServiceUnavailableException({
          message: 'Service is currently unhealthy',
          details: healthStatus,
        });
      }

      if (healthStatus.status === 'degraded') {
        this.logger.warn('Health check indicates service is degraded', healthStatus);
        // Still return 200 but with degraded status
      }

      this.logger.log(`Health check completed. Status: ${healthStatus.status}`);
      return healthStatus;
    } catch (error) {
      // Handle known service unavailable exceptions
      if (error instanceof ServiceUnavailableException) {
        throw error;
      }

      // Handle unexpected health check errors
      this.logger.error('Health check failed with unexpected error:', {
        error: error.message,
        stack: error.stack,
      });

      throw new ServiceUnavailableException({
        message: 'Health check failed due to unexpected error',
        error: error.message,
      });
    }
  }
}
