<template>
  <div class="relative h-full flex flex-col">
    <!-- Main Content -->
    <div class="flex flex-col flex-1 min-h-0">
      <!-- Toolbar -->
      <div class="flex-shrink-0 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border-b pb-4 px-4 sm:px-6 pt-4 sm:pt-6 mb-4">
        <ShotTableToolbar
          :view-mode="viewMode"
          :episode-filter="episodeFilter"
          :search="searchQuery"
          :column-visibility="columnVisibility"
          :episodes="episodes"
          :all-task-types="allTaskTypes"
          :project-id="projectId"
          :selected-shot="selectedShot"
          :is-detail-panel-enabled="isDetailPanelEnabled"
          :is-columns-locked="lockColumns"
          @update:view-mode="viewMode = $event"
          @update:episode-filter="handleEpisodeFilterChange"
          @update:search="searchQuery = $event"
          @update:column-visibility="handleColumnVisibilityChange"
          @task-status-filter-changed="handleTaskStatusFilter"
          @toggle-detail-panel="toggleDetailPanelEnabled"
          @toggle-column-lock="toggleColumnLock"
          @bulk-create="showBulkCreateDialog = true"
          @create-shot="showCreateDialog = true"
        />
      </div>

    <!-- Loading State -->
    <div v-if="isLoading" class="flex items-center justify-center py-12 px-4 sm:px-6">
      <div class="flex items-center gap-2">
        <div class="animate-spin rounded-full h-6 w-6 border-b-2 border-primary"></div>
        <span class="text-muted-foreground">Loading shots...</span>
      </div>
    </div>

    <!-- Error State -->
    <div v-else-if="error" class="text-center py-12 px-4 sm:px-6">
      <AlertCircle class="h-12 w-12 mx-auto text-destructive mb-4" />
      <h3 class="text-lg font-semibold mb-2">Failed to load shots</h3>
      <p class="text-muted-foreground mb-4">{{ error }}</p>
      <Button @click="loadShots" variant="outline">
        <RefreshCw class="h-4 w-4 mr-2" />
        Try Again
      </Button>
    </div>

    <!-- Empty State -->
    <div v-else-if="filteredShots.length === 0 && !searchQuery" class="text-center py-12 px-4 sm:px-6">
      <Camera class="h-12 w-12 mx-auto text-muted-foreground mb-4" />
      <h3 class="text-lg font-semibold mb-2">No shots yet</h3>
      <p class="text-muted-foreground mb-4">
        {{ episodeFilter !== null ? 'This episode has no shots yet' : 'No shots found' }}
      </p>
      <div class="flex justify-center gap-2">
        <Button @click="showCreateDialog = true">
          <Plus class="h-4 w-4 mr-2" />
          Create Shot
        </Button>
        <Button @click="showBulkCreateDialog = true" variant="outline">
          <Layers class="h-4 w-4 mr-2" />
          Bulk Create
        </Button>
      </div>
    </div>

    <!-- No Results State -->
    <div v-else-if="filteredShots.length === 0" class="text-center py-12 px-4 sm:px-6">
      <Search class="h-12 w-12 mx-auto text-muted-foreground mb-4" />
      <h3 class="text-lg font-semibold mb-2">No shots found</h3>
      <p class="text-muted-foreground mb-4">
        Try adjusting your search criteria
      </p>
      <Button @click="clearSearch" variant="outline">
        Clear Search
      </Button>
    </div>

    <!-- Shots Grid/List/Table -->
    <div v-else class="flex-1 min-h-0">
      <!-- Grid View -->
      <div 
        v-if="viewMode === 'grid'"
        class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 px-4 sm:px-6 h-full overflow-auto"
      >
        <ShotCard
          v-for="shot in filteredShots"
          :key="shot.id"
          :shot="shot"
          @select="selectShot"
          @edit="editShot"
          @delete="deleteShot"
        />
      </div>

      <!-- List View -->
      <div v-else-if="viewMode === 'list'" class="space-y-2 px-4 sm:px-6 h-full overflow-auto">
        <div 
          v-for="shot in filteredShots"
          :key="shot.id"
          class="flex items-center gap-4 p-4 border rounded-lg hover:bg-muted/50 transition-colors"
        >
          <Camera class="h-5 w-5 text-muted-foreground flex-shrink-0" />
          <div class="flex-1 min-w-0">
            <div class="flex items-center gap-2">
              <h3 class="font-medium truncate">{{ shot.name }}</h3>
              <Badge :variant="getStatusVariant(shot.status)" class="text-xs">
                {{ formatStatus(shot.status) }}
              </Badge>
            </div>
            <p class="text-sm text-muted-foreground truncate">
              Frames {{ shot.frame_start }}-{{ shot.frame_end }} ({{ shot.frame_end - shot.frame_start + 1 }} frames)
              <span v-if="shot.description"> • {{ shot.description }}</span>
            </p>
          </div>
          <div class="flex items-center gap-2 text-sm text-muted-foreground flex-shrink-0">
            <ListTodo class="h-4 w-4" />
            <span>{{ shot.task_count }}</span>
          </div>
          <DropdownMenu>
            <DropdownMenuTrigger asChild @click.stop>
              <Button variant="ghost" size="sm" class="h-8 w-8 p-0">
                <MoreHorizontal class="h-4 w-4" />
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end">
              <DropdownMenuItem @click.stop="editShot(shot)">
                <Edit class="h-4 w-4 mr-2" />
                Edit Shot
              </DropdownMenuItem>
              <DropdownMenuSeparator />
              <DropdownMenuItem 
                @click.stop="deleteShot(shot)"
                class="text-destructive focus:text-destructive"
              >
                <Trash2 class="h-4 w-4 mr-2" />
                Delete Shot
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </div>
      </div>

      <!-- Table View -->
      <ShotsDataTable
        v-else-if="viewMode === 'table'"
        :columns="shotColumns"
        :data="filteredShots"
        :sorting="sorting"
        :column-visibility="columnVisibility"
        :all-task-types="allTaskTypes"
        :lock-columns="lockColumns"
        @update:sorting="sorting = $event"
        @update:column-visibility="handleColumnVisibilityChange"
        @update:rowSelection="handleRowSelectionChange"
        @row-click="handleRowClick"
        @row-dblclick="handleRowDoubleClick"
      />
    </div>
    </div>

    <!-- Detail Panel (Overlay - Desktop) with Slide Animation -->
    <Transition
      enter-active-class="transition-transform duration-300 ease-out"
      enter-from-class="translate-x-full"
      enter-to-class="translate-x-0"
      leave-active-class="transition-transform duration-300 ease-in"
      leave-from-class="translate-x-0"
      leave-to-class="translate-x-full"
    >
      <div 
        v-if="showPanel && selectedShot" 
        class="fixed right-0 top-[113px] bottom-0 w-96 bg-background border-l shadow-lg z-50 hidden lg:block overflow-y-auto"
      >
        <ShotDetailPanel
          :project-id="projectId"
          :shot-id="selectedShot.id"
          :initial-shot="selectedShot"
          @edit="editShot"
          @delete="deleteShot"
          @create-task="handleCreateTask"
          @select-task="handleSelectTask"
          @close="closeDetailPanel"
        />
      </div>
    </Transition>
  </div>

  <!-- Mobile Detail Sheet -->
  <Sheet v-model:open="showMobileDetail">
    <SheetContent side="right" class="w-full sm:max-w-md p-0">
      <ShotDetailPanel
        v-if="selectedShot"
        :project-id="projectId"
        :shot-id="selectedShot.id"
        :initial-shot="selectedShot"
        @edit="editShot"
        @delete="deleteShot"
        @create-task="handleCreateTask"
        @select-task="handleSelectTask"
      />
    </SheetContent>
  </Sheet>


  <!-- Dialogs -->
  <div class="space-y-4">
    <!-- Create Shot Dialog -->
    <Dialog v-model:open="showCreateDialog">
      <DialogContent class="sm:max-w-[500px]">
        <DialogHeader>
          <DialogTitle>Create New Shot</DialogTitle>
          <DialogDescription>
            Add a new shot to the selected episode.
          </DialogDescription>
        </DialogHeader>
        <ShotForm
          :is-loading="isCreating"
          :project-context="projectContext || undefined"
          :episode-context="episodes.find(e => e.id === (episodeFilter || episodes[0]?.id))"
          :validation-error="validationError"
          @submit="handleCreateShot"
          @cancel="showCreateDialog = false"
          @clear-error="clearValidationError"
        />
      </DialogContent>
    </Dialog>

    <!-- Bulk Create Dialog -->
    <Dialog v-model:open="showBulkCreateDialog">
      <DialogContent class="sm:max-w-[600px] max-h-[90vh] overflow-y-auto">
        <DialogHeader>
          <DialogTitle>Bulk Create Shots</DialogTitle>
          <DialogDescription>
            Create multiple shots at once with automatic naming and task generation.
          </DialogDescription>
        </DialogHeader>
        <BulkShotForm
          :is-loading="isBulkCreating"
          :project-context="projectContext || undefined"
          :episode-context="episodes.find(e => e.id === (episodeFilter || episodes[0]?.id))"
          :validation-error="validationError"
          @submit="handleBulkCreateShots"
          @cancel="showBulkCreateDialog = false"
          @clear-error="clearValidationError"
        />
      </DialogContent>
    </Dialog>

    <!-- Edit Shot Dialog -->
    <Dialog v-model:open="showEditDialog">
      <DialogContent class="sm:max-w-[500px]">
        <DialogHeader>
          <DialogTitle>Edit Shot</DialogTitle>
          <DialogDescription>
            Update the shot information and settings.
          </DialogDescription>
        </DialogHeader>
        <ShotForm
          :shot="selectedShot ?? undefined"
          :is-loading="isUpdating"
          :project-context="projectContext || undefined"
          :episode-context="episodes.find(e => e.id === selectedShot?.episode_id)"
          :validation-error="validationError"
          @submit="handleUpdateShot"
          @cancel="showEditDialog = false"
          @clear-error="clearValidationError"
        />
      </DialogContent>
    </Dialog>

    <!-- Delete Confirmation Dialog -->
    <ShotDeleteConfirmDialog
      v-if="deletionInfo && shotToDelete"
      :open="showDeleteDialog"
      :shot-id="shotToDelete.id"
      :shot-name="deletionInfo.shot_name"
      @update:open="showDeleteDialog = $event"
      @confirm-delete="handleDeleteShot"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, shallowRef, markRaw, nextTick, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { 
  Search, Plus, Camera, AlertCircle, RefreshCw,
  Layers, MoreHorizontal, Edit, ListTodo, Trash2
} from 'lucide-vue-next'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { useColumnVisibilityStore } from '@/stores/columnVisibility'

