import sharp from 'sharp';

export interface SimpleFaceDetectionResult {
  success: boolean;
  faces_detected: number;
  primary_face_confidence: number;
  crop_info: {
    x: number;
    y: number;
    width: number;
    height: number;
  };
  original_dimensions: {
    width: number;
    height: number;
  };
  processing_strategy: 'face_centered' | 'center_crop' | 'smart_crop';
  error?: string;
}

export class SimpleFaceDetectionService {
  /**
   * Download image and get basic info
   */
  private async downloadImage(imageUrl: string): Promise<{ buffer: Buffer; width: number; height: number }> {
    try {
      const response = await fetch(imageUrl);
      if (!response.ok) {
        throw new Error(`Failed to download image: ${response.statusText}`);
      }
      
      const buffer = Buffer.from(await response.arrayBuffer());
      const metadata = await sharp(buffer).metadata();
      
      return {
        buffer,
        width: metadata.width || 0,
        height: metadata.height || 0
      };
    } catch (error) {
      throw new Error(`Image download failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }

  /**
   * Analyze image to find interesting areas (likely faces or main subjects)
   * Uses edge detection and high contrast areas to identify focal points
   */
  private async analyzeImageFocalPoints(imageBuffer: Buffer, width: number, height: number): Promise<{ x: number; y: number; confidence: number }[]> {
    try {
      // Resize image for faster processing
      const resizedBuffer = await sharp(imageBuffer)
        .resize(Math.min(400, width), Math.min(400, height), { fit: 'inside' })
        .greyscale()
        .raw()
        .toBuffer({ resolveWithObject: true });

      const { data, info } = resizedBuffer;
      const { width: resizedWidth, height: resizedHeight } = info;
      
      // Simple edge detection to find areas of interest
      const focalPoints: { x: number; y: number; confidence: number }[] = [];
      const blockSize = 20; // Analyze in 20x20 pixel blocks
      
      for (let y = 0; y < resizedHeight - blockSize; y += blockSize) {
        for (let x = 0; x < resizedWidth - blockSize; x += blockSize) {
          let edgeStrength = 0;
          let averageBrightness = 0;
          let pixelCount = 0;
          
          // Analyze block for edge strength and brightness
          for (let dy = 0; dy < blockSize; dy++) {
            for (let dx = 0; dx < blockSize; dx++) {
              const currentY = y + dy;
              const currentX = x + dx;
              
              if (currentY < resizedHeight && currentX < resizedWidth) {
                const idx = currentY * resizedWidth + currentX;
                const currentPixel = data[idx];
                averageBrightness += currentPixel;
                pixelCount++;
                
                // Simple edge detection (horizontal and vertical gradients)
                if (currentX < resizedWidth - 1 && currentY < resizedHeight - 1) {
                  const rightPixel = data[currentY * resizedWidth + (currentX + 1)];
                  const downPixel = data[(currentY + 1) * resizedWidth + currentX];
                  
                  const horizontalGradient = Math.abs(currentPixel - rightPixel);
                  const verticalGradient = Math.abs(currentPixel - downPixel);
                  edgeStrength += horizontalGradient + verticalGradient;
                }
              }
            }
          }
          
          averageBrightness /= pixelCount;
          
          // Calculate confidence based on edge strength and optimal brightness
          // Faces typically have moderate brightness (not too dark, not too bright)
          const brightnessScore = 1 - Math.abs(averageBrightness - 128) / 128;
          const edgeScore = Math.min(edgeStrength / (blockSize * blockSize * 100), 1);
          const confidence = (brightnessScore * 0.3 + edgeScore * 0.7);
          
          if (confidence > 0.3) { // Only consider blocks with reasonable confidence
            // Convert back to original image coordinates
            const originalX = (x / resizedWidth) * width;
            const originalY = (y / resizedHeight) * height;
            
            focalPoints.push({
              x: originalX,
              y: originalY,
              confidence
            });
          }
        }
      }
      
      // Sort by confidence and return top candidates
      return focalPoints
        .sort((a, b) => b.confidence - a.confidence)
        .slice(0, 3); // Keep top 3 focal points
      
    } catch (error) {
      console.error('Error analyzing image focal points:', error);
      return [];
    }
  }

  /**
   * Calculate smart crop based on focal points
   */
  private calculateSmartCrop(
    imageWidth: number,
    imageHeight: number,
    focalPoints: { x: number; y: number; confidence: number }[],
    targetAspect: number = 9/16
  ): { x: number; y: number; width: number; height: number } {
    
    if (focalPoints.length === 0) {
      // No focal points found, use center crop
      return this.calculateCenterCrop(imageWidth, imageHeight, targetAspect);
    }
    
    // Use the highest confidence focal point
    const primaryFocalPoint = focalPoints[0];
    
    let cropWidth: number, cropHeight: number, cropX: number, cropY: number;

    if (imageWidth / imageHeight > targetAspect) {
      // Image is wider than target aspect ratio
      cropWidth = Math.floor(imageHeight * targetAspect);
      cropHeight = imageHeight;
      
      // Center crop horizontally around focal point
      cropX = Math.max(0, Math.min(
        primaryFocalPoint.x - cropWidth / 2,
        imageWidth - cropWidth
      ));
      cropY = 0;
    } else {
      // Image is taller than target aspect ratio
      cropWidth = imageWidth;
      cropHeight = Math.floor(imageWidth / targetAspect);
      
      // Center crop vertically around focal point
      cropY = Math.max(0, Math.min(
        primaryFocalPoint.y - cropHeight / 2,
        imageHeight - cropHeight
      ));
      cropX = 0;
    }

    return { x: cropX, y: cropY, width: cropWidth, height: cropHeight };
  }

  /**
   * Calculate standard center crop
   */
  private calculateCenterCrop(
    imageWidth: number,
    imageHeight: number,
    targetAspect: number = 9/16
  ): { x: number; y: number; width: number; height: number } {
    let cropWidth: number, cropHeight: number, cropX: number, cropY: number;

    if (imageWidth / imageHeight > targetAspect) {
      cropWidth = Math.floor(imageHeight * targetAspect);
      cropHeight = imageHeight;
      cropX = Math.floor((imageWidth - cropWidth) / 2);
      cropY = 0;
    } else {
      cropWidth = imageWidth;
      cropHeight = Math.floor(imageWidth / targetAspect);
      cropX = 0;
      cropY = Math.floor((imageHeight - cropHeight) / 2);
    }

    return { x: cropX, y: cropY, width: cropWidth, height: cropHeight };
  }

  /**
   * Process thumbnail image to find optimal crop position
   */
  public async processThumbnail(thumbnailUrl: string): Promise<SimpleFaceDetectionResult> {
    try {
      console.log(`🔍 Analyzing thumbnail: ${thumbnailUrl}`);
      
      // Download and analyze the image
      const { buffer, width, height } = await this.downloadImage(thumbnailUrl);
      
      if (width === 0 || height === 0) {
        throw new Error('Invalid image dimensions');
      }

      // Analyze image for focal points (potential faces/subjects)
      const focalPoints = await this.analyzeImageFocalPoints(buffer, width, height);
      
      console.log(`🎯 Found ${focalPoints.length} focal points`);

      let cropInfo: { x: number; y: number; width: number; height: number };
      let strategy: 'face_centered' | 'center_crop' | 'smart_crop';
      let confidence = 0;
      let facesDetected = 0;

      if (focalPoints.length > 0) {
        const primaryFocalPoint = focalPoints[0];
        confidence = primaryFocalPoint.confidence;
        
        // Consider it a "face" if confidence is high enough
        if (confidence > 0.6) {
          facesDetected = 1;
          strategy = 'face_centered';
        } else {
          strategy = 'smart_crop';
        }
        
        cropInfo = this.calculateSmartCrop(width, height, focalPoints);
        
        console.log(`✅ Smart crop calculated with confidence: ${confidence.toFixed(2)}`);
      } else {
        // No focal points found, use center crop
        cropInfo = this.calculateCenterCrop(width, height);
        strategy = 'center_crop';
        
        console.log(`📐 Center crop calculated (no focal points detected)`);
      }

      return {
        success: true,
        faces_detected: facesDetected,
        primary_face_confidence: confidence,
        crop_info: cropInfo,
        original_dimensions: { width, height },
        processing_strategy: strategy
      };

    } catch (error) {
      console.error(`❌ Error processing thumbnail ${thumbnailUrl}:`, error);
      return {
        success: false,
        faces_detected: 0,
        primary_face_confidence: 0,
        crop_info: { x: 0, y: 0, width: 0, height: 0 },
        original_dimensions: { width: 0, height: 0 },
        processing_strategy: 'center_crop',
        error: error instanceof Error ? error.message : String(error)
      };
    }
  }

  /**
   * Calculate CSS object-position for optimal display
   */
  public calculateObjectPosition(
    cropInfo: { x: number; y: number; width: number; height: number },
    originalDimensions: { width: number; height: number }
  ): string {
    if (!cropInfo || !originalDimensions.width || !originalDimensions.height) {
      return 'center center';
    }

    // Calculate the percentage position of the crop center
    const cropCenterX = cropInfo.x + cropInfo.width / 2;
    const cropCenterY = cropInfo.y + cropInfo.height / 2;
    
    const positionX = (cropCenterX / originalDimensions.width) * 100;
    const positionY = (cropCenterY / originalDimensions.height) * 100;
    
    return `${Math.max(0, Math.min(100, positionX)).toFixed(1)}% ${Math.max(0, Math.min(100, positionY)).toFixed(1)}%`;
  }

  /**
   * Get optimized thumbnail information
   */
  public async getOptimizedThumbnailInfo(thumbnailUrl: string) {
    try {
      const result = await this.processThumbnail(thumbnailUrl);
      
      return {
        originalUrl: thumbnailUrl,
        faceCenterPosition: this.calculateObjectPosition(result.crop_info, result.original_dimensions),
        facesDetected: result.faces_detected,
        confidence: result.primary_face_confidence,
        strategy: result.processing_strategy,
        processedSuccessfully: result.success
      };
    } catch (error) {
      console.error('Error optimizing thumbnail:', error);
      return {
        originalUrl: thumbnailUrl,
        faceCenterPosition: 'center center',
        facesDetected: 0,
        confidence: 0,
        strategy: 'center_crop' as const,
        processedSuccessfully: false
      };
    }
  }
}

// Export singleton instance
export const simpleFaceDetectionService = new SimpleFaceDetectionService();