<template>
  <div class="rounded-md border">
    <Table>
      <TableHeader>
        <TableRow v-for="headerGroup in table.getHeaderGroups()" :key="headerGroup.id">
          <TableHead
            v-for="header in headerGroup.headers"
            :key="header.id"
            :class="[
              header.column.getCanSort() ? 'cursor-pointer select-none hover:bg-muted/50' : '',
              header.column.id === 'select' ? 'w-12' : '',
            ]"
            @click="header.column.getCanSort() ? header.column.toggleSorting() : null"
          >
            <FlexRender
              v-if="!header.isPlaceholder"
              :render="header.column.columnDef.header"
              :props="header.getContext()"
            />
          </TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        <template v-if="table.getRowModel().rows?.length">
          <TableRow
            v-for="(row, index) in table.getRowModel().rows"
            :key="row.id"
            :data-task-id="row.original.id"
            :data-state="row.getIsSelected() ? 'selected' : undefined"
            :class="[
              'cursor-pointer hover:bg-muted/50 select-none',
              row.getIsSelected() ? 'bg-muted/50' : ''
            ]"
            @click="handleRowClick(row.original, $event, index)"
            @dblclick="handleRowDoubleClick(row.original)"
            @contextmenu="handleContextMenu($event, index)"
          >
            <TableCell
              v-for="cell in row.getVisibleCells()"
              :key="cell.id"
            >
              <FlexRender
                :render="cell.column.columnDef.cell"
                :props="cell.getContext()"
              />
            </TableCell>
          </TableRow>
        </template>
        <template v-else>
          <TableRow>
            <TableCell :colspan="columns.length" class="h-24 text-center">
              <div class="flex flex-col items-center justify-center gap-2">
                <ListTodo class="h-8 w-8 text-muted-foreground" />
                <p class="text-sm text-muted-foreground">
                  No tasks found
                </p>
              </div>
            </TableCell>
          </TableRow>
        </template>
      </TableBody>
    </Table>
  </div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue'
import {
  FlexRender,
  getCoreRowModel,
  getSortedRowModel,
  useVueTable,
  type SortingState,
  type VisibilityState,
  type RowSelectionState,
} from '@tanstack/vue-table'
import { ListTodo } from 'lucide-vue-next'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import { createColumns } from './columns'
import { type Task } from '@/services/task'
import { TaskStatus } from '@/services/asset'

// Props interface
interface Props {
  tasks: Task[]
  columnVisibility: VisibilityState
  projectId: number
  isLoading?: boolean
}

const props = defineProps<Props>()

// Emits interface
interface Emits {
  (e: 'row-click', task: Task): void
  (e: 'row-double-click', task: Task): void
  (e: 'context-menu', event: MouseEvent, tasks: Task[]): void
  (e: 'selection-change', taskIds: number[]): void
  (e: 'update:column-visibility', visibility: VisibilityState): void
  (e: 'bulk-status-change', taskIds: number[], newStatus: TaskStatus): void
  (e: 'status-updated', taskId: number, newStatus: TaskStatus): void
}

const emit = defineEmits<Emits>()

// Internal state
const sorting = ref<SortingState>([{ id: 'created_at', desc: true }])
const rowSelection = ref<RowSelectionState>({})
const lastClickedIndex = ref<number | null>(null)

// Bulk status change handler
const handleBulkStatusChange = async (newStatus: TaskStatus) => {
  const selectedTasks = getSelectedTasks()
  if (selectedTasks.length === 0) return
  
  // Emit event for parent to handle
  emit('bulk-status-change', selectedTasks.map(t => t.id), newStatus)
}

// Status update handler
const handleStatusUpdated = (taskId: number, newStatus: TaskStatus) => {
  emit('status-updated', taskId, newStatus)
}

// Columns with callbacks
const columns = createColumns({
  onBulkStatusChange: handleBulkStatusChange,
  onStatusUpdated: handleStatusUpdated,
  getSelectedCount: () => Object.keys(rowSelection.value).filter(key => rowSelection.value[key]).length,
})