import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog'
import {
  Sheet,
  SheetContent,
} from '@/components/ui/sheet'
import ShotDeleteConfirmDialog from './ShotDeleteConfirmDialog.vue'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import ShotCard from './ShotCard.vue'
import ShotForm from './ShotForm.vue'
import BulkShotForm from './BulkShotForm.vue'
import ShotDetailPanel from './ShotDetailPanel.vue'
import ShotsDataTable from './ShotsDataTable.vue'
import ShotTableToolbar from './ShotTableToolbar.vue'
import { createShotColumns, type ShotColumnMeta } from './columns'
import { shotService, ShotStatus, TaskStatus, type Shot, type ShotCreate, type ShotUpdate, type BulkShotCreate, type ShotDeletionInfo, type ProjectValidationError } from '@/services/shot'
import { episodeService, type Episode } from '@/services/episode'
import { projectService, type Project } from '@/services/project'
import { customTaskTypeService } from '@/services/customTaskType'
import { useToast } from '@/components/ui/toast/use-toast'
import { useTaskStatusesStore } from '@/stores/taskStatuses'
import { useDetailPanel } from '@/composables/useDetailPanel'
import type { SortingState, VisibilityState } from '@tanstack/vue-table'

interface ValidationErrorDisplay {
  title: string
  message: string
  suggestion?: string
  field?: string
}

