<template>
  <div class="relative h-full">
    <!-- Main Content -->
    <div class="space-y-4">
    <!-- Toolbar - Sticky -->
    <div class="sticky top-0 z-10 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">
        <TaskTableToolbar
        v-model:status-filter="statusFilter"
        v-model:type-filter="typeFilter"
        v-model:episode-filter="episodeFilter"
        v-model:assignee-filter="assigneeFilter"
        v-model:context-filter="contextFilter"
        v-model:search="searchQuery"
        v-model:my-tasks-filter="myTasksFilter"
        :column-visibility="columnVisibility"
        :episodes="episodes"
        :assignees="assignees"
        :task-types="taskTypes"
        :current-user-id="currentUserId"
        :is-detail-panel-enabled="isDetailPanelEnabled"
        @update:column-visibility="updateColumnVisibility"
        @toggle-detail-panel="toggleDetailPanelEnabled"
      />
    </div>

    <!-- Task Count / Selection Count -->
    <div class="flex items-center justify-between px-4 sm:px-6">
      <div class="text-sm text-muted-foreground">
        <span v-if="selectedCount > 0" class="font-medium text-foreground">
          {{ selectedCount }} {{ selectedCount === 1 ? 'task' : 'tasks' }} selected
        </span>
        <span v-else-if="filteredTasks.length === tasks.length">
          {{ tasks.length }} {{ tasks.length === 1 ? 'task' : 'tasks' }}
        </span>
        <span v-else>
          {{ filteredTasks.length }} of {{ tasks.length }} {{ tasks.length === 1 ? 'task' : 'tasks' }}
        </span>
      </div>
    </div>

    <!-- Data Table -->
    <TasksDataTable
      :tasks="filteredTasks"
      :column-visibility="columnVisibility"
      :project-id="projectId"
      :is-loading="isLoading"
      @row-click="handleRowClick"
      @row-double-click="handleRowDoubleClick"
      @context-menu="handleContextMenu"
      @selection-change="handleSelectionChange"
      @update:column-visibility="updateColumnVisibility"
      @status-updated="handleStatusUpdated"
      @bulk-status-change="(_, status) => handleBulkStatusUpdate(status)"
    />
    </div>

    <!-- Task Detail Panel - Desktop (Fixed Right Side) -->
    <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"
        class="fixed right-0 top-[113px] bottom-0 w-96 bg-background border-l shadow-lg z-50 hidden lg:block overflow-y-auto"
      >
        <TaskDetailPanel
          v-if="selectedTask"
          :task-id="selectedTask?.id || 0"
          :is-open="true"
          @close="closeDetailPanel"
          @task-updated="handleTaskUpdated"
        />
      </div>
    </Transition>

    <!-- Task Detail Panel - Mobile (Sheet) -->
    <Sheet v-model:open="showMobileDetail">
      <SheetContent side="right" class="w-full sm:max-w-md p-0">
        <TaskDetailPanel
          v-if="selectedTask"
          :task-id="selectedTask?.id || 0"
          :is-open="true"
          @close="closeDetailPanel"
          @task-updated="handleTaskUpdated"
        />
      </SheetContent>
    </Sheet>

    <!-- Context Menu for Bulk Actions -->
    <TaskBulkActionsMenu
      v-model:open="showContextMenu"
      :position="contextMenuPosition"
      :selected-count="selectedCount"
      :selected-tasks="selectedTasks"
      :project-members="projectMembers"
      @status-selected="handleBulkStatusUpdate"
      @assignee-selected="handleBulkAssignment"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
import type { VisibilityState } from '@tanstack/vue-table'
import { Sheet, SheetContent } from '@/components/ui/sheet'
import { useToast } from '@/components/ui/toast/use-toast'
import TaskTableToolbar from './TaskTableToolbar.vue'
import TaskDetailPanel from './TaskDetailPanel.vue'
import TaskBulkActionsMenu from './TaskBulkActionsMenu.vue'
import TasksDataTable from './TasksDataTable.vue'
import { type Task } from '@/services/task'
import { taskService } from '@/services/task'
import { TaskStatus } from '@/services/asset'
import { episodeService, type Episode } from '@/services/episode'
import { projectService, type ProjectMember } from '@/services/project'
import { shotService, type Shot } from '@/services/shot'
import { assetService, type Asset } from '@/services/asset'
import { useAuthStore } from '@/stores/auth'
import { useDetailPanel } from '@/composables/useDetailPanel'

