/**
 * Media Store
 * Manages media processing and analysis operations
 */

import { create } from 'zustand'
import { VideoService, AudioService } from '../services/tauri'

interface ProcessingJob {
  id: string
  type: 'video' | 'audio'
  operation: string
  status: 'pending' | 'processing' | 'completed' | 'failed'
  progress: number
  inputPath: string
  outputPath?: string
  result?: any
  error?: string
  startTime: number
  endTime?: number
}

interface MediaState {
  // Processing jobs
  jobs: ProcessingJob[]
  
  // Current playback
  currentMedia: string | null
  isPlaying: boolean
  currentTime: number
  duration: number
  volume: number
  
  // Preview settings
  previewQuality: 'low' | 'medium' | 'high'
  
  // Actions
  addJob: (job: Omit<ProcessingJob, 'id' | 'status' | 'progress' | 'startTime'>) => string
  updateJob: (jobId: string, updates: Partial<ProcessingJob>) => void
  removeJob: (jobId: string) => void
  clearCompletedJobs: () => void
  
  // Video processing
  trimVideo: (inputPath: string, outputPath: string, startTime: number, endTime: number) => Promise<string>
  resizeVideo: (inputPath: string, outputPath: string, width?: number, height?: number) => Promise<string>
  cropVideo: (inputPath: string, outputPath: string, x1: number, y1: number, x2: number, y2: number) => Promise<string>
  adjustBrightness: (inputPath: string, outputPath: string, factor: number) => Promise<string>
  adjustContrast: (inputPath: string, outputPath: string, factor: number) => Promise<string>
  addText: (inputPath: string, outputPath: string, text: string, options?: any) => Promise<string>
  mergeVideos: (videoPaths: string[], outputPath: string) => Promise<string>
  
  // Audio analysis
  analyzeRhythm: (filePath: string) => Promise<string>
  analyzeSpectral: (filePath: string) => Promise<string>
  analyzeTempo: (filePath: string) => Promise<string>
  analyzePitch: (filePath: string) => Promise<string>
  analyzeEnergy: (filePath: string) => Promise<string>
  analyzeMFCC: (filePath: string) => Promise<string>
  
  // Playback control
  setCurrentMedia: (mediaPath: string | null) => void
  setPlaying: (playing: boolean) => void
  setCurrentTime: (time: number) => void
  setDuration: (duration: number) => void
  setVolume: (volume: number) => void
  
  // Settings
  setPreviewQuality: (quality: 'low' | 'medium' | 'high') => void
}