interface Props {
  projectId: number
  selectedEpisodeId?: number
}

const props = defineProps<Props>()

// Composables
const router = useRouter()
const { toast } = useToast()
const taskStatusesStore = useTaskStatusesStore()

// Detail panel composable
const {
  isDetailPanelEnabled,
  isDetailPanelVisible,
  selectedEntity: selectedShot,
  showMobileDetail,
  showPanel,
  toggleDetailPanelEnabled,
  closeDetailPanel,
  selectEntity: selectShot,
  handleRowClick
} = useDetailPanel<Shot>({
  isDialogOpen: () => showCreateDialog.value || showBulkCreateDialog.value || showEditDialog.value || showDeleteDialog.value,
  sessionStorageKey: 'shotBrowser.detailPanelEnabled'
})

// Handle double-click to navigate to shot detail page
const handleRowDoubleClick = (shot: Shot) => {
  if (props.projectId) {
    router.push(`/projects/${props.projectId}/shots/${shot.id}`)
  }
}

// Reactive state
const shots = ref<Shot[]>([])
const isLoading = ref(false)
const error = ref<string | null>(null)
const viewMode = ref<'grid' | 'list' | 'table'>('table')
const searchQuery = ref('')
const shotToDelete = ref<Shot | null>(null)
const showCreateDialog = ref(false)
const showBulkCreateDialog = ref(false)
const showEditDialog = ref(false)
const showDeleteDialog = ref(false)
const deletionInfo = ref<ShotDeletionInfo | null>(null)
const isCreating = ref(false)
const isBulkCreating = ref(false)
const isUpdating = ref(false)
const episodes = ref<Episode[]>([])
const episodeFilter = ref<number | null>(null)
const allTaskTypes = ref<string[]>([])
const taskStatusFilter = ref('')
const projectContext = ref<Project | null>(null)
const validationError = ref<ValidationErrorDisplay | null>(null)