interface Props {
  projectId: number
}

const props = defineProps<Props>()

const { toast } = useToast()
const authStore = useAuthStore()

// Detail panel composable
const {
  isDetailPanelEnabled,
  isDetailPanelVisible,
  selectedEntity: selectedTask,
  showMobileDetail,
  showPanel,
  toggleDetailPanelEnabled,
  closeDetailPanel,
  selectEntity: selectTask,
  handleRowClick: handleRowClickComposable
} = useDetailPanel<Task>({
  isDialogOpen: () => showContextMenu.value,
  sessionStorageKey: 'taskBrowser.detailPanelEnabled'
})

// State
const tasks = ref<Task[]>([])
const episodes = ref<Episode[]>([])
const projectMembers = ref<ProjectMember[]>([])
const isLoading = ref(false)

// Context menu state
const showContextMenu = ref(false)
const contextMenuPosition = ref({ x: 0, y: 0 })

// Filters
const statusFilter = ref<string[]>([])
const typeFilter = ref<string[]>([])
const episodeFilter = ref<number | null>(null)
const assigneeFilter = ref<number[]>([])
const contextFilter = ref<'all' | 'shots' | 'assets'>('all')
const searchQuery = ref('')
const myTasksFilter = ref(false)

// Table state
const columnVisibility = ref<VisibilityState>({})

// Selection state - using Set for efficient lookups
const selectedTaskIds = ref<Set<number>>(new Set())

// Computed
const currentUserId = computed(() => authStore.user?.id || null)

const assignees = computed(() => {
  const uniqueAssignees = new Map<number, { id: number; name: string }>()
  tasks.value.forEach((task) => {
    if (task.assigned_user_id && task.assigned_user_name) {
      uniqueAssignees.set(task.assigned_user_id, {
        id: task.assigned_user_id,
        name: task.assigned_user_name,
      })
    }
  })
  return Array.from(uniqueAssignees.values())
})

const taskTypes = computed(() => {
  const types = new Set<string>()
  tasks.value.forEach((task) => types.add(task.task_type))
  return Array.from(types).sort()
})

// Selection computed properties (Requirement 2.5)
const selectedTasks = computed(() => {
  return filteredTasks.value.filter(task => selectedTaskIds.value.has(task.id))
})

const selectedCount = computed(() => selectedTaskIds.value.size)

const filteredTasks = computed(() => {
  let filtered = tasks.value

  // Search filter
  if (searchQuery.value) {
    const query = searchQuery.value.toLowerCase()
    filtered = filtered.filter(
      (task) =>
        task.name.toLowerCase().includes(query) ||
        task.description?.toLowerCase().includes(query) ||
        task.shot_name?.toLowerCase().includes(query) ||
        task.asset_name?.toLowerCase().includes(query)
    )
  }

  // Status filter
  if (statusFilter.value.length > 0) {
    filtered = filtered.filter((task) => statusFilter.value.includes(task.status))
  }

  // Type filter
  if (typeFilter.value.length > 0) {
    filtered = filtered.filter((task) => typeFilter.value.includes(task.task_type))
  }

  // Episode filter
  if (episodeFilter.value !== null) {
    filtered = filtered.filter((task) => task.episode_id === episodeFilter.value)
  }

  // Assignee filter
  if (assigneeFilter.value.length > 0) {
    filtered = filtered.filter((task) =>
      task.assigned_user_id ? assigneeFilter.value.includes(task.assigned_user_id) : false
    )
  }

  // Context filter
  if (contextFilter.value === 'shots') {
    filtered = filtered.filter((task) => task.shot_id !== null && task.shot_id !== undefined)
  } else if (contextFilter.value === 'assets') {
    filtered = filtered.filter((task) => task.asset_id !== null && task.asset_id !== undefined)
  }

  return filtered
})

