/**
 * Utility for tracking image processing progress
 *
 * Usage example:
 *
 * // After saving a story, start polling for progress
 * const progressTracker = new ImageProcessingProgressTracker(storyId);
 *
 * progressTracker.onProgress((progress) => {
 *   console.log(`Processing ${progress.processedImages}/${progress.totalImages} images`);
 *   console.log(`Current: ${progress.currentImageUrl}`);
 *   console.log(`Status: ${progress.status}`);
 * });
 *
 * progressTracker.onComplete((finalProgress) => {
 *   console.log('Image processing completed!');
 * });
 *
 * progressTracker.onError((error) => {
 *   console.error('Image processing failed:', error);
 * });
 *
 * progressTracker.start();
 */

export interface ImageProcessingProgress {
  isProcessing: boolean;
  totalImages: number;
  processedImages: number;
  currentImageUrl: string;
  status: string;
  progressPercentage: number;
  completed: boolean;
  error: string;
  message?: string;
}

export type ProgressCallback = (progress: ImageProcessingProgress) => void;
export type CompleteCallback = (finalProgress: ImageProcessingProgress) => void;
export type ErrorCallback = (error: string) => void;

export class ImageProcessingProgressTracker {
  private storyId: string;
  private pollInterval: number;
  private timeoutMs: number;
  private isPolling: boolean = false;
  private pollTimer: NodeJS.Timeout | null = null;
  private startTime: number = 0;

  private progressCallbacks: ProgressCallback[] = [];
  private completeCallbacks: CompleteCallback[] = [];
  private errorCallbacks: ErrorCallback[] = [];

  constructor(
    storyId: string,
    pollInterval: number = 1000, // Poll every 1 second
    timeoutMs: number = 300000    // 5 minute timeout
  ) {
    this.storyId = storyId;
    this.pollInterval = pollInterval;
    this.timeoutMs = timeoutMs;
  }

  public onProgress(callback: ProgressCallback): void {
    this.progressCallbacks.push(callback);
  }

  public onComplete(callback: CompleteCallback): void {
    this.completeCallbacks.push(callback);
  }

  public onError(callback: ErrorCallback): void {
    this.errorCallbacks.push(callback);
  }

  public async start(): Promise<void> {
    if (this.isPolling) {
      console.warn('Progress tracking already started');
      return;
    }

    this.isPolling = true;
    this.startTime = Date.now();

    console.log(`Starting image processing progress tracking for story ${this.storyId}`);
    this.poll();
  }

  public stop(): void {
    this.isPolling = false;
    if (this.pollTimer) {
      clearTimeout(this.pollTimer);
      this.pollTimer = null;
    }
    console.log(`Stopped progress tracking for story ${this.storyId}`);
  }

  private async poll(): Promise<void> {
    if (!this.isPolling) {
      return;
    }

    // Check for timeout
    const elapsed = Date.now() - this.startTime;
    if (elapsed > this.timeoutMs) {
      this.handleError('Image processing timed out');
      return;
    }

    try {
      const response = await fetch(`/api/stories/${this.storyId}/image-processing-progress`);

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }

      const progress: ImageProcessingProgress = await response.json();

      // Call progress callbacks
      this.progressCallbacks.forEach(callback => {
        try {
          callback(progress);
        } catch (error) {
          console.error('Error in progress callback:', error);
        }
      });

      // Check if processing is complete
      if (progress.completed) {
        this.handleComplete(progress);
        return;
      }

      // Check for errors
      if (progress.error) {
        this.handleError(progress.error);
        return;
      }

      // Continue polling if still processing
      if (progress.isProcessing) {
        this.pollTimer = setTimeout(() => this.poll(), this.pollInterval);
      } else {
        // No active processing - might have finished or never started
        this.handleComplete(progress);
      }

    } catch (error) {
      this.handleError(`Failed to fetch progress: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }

  private handleComplete(finalProgress: ImageProcessingProgress): void {
    this.stop();
    console.log(`Image processing completed for story ${this.storyId}`);

    this.completeCallbacks.forEach(callback => {
      try {
        callback(finalProgress);
      } catch (error) {
        console.error('Error in complete callback:', error);
      }
    });
  }

  private handleError(error: string): void {
    this.stop();
    console.error(`Image processing error for story ${this.storyId}:`, error);

    this.errorCallbacks.forEach(callback => {
      try {
        callback(error);
      } catch (error) {
        console.error('Error in error callback:', error);
      }
    });
  }
}

/**
 * React hook for image processing progress
 *
 * Note: This hook requires React to be imported in the file where it's used.
 * To use this hook, import React in your component file:
 *
 * import React from 'react';
 * import { useImageProcessingProgress } from '../utils/imageProcessingProgress';
 *
 * Usage:
 * const { progress, isTracking, startTracking } = useImageProcessingProgress(storyId);
 */
import React from 'react';

export function useImageProcessingProgress(storyId: string) {
  const [progress, setProgress] = React.useState<ImageProcessingProgress | null>(null);
  const [isTracking, setIsTracking] = React.useState(false);
  const [tracker, setTracker] = React.useState<ImageProcessingProgressTracker | null>(null);

  const startTracking = React.useCallback(() => {
    if (tracker) {
      tracker.stop();
    }

    const newTracker = new ImageProcessingProgressTracker(storyId);

    newTracker.onProgress((progress) => {
      setProgress(progress);
    });

    newTracker.onComplete((finalProgress) => {
      setProgress(finalProgress);
      setIsTracking(false);
    });

    newTracker.onError((error) => {
      console.error('Image processing error:', error);
      setIsTracking(false);
    });

    setTracker(newTracker);
    setIsTracking(true);
    newTracker.start();
  }, [storyId, tracker]);

  const stopTracking = React.useCallback(() => {
    if (tracker) {
      tracker.stop();
      setIsTracking(false);
    }
  }, [tracker]);

  React.useEffect(() => {
    return () => {
      if (tracker) {
        tracker.stop();
      }
    };
  }, [tracker]);

  return {
    progress,
    isTracking,
    startTracking,
    stopTracking
  };
}