// TanStack Table state
const sorting = ref<SortingState>([])
const columnVisibilityStore = useColumnVisibilityStore()
const columnVisibility = ref<VisibilityState>({})
const rowSelection = ref<Record<string, boolean>>({})

// Lock (freeze) the first columns (select/thumbnail/name) for horizontal scroll
const lockColumns = ref(localStorage.getItem('shot-columns-locked') === 'true')
const toggleColumnLock = () => {
  lockColumns.value = !lockColumns.value
  localStorage.setItem('shot-columns-locked', String(lockColumns.value))
}

// Computed for selected count
const selectedCount = computed(() => {
  return Object.keys(rowSelection.value).length
})

const initializeColumnVisibility = () => {
  // Initialize the global store
  columnVisibilityStore.initialize()
  // Use store's visibility as the initial value
  columnVisibility.value = columnVisibilityStore.visibility
}

initializeColumnVisibility()

// Computed properties
const filteredShots = computed(() => {
  let filtered = [...shots.value]

  // Filter by episode
  if (episodeFilter.value !== null) {
    filtered = filtered.filter(shot => shot.episode_id === episodeFilter.value)
  }

  // Filter by search query
  if (searchQuery.value.trim()) {
    const query = searchQuery.value.toLowerCase().trim()
    filtered = filtered.filter(shot =>
      shot.name.toLowerCase().includes(query) ||
      shot.description?.toLowerCase().includes(query)
    )
  }

  return filtered
})

// Watch filteredShots for any additional logic if needed

// Methods
const loadShots = async () => {
  try {
    isLoading.value = true
    error.value = null
    const options: any = {}
    
    if (taskStatusFilter.value) {
      options.taskStatusFilter = taskStatusFilter.value
    }
    if (episodeFilter.value !== null) {
      options.episodeId = episodeFilter.value
    }

    const data = await shotService.getShots(options)
    shots.value = data
  } catch (err) {
    error.value = err instanceof Error ? err.message : 'Failed to load shots'
    console.error('Failed to load shots:', err)
  } finally {
    isLoading.value = false
  }
}

const loadEpisodes = async () => {
  if (!props.projectId) return
  
  try {
    const data = await episodeService.getEpisodes(props.projectId)
    episodes.value = data
  } catch (err) {
    console.error('Failed to load episodes:', err)
  }
}

const loadTaskTypes = async () => {
  if (!props.projectId) return
  
  try {
    const data = await customTaskTypeService.getAllTaskTypes(props.projectId)
    allTaskTypes.value = data.shot_task_types || []
  } catch (err) {
    console.error('Failed to load task types:', err)
  }
}

const loadTaskStatuses = async () => {
  if (!props.projectId) return
  
  try {
    await taskStatusesStore.fetchProjectStatuses(props.projectId)
  } catch (err) {
    console.error('Failed to load task statuses:', err)
  }
}

const loadProjectContext = async () => {
  if (!props.projectId) return
  
  try {
    const project = await projectService.getProject(props.projectId)
    projectContext.value = project
  } catch (err) {
    console.error('Failed to load project context:', err)
  }
}