// Methods
const fetchTasks = async () => {
  try {
    isLoading.value = true
    
    // Get both shots and assets with embedded task data (two optimized backend calls)
    const [shots, assets] = await Promise.all([
      shotService.getShots({ projectId: props.projectId }),
      assetService.getAssets(props.projectId)
    ])
    
    // Extract tasks from embedded data - no separate task API calls needed!
    const shotTasks = shots.flatMap(shot => 
      (shot.task_details || []).map(taskDetail => ({
        id: taskDetail.task_id || 0,
        name: `${shot.name} - ${taskDetail.task_type}`,
        description: `${taskDetail.task_type} task for shot ${shot.name}`,
        task_type: taskDetail.task_type,
        status: taskDetail.status,
        project_id: shot.project_id,
        project_name: shot.project_name,
        episode_id: shot.episode_id,
        shot_id: shot.id,
        shot_name: shot.name,
        assigned_user_id: taskDetail.assigned_user_id,
        assigned_user_name: undefined, // Will be populated from project members if needed
        assigned_user_email: undefined,
        created_at: shot.created_at,
        updated_at: shot.updated_at
      } as Task))
    )
    
    const assetTasks = assets.flatMap(asset => 
      (asset.task_details || []).map(taskDetail => ({
        id: taskDetail.task_id || 0,
        name: `${asset.name} - ${taskDetail.task_type}`,
        description: `${taskDetail.task_type} task for asset ${asset.name}`,
        task_type: taskDetail.task_type,
        status: taskDetail.status,
        project_id: asset.project_id,
        asset_id: asset.id,
        asset_name: asset.name,
        assigned_user_id: taskDetail.assigned_user_id,
        assigned_user_name: undefined, // Will be populated from project members if needed
        assigned_user_email: undefined,
        created_at: asset.created_at,
        updated_at: asset.updated_at
      } as Task))
    )
    
    // Combine all tasks from embedded data
    tasks.value = [...shotTasks, ...assetTasks]
  } catch (error) {
    console.error('Failed to fetch tasks:', error)
    toast({
      title: 'Error',
      description: 'Failed to load tasks',
      variant: 'destructive',
    })
  } finally {
    isLoading.value = false
  }
}

const fetchEpisodes = async () => {
  try {
    const response = await episodeService.getEpisodes(props.projectId)
    episodes.value = response
  } catch (error) {
    console.error('Failed to fetch episodes:', error)
  }
}

const fetchProjectMembers = async () => {
  try {
    const response = await projectService.getProjectMembers(props.projectId)
    projectMembers.value = response
  } catch (error) {
    console.error('Failed to fetch project members:', error)
  }
}

const handleRowClick = () => {
  // Row click is now handled by TasksDataTable and the composable
  // This handler can be used for additional logic if needed
}

const handleRowDoubleClick = (task: Task) => {
  selectTask(task)
  // Show mobile sheet on small screens if enabled
  if (isDetailPanelEnabled.value && window.innerWidth < 1024) {
    showMobileDetail.value = true
  }
  // Don't reset manual visibility when selecting a new task
}

const handleTaskUpdated = () => {
  fetchTasks()
}

// Status updated handler - for individual task status changes
const handleStatusUpdated = (taskId: number, newStatus: string) => {
  // Find and update the task in the array
  const taskIndex = tasks.value.findIndex((t) => t.id === taskId)
  if (taskIndex !== -1) {
    // Create a completely new array to trigger TanStack Table reactivity
    const updatedTasks = [...tasks.value]
    updatedTasks[taskIndex] = {
      ...updatedTasks[taskIndex],
      status: newStatus as TaskStatus,
    }
    tasks.value = updatedTasks
  }
}

// Selection change handler - receives selected task IDs from TasksDataTable
const handleSelectionChange = (taskIds: number[]) => {
  // Update selectedTaskIds Set with new selection
  selectedTaskIds.value = new Set(taskIds)
}

