/**
 * HTTP Protocol Detector
 * 
 * Simplified HTTP detection using the new architecture
 */

import type { IProtocolDetector } from '../models/interfaces.js';
import type { IDetectionResult, IDetectionOptions } from '../models/detection-types.js';
import type { IProtocolDetectionResult, IConnectionContext } from '../../protocols/common/types.js';
import type { THttpMethod } from '../../protocols/http/index.js';
import { QuickProtocolDetector } from './quick-detector.js';
import { RoutingExtractor } from './routing-extractor.js';
import { DetectionFragmentManager } from '../utils/fragment-manager.js';
import { HttpParser } from '../../protocols/http/parser.js';

/**
 * Simplified HTTP detector
 */
export class HttpDetector implements IProtocolDetector {
  private quickDetector = new QuickProtocolDetector();
  private fragmentManager: DetectionFragmentManager;
  
  constructor(fragmentManager?: DetectionFragmentManager) {
    this.fragmentManager = fragmentManager || new DetectionFragmentManager();
  }
  
  /**
   * Check if buffer can be handled by this detector
   */
  canHandle(buffer: Buffer): boolean {
    const result = this.quickDetector.quickDetect(buffer);
    return result.protocol === 'http' && result.confidence > 50;
  }
  
  /**
   * Get minimum bytes needed for detection
   */
  getMinimumBytes(): number {
    return 4; // "GET " minimum
  }
  
  /**
   * Detect HTTP protocol from buffer
   */
  detect(buffer: Buffer, options?: IDetectionOptions): IDetectionResult | null {
    // Quick detection first
    const quickResult = this.quickDetector.quickDetect(buffer);
    
    if (quickResult.protocol !== 'http' || quickResult.confidence < 50) {
      return null;
    }
    
    // Check if we have complete headers first
    const headersEnd = buffer.indexOf('\r\n\r\n');
    const isComplete = headersEnd !== -1;
    
    // Extract routing information
    const routing = RoutingExtractor.extract(buffer, 'http');
    
    // Extract headers if requested and we have complete headers
    let headers: Record<string, string> | undefined;
    if (options?.extractFullHeaders && isComplete) {
      const headerSection = buffer.slice(0, headersEnd).toString();
      const lines = headerSection.split('\r\n');
      if (lines.length > 1) {
        // Skip the request line and parse headers
        headers = HttpParser.parseHeaders(lines.slice(1));
      }
    }
    
    // If we don't need full headers and we have complete headers, we can return early
    if (quickResult.confidence >= 95 && !options?.extractFullHeaders && isComplete) {
      return {
        protocol: 'http',
        connectionInfo: { 
          protocol: 'http',
          method: quickResult.metadata?.method as THttpMethod,
          domain: routing?.domain,
          path: routing?.path
        },
        isComplete: true
      };
    }
    
    return {
      protocol: 'http',
      connectionInfo: {
        protocol: 'http',
        domain: routing?.domain,
        path: routing?.path,
        method: quickResult.metadata?.method as THttpMethod,
        headers: headers
      },
      isComplete,
      bytesNeeded: isComplete ? undefined : buffer.length + 512 // Need more for headers
    };
  }
  
  /**
   * Handle fragmented detection
   */
  detectWithContext(
    buffer: Buffer,
    context: IConnectionContext,
    options?: IDetectionOptions
  ): IDetectionResult | null {
    const handler = this.fragmentManager.getHandler('http');
    const connectionId = DetectionFragmentManager.createConnectionId(context);
    
    // Add fragment
    const result = handler.addFragment(connectionId, buffer);
    
    if (result.error) {
      handler.complete(connectionId);
      return null;
    }
    
    // Try detection on accumulated buffer
    const detectResult = this.detect(result.buffer!, options);
    
    if (detectResult && detectResult.isComplete) {
      handler.complete(connectionId);
    }
    
    return detectResult;
  }
}