const formatValidationError = (err: ProjectValidationError, context: 'single' | 'bulk' = 'single'): ValidationErrorDisplay => {
  switch (err.code) {
    case 'PROJECT_SCOPED_NAME_CONFLICT':
      return {
        title: 'Duplicate Shot Name',
        message: context === 'bulk' 
          ? `One or more shots with the prefix "${err.shotName}" already exist in this project.`
          : `A shot named "${err.shotName}" already exists in this project.`,
        suggestion: context === 'bulk'
          ? 'Try using a different name prefix or check existing shots.'
          : 'Please choose a different name for this shot.',
        field: context === 'bulk' ? 'name_prefix' : 'name'
      }
    case 'PROJECT_EPISODE_MISMATCH':
      return {
        title: 'Project Mismatch',
        message: 'The selected episode does not belong to the current project.',
        suggestion: 'Please select an episode from the current project.'
      }
    case 'INVALID_PROJECT_ID':
      return {
        title: 'Invalid Project',
        message: 'The specified project is not valid or accessible.',
        suggestion: 'Please refresh the page and try again.'
      }
    default:
      return {
        title: 'Validation Error',
        message: err.message || 'An unknown validation error occurred.',
        suggestion: 'Please check your input and try again.'
      }
  }
}

const clearValidationError = () => {
  validationError.value = null
}

const handleEpisodeFilterChange = (episodeId: number | null) => {
  episodeFilter.value = episodeId
  loadShots()
}

const handleTaskStatusFilter = (filter: string) => {
  taskStatusFilter.value = filter
  loadShots()
}

// Debounced column visibility handler to prevent rapid re-renders
let visibilityUpdateTimeout: ReturnType<typeof setTimeout> | null = null
const handleColumnVisibilityChange = (visibility: VisibilityState) => {
  columnVisibility.value = visibility
  
  // Also update the global store
  columnVisibilityStore.setColumnVisibility(visibility)
  
  // Debounce session storage updates (for backwards compatibility)
  if (visibilityUpdateTimeout) clearTimeout(visibilityUpdateTimeout)
  visibilityUpdateTimeout = setTimeout(() => {
    sessionStorage.setItem('shotBrowser.columnVisibility', JSON.stringify(visibility))
  }, 100)
}

const handleRowSelectionChange = (selection: Record<string, boolean>) => {
  // Update local selection state
  rowSelection.value = selection
}

const getSelectedCount = () => {
  return Object.keys(rowSelection.value).length
}



const viewTasks = (shot: Shot) => {
  selectShot(shot)
  // Always show panel when explicitly viewing tasks, regardless of enabled state
  // Show mobile detail sheet on small screens
  if (window.innerWidth < 1024) {
    showMobileDetail.value = true
  }
}

const handleTaskStatusUpdated = (shotId: number, taskType: string, newStatus: TaskStatus) => {
  // Update local state instead of reloading all shots
  const shot = shots.value.find(s => s.id === shotId)
  if (shot) {
    if (!shot.task_status) {
      shot.task_status = {}
    }
    shot.task_status[taskType] = newStatus
  }
  
  // Show success toast
  toast({
    title: 'Task status updated',
    description: `${taskType} status updated successfully`,
  })
}

const handleTaskAssignmentUpdated = (shotId: number, taskType: string, userId: number | null) => {
  // Update local state instead of reloading all shots
  const shot = shots.value.find(s => s.id === shotId)
  if (shot && shot.task_details) {
    const taskDetail = shot.task_details.find(detail => detail.task_type === taskType)
    if (taskDetail) {
      taskDetail.assigned_user_id = userId ?? undefined
    }
  }
  
  // Show success toast
  toast({
    title: 'Task assignment updated',
    description: userId ? `${taskType} task assigned successfully` : `${taskType} task unassigned successfully`,
  })
}

const handleBulkTaskStatusChange = async (taskType: string, newStatus: TaskStatus) => {
  const selectedShotIds = Object.keys(rowSelection.value).map(id => parseInt(id))
  
  if (selectedShotIds.length === 0) {
    return
  }

  try {
    // Update each selected shot's task status
    const updatePromises = selectedShotIds.map(async (shotId) => {
      const shot = shots.value.find(s => s.id === shotId)
      if (shot) {
        // Update local state optimistically
        if (!shot.task_status) {
          shot.task_status = {}
        }
        shot.task_status[taskType] = newStatus
        
        // Call the individual update handler to trigger any API calls
        handleTaskStatusUpdated(shotId, taskType, newStatus)
      }
    })
    
    await Promise.all(updatePromises)
    
    // Show success toast
    toast({
      title: 'Bulk status update completed',
      description: `Updated ${taskType} status for ${selectedShotIds.length} shot${selectedShotIds.length === 1 ? '' : 's'}`,
    })
    
    // Keep selection active so users can perform additional bulk operations
    
  } catch (err) {
    toast({
      title: 'Bulk update failed',
      description: err instanceof Error ? err.message : 'An error occurred during bulk update',
      variant: 'destructive'
    })
  }
}

