import { ollamaClient } from './ollama-client'
import { jasonProcessor } from './jason-processor'

export interface SeriesConfig {
  id: string
  title: string
  description: string
  imageCount: number
  style: string
  prompts: string[]
}

export interface GeneratedSeries {
  id: string
  config: SeriesConfig
  images: GeneratedImage[]
  createdAt: string
  updatedAt: string
}

export interface GeneratedImage {
  id: string
  title: string
  prompt: string
  jasonPrompt?: string
  thumbnail?: string
  seriesId: string
  characterConsistency?: any
  itemConsistency?: any
}

export interface CharacterProfile {
  name: string
  description: string
  features: {
    appearance: string
    personality: string
    backstory: string
  }
  importance: 'main' | 'supporting' | 'background'
}

export interface ItemProfile {
  name: string
  description: string
  features: {
    appearance: string
    purpose: string
    origin: string
  }
  importance: 'critical' | 'important' | 'background'
}

export class SeriesGenerator {
  private storage: Storage

  constructor() {
    this.storage = typeof window !== 'undefined' ? localStorage : new Map()
  }

  // Generate series using AI (Ollama Cloud)
  async createSeries(
    basePrompt: string,
    config: SeriesConfig,
    characters?: CharacterProfile[],
    items?: ItemProfile[]
  ): Promise<GeneratedSeries> {
    try {
      console.log('Generating series with Ollama Cloud...')
      
      // Use Ollama for AI-powered story generation
      const storyData = await ollamaClient.generateStorySeries(basePrompt, {
        imageCount: config.imageCount,
        style: config.style,
        mood: 'wonderful', // Default mood
        includeCharacters: characters && characters.length > 0,
        includeItems: items && items.length > 0,
      })

      // Generate Jason prompts for each scene
      const jasonPrompts = storyData.prompts.map((prompt, index) => 
        jasonProcessor.generateConsistencyEnhancedPrompt(
          prompt,
          {
            characters: characters?.map(c => c.name) || [],
            items: items?.map(i => i.name) || [],
            colorPalette: ['blue', 'purple', 'gold'], // Story-appropriate colors
            style: config.style,
            mood: storyData.mood,
          },
          index + 1,
          storyData.prompts.length
        )
      )

      // Create generated images with Jason prompts
      const images: GeneratedImage[] = jasonPrompts.map((jasonPrompt, index) => ({
        id: `${config.id}_${index}`,
        title: `${storyData.title} - Scene ${index + 1}`,
        prompt: storyData.prompts[index],
        jasonPrompt: JSON.stringify(jasonPrompt, null, 2),
        seriesId: config.id,
      }))

      const series: GeneratedSeries = {
        id: config.id,
        config: {
          ...config,
          prompts: storyData.prompts,
        },
        images,
        createdAt: new Date().toISOString(),
        updatedAt: new Date().toISOString(),
      }

      // Store series
      this.saveSeries(series)
      
      console.log(`Generated series: ${series.config.title} with ${images.length} scenes`)
      return series

    } catch (error) {
      console.error('Failed to create series:', error)
      
      // Fallback to offline generation
      return this.createOfflineSeries(basePrompt, config, characters, items)
    }
  }

  // Fallback offline series generation
  private createOfflineSeries(
    basePrompt: string,
    config: SeriesConfig,
    characters?: CharacterProfile[],
    items?: ItemProfile[]
  ): GeneratedSeries {
    console.log('Using offline series generation (fallback mode)')

    // Basic progression without AI
    const progression = this.generateBasicProgression(config.imageCount)
    const images: GeneratedImage[] = progression.map((stage, index) => ({
      id: `${config.id}_${index}`,
      title: `${config.title} - ${stage}`,
      prompt: `${basePrompt} - ${stage}`,
      jasonPrompt: JSON.stringify({
        prompt: `${basePrompt} - ${stage}`,
        style: config.style,
        characters: characters?.map(c => c.name) || [],
        mood: 'neutral',
      }, null, 2),
      seriesId: config.id,
    }))

    const series: GeneratedSeries = {
      id: config.id,
      config,
      images,
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString(),
    }

    this.saveSeries(series)
    return series
  }

  private generateBasicProgression(imageCount: number): string[] {
    if (imageCount <= 3) {
      return ['Introduction', 'Development', 'Conclusion']
    } else if (imageCount <= 5) {
      return ['Introduction', 'Rising Action', 'Climax', 'Falling Action', 'Conclusion']
    } else if (imageCount <= 8) {
      return [
        'Introduction', 'Setup', 'Rising Action 1', 'Rising Action 2', 
        'Midpoint', 'Climax', 'Falling Action', 'Conclusion'
      ]
    } else {
      // For longer series
      const stages = ['Introduction', 'Setup']
      for (let i = 2; i <= imageCount; i++) {
        stages.push(`Development ${i-1}`)
      }
      return stages.slice(0, imageCount)
    }
  }