export const useMediaStore = create<MediaState>((set, get) => ({
  // Initial state
  jobs: [],
  currentMedia: null,
  isPlaying: false,
  currentTime: 0,
  duration: 0,
  volume: 1.0,
  previewQuality: 'medium',

  // Job management
  addJob: (jobData) => {
    const job: ProcessingJob = {
      ...jobData,
      id: crypto.randomUUID(),
      status: 'pending',
      progress: 0,
      startTime: Date.now()
    }

    set(state => ({
      jobs: [...state.jobs, job]
    }))

    return job.id
  },

  updateJob: (jobId, updates) => {
    set(state => ({
      jobs: state.jobs.map(job =>
        job.id === jobId ? { ...job, ...updates } : job
      )
    }))
  },

  removeJob: (jobId) => {
    set(state => ({
      jobs: state.jobs.filter(job => job.id !== jobId)
    }))
  },

  clearCompletedJobs: () => {
    set(state => ({
      jobs: state.jobs.filter(job => job.status !== 'completed' && job.status !== 'failed')
    }))
  },

  // Video processing operations
  trimVideo: async (inputPath, outputPath, startTime, endTime) => {
    const { addJob, updateJob } = get()
    
    const jobId = addJob({
      type: 'video',
      operation: 'trim',
      inputPath,
      outputPath
    })

    try {
      updateJob(jobId, { status: 'processing', progress: 0 })
      
      const result = await VideoService.trimVideo(inputPath, outputPath, startTime, endTime)
      
      updateJob(jobId, { 
        status: 'completed', 
        progress: 100, 
        result,
        endTime: Date.now()
      })
      
      return jobId
    } catch (error) {
      updateJob(jobId, { 
        status: 'failed', 
        error: error instanceof Error ? error.message : 'Unknown error',
        endTime: Date.now()
      })
      throw error
    }
  },

  resizeVideo: async (inputPath, outputPath, width, height) => {
    const { addJob, updateJob } = get()
    
    const jobId = addJob({
      type: 'video',
      operation: 'resize',
      inputPath,
      outputPath
    })

    try {
      updateJob(jobId, { status: 'processing', progress: 0 })
      
      const result = await VideoService.resizeVideo(inputPath, outputPath, width, height)
      
      updateJob(jobId, { 
        status: 'completed', 
        progress: 100, 
        result,
        endTime: Date.now()
      })
      
      return jobId
    } catch (error) {
      updateJob(jobId, { 
        status: 'failed', 
        error: error instanceof Error ? error.message : 'Unknown error',
        endTime: Date.now()
      })
      throw error
    }
  },

  cropVideo: async (inputPath, outputPath, x1, y1, x2, y2) => {
    const { addJob, updateJob } = get()
    
    const jobId = addJob({
      type: 'video',
      operation: 'crop',
      inputPath,
      outputPath
    })

    try {
      updateJob(jobId, { status: 'processing', progress: 0 })
      
      const result = await VideoService.cropVideo(inputPath, outputPath, x1, y1, x2, y2)
      
      updateJob(jobId, { 
        status: 'completed', 
        progress: 100, 
        result,
        endTime: Date.now()
      })
      
      return jobId
    } catch (error) {
      updateJob(jobId, { 
        status: 'failed', 
        error: error instanceof Error ? error.message : 'Unknown error',
        endTime: Date.now()
      })
      throw error
    }
  },

  adjustBrightness: async (inputPath, outputPath, factor) => {
    const { addJob, updateJob } = get()
    
    const jobId = addJob({
      type: 'video',
      operation: 'adjust_brightness',
      inputPath,
      outputPath
    })

    try {
      updateJob(jobId, { status: 'processing', progress: 0 })
      
      const result = await VideoService.adjustBrightness(inputPath, outputPath, factor)
      
      updateJob(jobId, { 
        status: 'completed', 
        progress: 100, 
        result,
        endTime: Date.now()
      })
      
      return jobId
    } catch (error) {
      updateJob(jobId, { 
        status: 'failed', 
        error: error instanceof Error ? error.message : 'Unknown error',
        endTime: Date.now()
      })
      throw error
    }
  },

  adjustContrast: async (inputPath, outputPath, factor) => {
    const { addJob, updateJob } = get()
    
    const jobId = addJob({
      type: 'video',
      operation: 'adjust_contrast',
      inputPath,
      outputPath
    })

    try {
      updateJob(jobId, { status: 'processing', progress: 0 })
      
      const result = await VideoService.adjustContrast(inputPath, outputPath, factor)
      
      updateJob(jobId, { 
        status: 'completed', 
        progress: 100, 
        result,
        endTime: Date.now()
      })
      
      return jobId
    } catch (error) {
      updateJob(jobId, { 
        status: 'failed', 
        error: error instanceof Error ? error.message : 'Unknown error',
        endTime: Date.now()
      })
      throw error
    }
  },

  addText: async (inputPath, outputPath, text, options) => {
    const { addJob, updateJob } = get()
    
    const jobId = addJob({
      type: 'video',
      operation: 'add_text',
      inputPath,
      outputPath
    })

    try {
      updateJob(jobId, { status: 'processing', progress: 0 })
      
      const result = await VideoService.addText(inputPath, outputPath, text, options)
      
      updateJob(jobId, { 
        status: 'completed', 
        progress: 100, 
        result,
        endTime: Date.now()
      })
      
      return jobId
    } catch (error) {
      updateJob(jobId, { 
        status: 'failed', 
        error: error instanceof Error ? error.message : 'Unknown error',
        endTime: Date.now()
      })
      throw error
    }
  },

  mergeVideos: async (videoPaths, outputPath) => {
    const { addJob, updateJob } = get()
    
    const jobId = addJob({
      type: 'video',
      operation: 'merge',
      inputPath: videoPaths.join(', '),
      outputPath
    })

    try {
      updateJob(jobId, { status: 'processing', progress: 0 })
      
      const result = await VideoService.mergeVideos(videoPaths, outputPath)
      
      updateJob(jobId, { 
        status: 'completed', 
        progress: 100, 
        result,
        endTime: Date.now()
      })
      
      return jobId
    } catch (error) {
      updateJob(jobId, { 
        status: 'failed', 
        error: error instanceof Error ? error.message : 'Unknown error',
        endTime: Date.now()
      })
      throw error
    }
  },

  // Audio analysis operations
  analyzeRhythm: async (filePath) => {
    const { addJob, updateJob } = get()
    
    const jobId = addJob({
      type: 'audio',
      operation: 'analyze_rhythm',
      inputPath: filePath
    })

    try {
      updateJob(jobId, { status: 'processing', progress: 0 })
      
      const result = await AudioService.analyzeRhythm(filePath)
      
      updateJob(jobId, { 
        status: 'completed', 
        progress: 100, 
        result,
        endTime: Date.now()
      })
      
      return jobId
    } catch (error) {
      updateJob(jobId, { 
        status: 'failed', 
        error: error instanceof Error ? error.message : 'Unknown error',
        endTime: Date.now()
      })
      throw error
    }
  },

  analyzeSpectral: async (filePath) => {
    const { addJob, updateJob } = get()
    
    const jobId = addJob({
      type: 'audio',
      operation: 'analyze_spectral',
      inputPath: filePath
    })

    try {
      updateJob(jobId, { status: 'processing', progress: 0 })
      
      const result = await AudioService.analyzeSpectral(filePath)
      
      updateJob(jobId, { 
        status: 'completed', 
        progress: 100, 
        result,
        endTime: Date.now()
      })
      
      return jobId
    } catch (error) {
      updateJob(jobId, { 
        status: 'failed', 
        error: error instanceof Error ? error.message : 'Unknown error',
        endTime: Date.now()
      })
      throw error
    }
  },

  analyzeTempo: async (filePath) => {
    const { addJob, updateJob } = get()
    
    const jobId = addJob({
      type: 'audio',
      operation: 'analyze_tempo',
      inputPath: filePath
    })

    try {
      updateJob(jobId, { status: 'processing', progress: 0 })
      
      const result = await AudioService.analyzeTempo(filePath)
      
      updateJob(jobId, { 
        status: 'completed', 
        progress: 100, 
        result,
        endTime: Date.now()
      })
      
      return jobId
    } catch (error) {
      updateJob(jobId, { 
        status: 'failed', 
        error: error instanceof Error ? error.message : 'Unknown error',
        endTime: Date.now()
      })
      throw error
    }
  },

  analyzePitch: async (filePath) => {
    const { addJob, updateJob } = get()
    
    const jobId = addJob({
      type: 'audio',
      operation: 'analyze_pitch',
      inputPath: filePath
    })

    try {
      updateJob(jobId, { status: 'processing', progress: 0 })
      
      const result = await AudioService.analyzePitch(filePath)
      
      updateJob(jobId, { 
        status: 'completed', 
        progress: 100, 
        result,
        endTime: Date.now()
      })
      
      return jobId
    } catch (error) {
      updateJob(jobId, { 
        status: 'failed', 
        error: error instanceof Error ? error.message : 'Unknown error',
        endTime: Date.now()
      })
      throw error
    }
  },

  analyzeEnergy: async (filePath) => {
    const { addJob, updateJob } = get()
    
    const jobId = addJob({
      type: 'audio',
      operation: 'analyze_energy',
      inputPath: filePath
    })

    try {
      updateJob(jobId, { status: 'processing', progress: 0 })
      
      const result = await AudioService.analyzeEnergy(filePath)
      
      updateJob(jobId, { 
        status: 'completed', 
        progress: 100, 
        result,
        endTime: Date.now()
      })
      
      return jobId
    } catch (error) {
      updateJob(jobId, { 
        status: 'failed', 
        error: error instanceof Error ? error.message : 'Unknown error',
        endTime: Date.now()
      })
      throw error
    }
  },

  analyzeMFCC: async (filePath) => {
    const { addJob, updateJob } = get()
    
    const jobId = addJob({
      type: 'audio',
      operation: 'analyze_mfcc',
      inputPath: filePath
    })

    try {
      updateJob(jobId, { status: 'processing', progress: 0 })
      
      const result = await AudioService.analyzeMFCC(filePath)
      
      updateJob(jobId, { 
        status: 'completed', 
        progress: 100, 
        result,
        endTime: Date.now()
      })
      
      return jobId
    } catch (error) {
      updateJob(jobId, { 
        status: 'failed', 
        error: error instanceof Error ? error.message : 'Unknown error',
        endTime: Date.now()
      })
      throw error
    }
  },

  // Playback control
  setCurrentMedia: (mediaPath) => {
    set({ currentMedia: mediaPath })
  },

  setPlaying: (playing) => {
    set({ isPlaying: playing })
  },

  setCurrentTime: (time) => {
    set({ currentTime: time })
  },

  setDuration: (duration) => {
    set({ duration })
  },

  setVolume: (volume) => {
    set({ volume: Math.max(0, Math.min(1, volume)) })
  },

  // Settings
  setPreviewQuality: (quality) => {
    set({ previewQuality: quality })
  }
}))

// Selectors
export const useProcessingJobs = () => useMediaStore(state => state.jobs)
export const useCurrentMedia = () => useMediaStore(state => state.currentMedia)
export const usePlaybackState = () => useMediaStore(state => ({
  isPlaying: state.isPlaying,
  currentTime: state.currentTime,
  duration: state.duration,
  volume: state.volume
}))