const editShot = (shot: Shot) => {
  selectedShot.value = shot
  showEditDialog.value = true
}

const deleteShot = async (shot: Shot) => {
  // Don't set selectedShot here as it opens the detail panel
  // Instead, store the shot reference separately
  shotToDelete.value = shot
  
  try {
    // Get deletion info first
    deletionInfo.value = await shotService.getShotDeletionInfo(shot.id)
    showDeleteDialog.value = true
  } catch (err) {
    toast({
      title: 'Failed to get shot information',
      description: err instanceof Error ? err.message : 'An error occurred',
      variant: 'destructive'
    })
  }
}



const handleCreateShot = async (shotData: ShotCreate | ShotUpdate) => {
  // Use the current episode filter or default to the first episode
  const targetEpisodeId = episodeFilter.value || episodes.value[0]?.id
  if (!targetEpisodeId) {
    toast({
      title: 'No episode selected',
      description: 'Please select an episode to create shots',
      variant: 'destructive'
    })
    return
  }

  try {
    isCreating.value = true
    validationError.value = null
    const newShot = await shotService.createShot(targetEpisodeId, shotData as ShotCreate)
    shots.value.push(newShot)
    showCreateDialog.value = false
    toast({
      title: 'Shot created',
      description: `${newShot.name} has been created successfully.`
    })
  } catch (err) {
    if (err instanceof Error && 'code' in err) {
      const validationErr = err as ProjectValidationError
      validationError.value = formatValidationError(validationErr)
    } else {
      toast({
        title: 'Failed to create shot',
        description: err instanceof Error ? err.message : 'An error occurred',
        variant: 'destructive'
      })
    }
  } finally {
    isCreating.value = false
  }
}

const handleBulkCreateShots = async (bulkData: BulkShotCreate) => {
  // Use the current episode filter or default to the first episode
  const targetEpisodeId = episodeFilter.value || episodes.value[0]?.id
  if (!targetEpisodeId) {
    toast({
      title: 'No episode selected',
      description: 'Please select an episode to create shots',
      variant: 'destructive'
    })
    return
  }

  try {
    isBulkCreating.value = true
    validationError.value = null
    const result = await shotService.bulkCreateShots(targetEpisodeId, bulkData)
    shots.value.push(...result.created_shots)
    showBulkCreateDialog.value = false
    toast({
      title: 'Shots created',
      description: result.message
    })
  } catch (err) {
    if (err instanceof Error && 'code' in err) {
      const validationErr = err as ProjectValidationError
      validationError.value = formatValidationError(validationErr, 'bulk')
    } else {
      toast({
        title: 'Failed to create shots',
        description: err instanceof Error ? err.message : 'An error occurred',
        variant: 'destructive'
      })
    }
  } finally {
    isBulkCreating.value = false
  }
}

const handleUpdateShot = async (shotData: ShotCreate | ShotUpdate) => {
  if (!selectedShot.value) return

  try {
    isUpdating.value = true
    validationError.value = null
    const updatedShot = await shotService.updateShot(selectedShot.value.id, shotData as ShotUpdate)
    
    // Update in shots list
    const index = shots.value.findIndex(shot => shot.id === selectedShot.value!.id)
    if (index !== -1) {
      shots.value[index] = updatedShot
    }
    
    showEditDialog.value = false
    selectedShot.value = null
    toast({
      title: 'Shot updated',
      description: 'Shot has been updated successfully.'
    })
  } catch (err) {
    if (err instanceof Error && 'code' in err) {
      const validationErr = err as ProjectValidationError
      validationError.value = formatValidationError(validationErr)
    } else {
      toast({
        title: 'Failed to update shot',
        description: err instanceof Error ? err.message : 'An error occurred',
        variant: 'destructive'
      })
    }
  } finally {
    isUpdating.value = false
  }
}