  // Generate series ideas using AI
  async generateSeriesIdeas(userInterest: string, count: number = 5): Promise<string[]> {
    try {
      if (!ollamaClient.isAvailable()) {
        console.log('Ollama not available, generating offline ideas')
        return this.generateOfflineIdeas(userInterest, count)
      }

      const systemPrompt = `Generate ${count} creative and diverse series ideas for visual storytelling based on the user's interest: "${userInterest}"

Each idea should be:
1. Engaging and visually rich
2. Suitable for image series (5-30 images)
3. Different genres and styles
4. Have strong narrative potential
5. Appeal to creators and storytellers

Return as a JSON array of strings:
["Idea 1 title and brief description", "Idea 2 title and brief description", ...]

Focus on variety: fantasy, sci-fi, slice of life, adventure, mystery, etc.`

      const response = await ollamaClient.chat({
        model: 'gpt-oss:78b-cloud', // Use faster model for ideas
        messages: [
          {
            role: 'system',
            content: systemPrompt
          },
          {
            role: 'user',
            content: `Generate ${count} series ideas about ${userInterest}`
          }
        ],
        options: {
          temperature: 0.9, // High creativity for ideas
          max_tokens: 1000,
        },
      })

      // Parse response
      const ideasMatch = response.match(/\[[\s\S]*?\]/)
      if (ideasMatch) {
        try {
          return JSON.parse(ideasMatch[0])
        } catch (e) {
          console.error('Failed to parse ideas:', e)
        }
      }

      // Fallback to offline if parsing fails
      return this.generateOfflineIdeas(userInterest, count)

    } catch (error) {
      console.error('Failed to generate ideas:', error)
      return this.generateOfflineIdeas(userInterest, count)
    }
  }

  // Offline idea generation
  private generateOfflineIdeas(userInterest: string, count: number): string[] {
    const templates = [
      `Epic ${userInterest} Adventure Series`,
      `Mysterious ${userInterest} Mystery`,
      `Coming-of-Age ${userInterest} Story`,
      `Action-Packed ${userInterest} Saga`,
      `Heartwarming ${userInterest} Journey`,
    ]

    return templates.slice(0, count)
  }

  // Storage methods
  private saveSeries(series: GeneratedSeries): void {
    if (typeof window !== 'undefined') {
      localStorage.setItem(`series_${series.id}`, JSON.stringify(series))
    }
  }

  getSeries(seriesId: string): GeneratedSeries | null {
    if (typeof window === 'undefined') return null
    
    try {
      const stored = localStorage.getItem(`series_${seriesId}`)
      return stored ? JSON.parse(stored) : null
    } catch (error) {
      console.error('Failed to load series:', error)
      return null
    }
  }

  getAllSeries(): GeneratedSeries[] {
    if (typeof window === 'undefined') return []
    
    const series: GeneratedSeries[] = []
    for (let i = 0; i < localStorage.length; i++) {
      const key = localStorage.key(i)
      if (key && key.startsWith('series_')) {
        try {
          const seriesData = JSON.parse(localStorage.getItem(key)!)
          series.push(seriesData)
        } catch (error) {
          console.error('Failed to parse series:', error)
        }
      }
    }
    return series
  }

  deleteSeries(seriesId: string): boolean {
    if (typeof window === 'undefined') return false
    
    try {
      localStorage.removeItem(`series_${seriesId}`)
      return true
    } catch (error) {
      console.error('Failed to delete series:', error)
      return false
    }
  }

  updateSeries(seriesId: string, updates: Partial<GeneratedSeries>): boolean {
    if (typeof window === 'undefined') return false
    
    try {
      const existing = this.getSeries(seriesId)
      if (!existing) return false
      
      const updated = { ...existing, ...updates, updatedAt: new Date().toISOString() }
      localStorage.setItem(`series_${seriesId}`, JSON.stringify(updated))
      return true
    } catch (error) {
      console.error('Failed to update series:', error)
      return false
    }
  }

  // Check Ollama availability
  async checkOllamaStatus(): Promise<{
    available: boolean
    modelsAvailable: string[]
    apiKeySet: boolean
    error?: string
  }> {
    try {
      if (!ollamaClient.isAvailable()) {
        return {
          available: false,
          modelsAvailable: [],
          apiKeySet: false,
          error: 'Ollama API key not set. Get your free key at https://ollama.com'
        }
      }

      const models = await ollamaClient.listModels()
      return {
        available: true,
        modelsAvailable: models.map(m => m.name),
        apiKeySet: true,
      }
    } catch (error) {
      return {
        available: false,
        modelsAvailable: [],
        apiKeySet: ollamaClient.isAvailable(),
        error: error instanceof Error ? error.message : 'Unknown error'
      }
    }
  }
}

export const seriesGenerator = new SeriesGenerator()