// TanStack Table configuration
const table = useVueTable({
  get data() {
    return props.tasks
  },
  get columns() {
    return columns
  },
  getCoreRowModel: getCoreRowModel(),
  getSortedRowModel: getSortedRowModel(),
  enableRowSelection: true,
  enableMultiRowSelection: true,
  getRowId: (row) => String(row.id),
  onSortingChange: (updaterOrValue) => {
    sorting.value =
      typeof updaterOrValue === 'function' ? updaterOrValue(sorting.value) : updaterOrValue
  },
  onColumnVisibilityChange: (updaterOrValue) => {
    const newVisibility =
      typeof updaterOrValue === 'function'
        ? updaterOrValue(props.columnVisibility)
        : updaterOrValue
    emit('update:column-visibility', newVisibility)
  },
  onRowSelectionChange: (updaterOrValue) => {
    rowSelection.value =
      typeof updaterOrValue === 'function'
        ? updaterOrValue(rowSelection.value)
        : updaterOrValue
  },
  state: {
    get sorting() {
      return sorting.value
    },
    get columnVisibility() {
      return props.columnVisibility
    },
    get rowSelection() {
      return rowSelection.value
    },
  },
})

// Watch rowSelection changes and emit selection-change events
watch(
  rowSelection,
  (newSelection) => {
    const selectedIds = Object.keys(newSelection)
      .filter(key => newSelection[key])
      .map(key => parseInt(key))
    emit('selection-change', selectedIds)
  },
  { deep: true }
)

// Helper function to compute selected tasks from selection state
const getSelectedTasks = (): Task[] => {
  const selectedIds = Object.keys(rowSelection.value).filter(key => rowSelection.value[key])
  return props.tasks.filter(task => selectedIds.includes(String(task.id)))
}

// Event handlers
const handleRowClick = (task: Task, event: MouseEvent, index: number) => {
  // If double-click handler will handle it, skip selection logic
  if (event.detail === 2) {
    return
  }

  const taskId = String(task.id)

  if (event.shiftKey && lastClickedIndex.value !== null) {
    // Shift+Click: Range selection
    const start = Math.min(lastClickedIndex.value, index)
    const end = Math.max(lastClickedIndex.value, index)
    const newSelection: Record<string, boolean> = {}

    for (let i = start; i <= end; i++) {
      const id = String(props.tasks[i].id)
      newSelection[id] = true
    }

    // Update rowSelection - create completely new object to trigger reactivity
    rowSelection.value = newSelection
    console.log('Shift-click selection updated:', rowSelection.value)
    lastClickedIndex.value = index
  } else if (event.ctrlKey || event.metaKey) {
    // Ctrl/Cmd+Click: Toggle selection
    const newSelection = { ...rowSelection.value }
    if (newSelection[taskId]) {
      delete newSelection[taskId]
    } else {
      newSelection[taskId] = true
    }
    rowSelection.value = newSelection
    lastClickedIndex.value = index
  } else {
    // Regular click: Select only this row
    rowSelection.value = { [taskId]: true }
    lastClickedIndex.value = index
  }

  // Emit row-click event (selection-change is emitted by watcher)
  emit('row-click', task)
}

const handleRowDoubleClick = (task: Task) => {
  emit('row-double-click', task)
}

const handleContextMenu = (event: MouseEvent, index: number) => {
  event.preventDefault()

  // Prevent context menu on empty table areas
  if (props.tasks.length === 0) {
    return
  }

  const rightClickedTask = props.tasks[index]
  if (!rightClickedTask) return

  const taskId = String(rightClickedTask.id)

  // If right-clicked row is not selected, add it to selection
  // If it's already selected, keep current selection
  if (!rowSelection.value[taskId]) {
    const newSelection = { ...rowSelection.value }
    newSelection[taskId] = true
    rowSelection.value = newSelection
  }

  // Get currently selected tasks
  const selectedTasks = getSelectedTasks()

  // Emit context-menu event with selected tasks
  emit('context-menu', event, selectedTasks)
}
</script>