const handleDeleteShot = async () => {
  if (!shotToDelete.value) return

  try {
    // Delete shot (soft deletion by default)
    await shotService.deleteShot(shotToDelete.value.id)
    
    // Remove from shots list
    const index = shots.value.findIndex(shot => shot.id === shotToDelete.value!.id)
    if (index !== -1) {
      shots.value.splice(index, 1)
    }
    
    showDeleteDialog.value = false
    showMobileDetail.value = false
    shotToDelete.value = null
    
    const taskCount = deletionInfo.value?.task_count || 0
    deletionInfo.value = null
    toast({
      title: 'Shot deleted',
      description: taskCount > 0 
        ? `Shot and ${taskCount} associated task${taskCount === 1 ? '' : 's'} deleted successfully.`
        : 'Shot deleted successfully.'
    })
  } catch (err) {
    toast({
      title: 'Failed to delete shot',
      description: err instanceof Error ? err.message : 'An error occurred',
      variant: 'destructive'
    })
  }
}

const clearSearch = () => {
  // This will be handled by the parent component
  // For now, just reload shots to clear any filters
  loadShots()
}

const handleCreateTask = () => {
  // TODO: Navigate to task creation for this shot
  console.log('Create task for shot:', selectedShot.value?.name)
}

const handleSelectTask = (task: any) => {
  // TODO: Navigate to task detail view
  console.log('View task:', task.name)
}

const formatStatus = (status: ShotStatus) => {
  return status.split('_').map(word => 
    word.charAt(0).toUpperCase() + word.slice(1)
  ).join(' ')
}

const getStatusVariant = (status: ShotStatus) => {
  switch (status) {
    case ShotStatus.NOT_STARTED:
      return 'secondary'
    case ShotStatus.IN_PROGRESS:
      return 'default'
    case ShotStatus.ON_HOLD:
      return 'outline'
    case ShotStatus.COMPLETED:
      return 'default'
    case ShotStatus.APPROVED:
      return 'default'
    default:
      return 'secondary'
  }
}

// Memoized shot columns - use shallowRef to avoid deep reactivity on column objects
const shotColumns = shallowRef<ReturnType<typeof createShotColumns>>([])

// Create a stable reference to the meta object to prevent unnecessary column recreation
const createStableMeta = (): ShotColumnMeta => ({
  projectId: props.projectId,
  episodes: episodes.value,
  onEdit: editShot,
  onDelete: deleteShot,
  onViewTasks: viewTasks,
  onTaskStatusUpdated: handleTaskStatusUpdated,
  onTaskAssignmentUpdated: handleTaskAssignmentUpdated,
  onBulkTaskStatusChange: handleBulkTaskStatusChange,
  getSelectedCount: getSelectedCount,
  getAllStatusOptions: () => taskStatusesStore.getAllStatusOptions(props.projectId),
})

// Update columns only when dependencies actually change
const updateColumns = () => {
  const meta = createStableMeta()
  // Use markRaw to prevent deep reactivity on column definitions
  shotColumns.value = markRaw(createShotColumns(allTaskTypes.value, meta))
}

// Watchers
watch(() => props.selectedEpisodeId, (newEpisodeId) => {
  // Set the episode filter based on the selected episode from parent
  episodeFilter.value = newEpisodeId ?? null
}, { immediate: true })

watch(() => props.projectId, (newProjectId) => {
  if (newProjectId) {
    loadProjectContext()
    loadEpisodes()
    loadTaskTypes()
    loadTaskStatuses()
    loadShots()
  }
}, { immediate: true })

// Clear validation errors when dialogs are closed
watch(() => showCreateDialog.value, (isOpen) => {
  if (!isOpen) {
    validationError.value = null
  }
})

watch(() => showBulkCreateDialog.value, (isOpen) => {
  if (!isOpen) {
    validationError.value = null
  }
})

watch(() => showEditDialog.value, (isOpen) => {
  if (!isOpen) {
    validationError.value = null
  }
})

// Watch for changes that require column recreation (after all functions are defined)
watch([() => allTaskTypes.value, () => episodes.value, () => props.projectId], updateColumns, { immediate: true })

// Watch for changes from global column visibility store
watch(() => columnVisibilityStore.visibility, (newVisibility) => {
  // Only update if the change didn't come from this component
  if (JSON.stringify(newVisibility) !== JSON.stringify(columnVisibility.value)) {
    columnVisibility.value = newVisibility
  }
}, { deep: true })
</script>