import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { assetService, type Asset, type AssetCreate, type AssetUpdate, AssetCategory, TaskStatus } from '@/services/asset'

export const useAssetsStore = defineStore('assets', () => {
  // State
  const assets = ref<Asset[]>([])
  const currentAsset = ref<Asset | null>(null)
  const isLoading = ref(false)
  const error = ref<string | null>(null)

  // Getters
  const getAssetsByCategory = computed(() => {
    return (category: AssetCategory) => assets.value.filter(asset => asset.category === category)
  })

  const getAssetById = computed(() => {
    return (id: number) => assets.value.find(asset => asset.id === id)
  })

  const assetsByCategory = computed(() => {
    const grouped: Record<AssetCategory, Asset[]> = {
      [AssetCategory.CHARACTERS]: [],
      [AssetCategory.PROPS]: [],
      [AssetCategory.SETS]: [],
      [AssetCategory.VEHICLES]: []
    }

    assets.value.forEach(asset => {
      grouped[asset.category].push(asset)
    })

    return grouped
  })

  // Actions
  const fetchAssets = async (
    projectId: number, 
    options?: {
      category?: AssetCategory
      taskStatusFilter?: string
      sortBy?: string
      sortDirection?: 'asc' | 'desc'
    }
  ) => {
    try {
      isLoading.value = true
      error.value = null
      const data = await assetService.getAssets(projectId, options)
      assets.value = data
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to fetch assets'
      throw err
    } finally {
      isLoading.value = false
    }
  }

  const fetchAsset = async (assetId: number) => {
    try {
      isLoading.value = true
      error.value = null
      const data = await assetService.getAsset(assetId)
      currentAsset.value = data
      
      // Update in assets list if it exists
      const index = assets.value.findIndex(asset => asset.id === assetId)
      if (index !== -1) {
        assets.value[index] = data
      }
      
      return data
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to fetch asset'
      throw err
    } finally {
      isLoading.value = false
    }
  }

  const createAsset = async (projectId: number, assetData: AssetCreate) => {
    try {
      isLoading.value = true
      error.value = null
      const newAsset = await assetService.createAsset(projectId, assetData)
      assets.value.push(newAsset)
      return newAsset
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to create asset'
      throw err
    } finally {
      isLoading.value = false
    }
  }

  const updateAsset = async (assetId: number, assetData: AssetUpdate) => {
    try {
      isLoading.value = true
      error.value = null
      const updatedAsset = await assetService.updateAsset(assetId, assetData)
      
      // Update in assets list
      const index = assets.value.findIndex(asset => asset.id === assetId)
      if (index !== -1) {
        assets.value[index] = updatedAsset
      }
      
      // Update current asset if it's the same
      if (currentAsset.value?.id === assetId) {
        currentAsset.value = updatedAsset
      }
      
      return updatedAsset
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to update asset'
      throw err
    } finally {
      isLoading.value = false
    }
  }

  const deleteAsset = async (assetId: number) => {
    try {
      isLoading.value = true
      error.value = null
      await assetService.deleteAsset(assetId)
      
      // Remove from assets list
      const index = assets.value.findIndex(asset => asset.id === assetId)
      if (index !== -1) {
        assets.value.splice(index, 1)
      }
      
      // Clear current asset if it's the same
      if (currentAsset.value?.id === assetId) {
        currentAsset.value = null
      }
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to delete asset'
      throw err
    } finally {
      isLoading.value = false
    }
  }

  const clearAssets = () => {
    assets.value = []
    currentAsset.value = null
    error.value = null
  }

  const setCurrentAsset = (asset: Asset | null) => {
    currentAsset.value = asset
  }

  const updateTaskStatus = async (assetId: number, taskType: string, newStatus: TaskStatus) => {
    // Find the asset in the store
    const assetIndex = assets.value.findIndex(asset => asset.id === assetId)
    if (assetIndex === -1) return

    const asset = assets.value[assetIndex]
    
    // Store original status for rollback
    const originalStatus = asset.task_status?.[taskType]
    const originalTaskDetail = asset.task_details?.find(task => task.task_type === taskType)
    const originalTaskDetailStatus = originalTaskDetail?.status
    
    // Optimistic update - update the task status in the asset immediately
    if (asset.task_status) {
      asset.task_status[taskType] = newStatus
    }
    
    // Update the task details if available
    if (asset.task_details) {
      const taskDetail = asset.task_details.find(task => task.task_type === taskType)
      if (taskDetail) {
        taskDetail.status = newStatus
      }
    }
    
    // Update the current asset if it's the same
    if (currentAsset.value?.id === assetId) {
      currentAsset.value = { ...asset }
    }

    try {
      // Make API call to update task status
      const { taskService } = await import('@/services/task')
      
      // Get task ID from task details
      let taskId = asset.task_details?.find(task => task.task_type === taskType)?.task_id
      
      // If no task exists, create one first
      if (!taskId) {
        const newTask = await taskService.createAssetTask(assetId, taskType)
        taskId = newTask.task_id
        
        // Update task details with new task
        if (asset.task_details) {
          const existingTaskIndex = asset.task_details.findIndex(task => task.task_type === taskType)
          if (existingTaskIndex !== -1) {
            asset.task_details[existingTaskIndex].task_id = taskId
          } else {
            asset.task_details.push({
              task_type: taskType as any,
              status: newStatus,
              task_id: taskId
            })
          }
        }
      }
      
      // Update the task status via API
      if (taskId) {
        await taskService.updateTaskStatus(taskId, newStatus)
      }
    } catch (error) {
      // Rollback optimistic update on error
      if (asset.task_status && originalStatus !== undefined) {
        asset.task_status[taskType] = originalStatus
      }
      
      if (originalTaskDetail && originalTaskDetailStatus !== undefined) {
        originalTaskDetail.status = originalTaskDetailStatus
      }
      
      // Update the current asset if it's the same
      if (currentAsset.value?.id === assetId) {
        currentAsset.value = { ...asset }
      }
      
      throw error
    }
  }

  const bulkUpdateTaskStatus = async (assetIds: number[], taskType: string, newStatus: TaskStatus) => {
    if (assetIds.length === 0) return

    // Store original states for rollback
    const originalStates = new Map<number, {
      taskStatus?: TaskStatus
      taskDetail?: { status: TaskStatus; task_id?: number }
    }>()

    // Optimistic updates
    for (const assetId of assetIds) {
      const assetIndex = assets.value.findIndex(asset => asset.id === assetId)
      if (assetIndex === -1) continue

      const asset = assets.value[assetIndex]
      
      // Store original state
      const originalTaskStatus = asset.task_status?.[taskType]
      const originalTaskDetail = asset.task_details?.find(task => task.task_type === taskType)
      originalStates.set(assetId, {
        taskStatus: originalTaskStatus,
        taskDetail: originalTaskDetail ? { 
          status: originalTaskDetail.status, 
          task_id: originalTaskDetail.task_id 
        } : undefined
      })

      // Apply optimistic update
      if (asset.task_status) {
        asset.task_status[taskType] = newStatus
      }
      
      if (asset.task_details) {
        const taskDetail = asset.task_details.find(task => task.task_type === taskType)
        if (taskDetail) {
          taskDetail.status = newStatus
        }
      }
      
      // Update current asset if it's the same
      if (currentAsset.value?.id === assetId) {
        currentAsset.value = { ...asset }
      }
    }

    try {
      const { taskService } = await import('@/services/task')
      const taskIds: number[] = []

      // Collect or create task IDs
      for (const assetId of assetIds) {
        const asset = assets.value.find(a => a.id === assetId)
        if (!asset) continue

        let taskId = asset.task_details?.find(task => task.task_type === taskType)?.task_id
        
        // If no task exists, create one first
        if (!taskId) {
          const newTask = await taskService.createAssetTask(assetId, taskType)
          taskId = newTask.task_id
          
          // Update task details with new task
          if (asset.task_details) {
            const existingTaskIndex = asset.task_details.findIndex(task => task.task_type === taskType)
            if (existingTaskIndex !== -1) {
              asset.task_details[existingTaskIndex].task_id = taskId
            } else {
              asset.task_details.push({
                task_type: taskType as any,
                status: newStatus,
                task_id: taskId
              })
            }
          }
        }
        
        if (taskId) {
          taskIds.push(taskId)
        }
      }

      // Bulk update task statuses via API
      if (taskIds.length > 0) {
        await taskService.bulkUpdateStatus(taskIds, newStatus)
      }
    } catch (error) {
      // Rollback all optimistic updates on error
      for (const assetId of assetIds) {
        const assetIndex = assets.value.findIndex(asset => asset.id === assetId)
        if (assetIndex === -1) continue

        const asset = assets.value[assetIndex]
        const originalState = originalStates.get(assetId)
        
        if (originalState) {
          // Rollback task status
          if (asset.task_status && originalState.taskStatus !== undefined) {
            asset.task_status[taskType] = originalState.taskStatus
          }
          
          // Rollback task detail
          if (originalState.taskDetail) {
            const taskDetail = asset.task_details?.find(task => task.task_type === taskType)
            if (taskDetail) {
              taskDetail.status = originalState.taskDetail.status
              if (originalState.taskDetail.task_id !== undefined) {
                taskDetail.task_id = originalState.taskDetail.task_id
              }
            }
          }
        }
        
        // Update current asset if it's the same
        if (currentAsset.value?.id === assetId) {
          currentAsset.value = { ...asset }
        }
      }
      
      throw error
    }
  }

  return {
    // State
    assets,
    currentAsset,
    isLoading,
    error,
    
    // Getters
    getAssetsByCategory,
    getAssetById,
    assetsByCategory,
    
    // Actions
    fetchAssets,
    fetchAsset,
    createAsset,
    updateAsset,
    deleteAsset,
    clearAssets,
    setCurrentAsset,
    updateTaskStatus,
    bulkUpdateTaskStatus
  }
})