import { useState, useCallback } from 'react';
import { v4 as uuidv4 } from 'uuid';
import { GenerateLayerParams, InstrumentLayer } from '../utils/types';

const API_BASE_URL = 'https://studio-api.staging.suno.com/api/v2/external';

export function useLayerGeneration(onLayerUpdate?: (layer: InstrumentLayer) => void) {
  const [isGenerating, setIsGenerating] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const generateLayer = useCallback(async ({ prompt, bpm, key, duration = 30 }: GenerateLayerParams): Promise<InstrumentLayer> => {
    setIsGenerating(true);
    setError(null);
    
    try {
      const apiToken = process.env.NEXT_PUBLIC_SUNO_API_TOKEN;
      
      if (!apiToken) {
        throw new Error('NEXT_PUBLIC_SUNO_API_TOKEN not found in environment variables');
      }
      
      const fullPrompt = `${prompt}\nbpm: ${bpm}\nkey: ${key}\nduration_s: ${duration}`;
      console.log('Generating layer with prompt:', fullPrompt);
      
      const response = await fetch(`${API_BASE_URL}/generate/`, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${apiToken}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          topic: '',
          prompt: fullPrompt,
          tags: '',
          model: 'chirp-seeds'
        })
      });
      
      if (!response.ok) {
        throw new Error(`Failed to generate layer: ${response.statusText}`);
      }
      
      const data = await response.json();
      
      if (!data?.id) {
        throw new Error('Failed to generate layer - no clip ID returned');
      }
      
      console.log('Generated clip:', data);
      
      // Create initial layer object using clipId as the primary ID
      const layer: InstrumentLayer = {
        id: data.id, // Use clipId as the primary ID
        instrumentType: 'other', // Default since we're using free-form prompts
        title: prompt.slice(0, 50) + (prompt.length > 50 ? '...' : ''), // Use first 50 chars of prompt as title
        status: 'processing',
        volume: 1,
        muted: false,
        clipId: data.id,
        metadata: {
          prompt: fullPrompt,
          gpt_description_prompt: fullPrompt,
          tags: ''
        }
      };
      
      // Start polling for completion
      pollForCompletion(layer, onLayerUpdate);
      
      return layer;
      
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Failed to generate layer';
      setError(errorMessage);
      throw new Error(errorMessage);
    } finally {
      setIsGenerating(false);
    }
  }, [onLayerUpdate]);

  const pollForCompletion = useCallback(async (layer: InstrumentLayer, onUpdate?: (layer: InstrumentLayer) => void) => {
    const maxAttempts = 60; // 5 minutes max
    let attempts = 0;
    
    const poll = async (): Promise<InstrumentLayer> => {
      attempts++;
      
      try {
        const apiToken = process.env.NEXT_PUBLIC_SUNO_API_TOKEN;
        
        const response = await fetch(`${API_BASE_URL}/clips/?ids=${layer.clipId}`, {
          headers: {
            'Authorization': `Bearer ${apiToken}`
          }
        });
        
        if (!response.ok) {
          throw new Error(`Failed to get clip status: ${response.statusText}`);
        }
        
        const clips = await response.json();
        const clip = clips[0]; // API returns array, take first clip
        
        if (!clip) {
          if (attempts < maxAttempts) {
            // Clip not found yet, continue polling
            setTimeout(() => poll(), 5000);
            return layer;
          } else {
            throw new Error('Clip not found after polling timeout');
          }
        }
        
        console.log(`Clip ${clip.id}: status=${clip.status}, has_audio=${!!clip.audio_url}`);
        
        if (clip.audio_url) {
          // Complete! Update layer with audio URL
          const updatedLayer: InstrumentLayer = {
            ...layer,
            status: 'ready',
            audioUrl: clip.audio_url,
            metadata: {
              ...layer.metadata,
              duration: clip.metadata?.duration
            }
          };
          
          onUpdate?.(updatedLayer);
          return updatedLayer;
        }
        
        // Update status while polling
        const pollingLayer: InstrumentLayer = {
          ...layer,
          status: 'processing'
        };
        onUpdate?.(pollingLayer);
        
        // Still generating, continue polling
        if (attempts < maxAttempts) {
          const delay = clip.status === 'streaming' ? 10000 : 5000;
          setTimeout(() => poll(), delay);
        } else {
          throw new Error('Generation timeout');
        }
        
        return layer;
        
      } catch (err) {
        console.error('Polling error:', err);
        const errorLayer: InstrumentLayer = {
          ...layer,
          status: 'error'
        };
        return errorLayer;
      }
    };
    
    return poll();
  }, []);

  return {
    generateLayer,
    pollForCompletion,
    isGenerating,
    error
  };
}