// Context menu handlers (Requirements 4.1, 4.2)
const handleContextMenu = (event: MouseEvent, _tasks: Task[]) => {
  // Selection is already handled by TasksDataTable
  // Just position and show the context menu
  contextMenuPosition.value = { x: event.clientX, y: event.clientY }
  showContextMenu.value = true
}

const closeContextMenu = () => {
  showContextMenu.value = false
}

// Bulk action handlers (Requirements 4.2, 4.3, 4.4, 4.5, 6.1, 6.3)
const handleBulkStatusUpdate = async (status: string) => {
  try {
    // Extract selected task IDs
    const taskIds = selectedTasks.value.map(task => task.id)
    
    if (taskIds.length === 0) {
      return
    }

    // Show loading state during operation
    isLoading.value = true

    // Call bulk update service
    const result = await taskService.bulkUpdateStatus(taskIds, status)

    // Display success toast with count of updated tasks
    toast({
      title: 'Success',
      description: `${result.success_count} ${result.success_count === 1 ? 'task' : 'tasks'} updated`,
    })

    // Refresh task list after successful update
    await fetchTasks()

    // Close context menu (keep selection)
    closeContextMenu()
  } catch (error) {
    // Handle errors and display error toast
    console.error('Failed to update task status:', error)
    toast({
      title: 'Error',
      description: 'Failed to update tasks. Please try again.',
      variant: 'destructive',
    })
  } finally {
    isLoading.value = false
  }
}

// Bulk assignment handler (Requirements 5.3, 5.4, 5.5, 5.6, 6.1, 6.3)
const handleBulkAssignment = async (userId: number) => {
  try {
    // Extract selected task IDs from selection state
    const taskIds = selectedTasks.value.map(task => task.id)
    
    if (taskIds.length === 0) {
      return
    }

    // Show loading state during operation
    isLoading.value = true

    // Call taskService.bulkAssignTasks with task IDs and user ID
    const result = await taskService.bulkAssignTasks(taskIds, userId)

    // Display success toast with count of assigned tasks
    toast({
      title: 'Success',
      description: `${result.success_count} ${result.success_count === 1 ? 'task' : 'tasks'} assigned`,
    })

    // Refresh task list after successful update
    await fetchTasks()

    // Close context menu (keep selection)
    closeContextMenu()
  } catch (error) {
    // Handle errors and display error toast
    console.error('Failed to assign tasks:', error)
    toast({
      title: 'Error',
      description: 'Failed to assign tasks. Please try again.',
      variant: 'destructive',
    })
  } finally {
    isLoading.value = false
  }
}

const updateColumnVisibility = (visibility: VisibilityState) => {
  columnVisibility.value = visibility
  // Persist to session storage
  sessionStorage.setItem(
    `tasks-table-column-visibility-${props.projectId}`,
    JSON.stringify(visibility)
  )
}

// Load column visibility from session storage
const loadColumnVisibility = () => {
  const saved = sessionStorage.getItem(`tasks-table-column-visibility-${props.projectId}`)
  if (saved) {
    try {
      columnVisibility.value = JSON.parse(saved)
    } catch (error) {
      console.error('Failed to parse saved column visibility:', error)
    }
  }
}

// Lifecycle
onMounted(() => {
  loadColumnVisibility()
  fetchTasks()
  fetchEpisodes()
  fetchProjectMembers()
})

onUnmounted(() => {
  // Cleanup handled by composable
})

// Watch for project changes
watch(
  () => props.projectId,
  () => {
    loadColumnVisibility()
    fetchTasks()
    fetchEpisodes()
    fetchProjectMembers()
  }
)

// Watch mobile sheet close
watch(showMobileDetail, (isOpen) => {
  if (!isOpen) {
    // Let the composable handle cleanup
  }
})

// Clear selection when filters change (Requirements 5.1, 5.2, 5.3, 5.4, 5.5)
watch([statusFilter, typeFilter, episodeFilter, assigneeFilter, contextFilter, searchQuery], () => {
  selectedTaskIds.value = new Set()
})
</script>
