<template>
  <div class="space-y-4 px-4">
    <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"
              v-show="header.column.getIsVisible()"
              :class="[
                header.column.getCanSort() ? 'cursor-pointer select-none hover:bg-muted/50' : '',
                header.column.id === 'select' ? 'w-12' : '',
                header.column.id === 'actions' ? 'w-12' : '',
                allTaskTypes.includes(header.column.id) ? 'w-[140px]' : '',
              ]"
              @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 in table.getRowModel().rows"
              :key="row.id"
              :data-state="row.getIsSelected() ? 'selected' : undefined"
              class="cursor-pointer hover:bg-muted/50"
              :class="{ 
                'bg-muted/30': row.getIsSelected(),
                'table-row-selectable': true,
                'selecting': isRangeSelecting
              }"
              @click="handleRowClick(row.original, $event, row)"
              @mousedown="handleMouseDown"
              @mouseup="handleMouseUp"
            >
              <TableCell
                v-for="cell in row.getAllCells()"
                :key="cell.id"
                v-show="cell.column.getIsVisible()"
                v-memo="[cell.getValue(), cell.column.getIsVisible()]"
              >
                <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">
                No results.
              </TableCell>
            </TableRow>
          </template>
        </TableBody>
      </Table>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue'
import {
  FlexRender,
  getCoreRowModel,
  getSortedRowModel,
  useVueTable,
  type ColumnDef,
  type SortingState,
  type VisibilityState,
} from '@tanstack/vue-table'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import { type Asset } from '@/services/asset'

interface Props {
  columns: ColumnDef<Asset>[]
  data: Asset[]
  sorting: SortingState
  columnVisibility: VisibilityState
  allTaskTypes: string[]
}

const props = defineProps<Props>()

const emit = defineEmits<{
  'update:sorting': [sorting: SortingState]
  'update:columnVisibility': [visibility: VisibilityState]
  'update:rowSelection': [selection: Record<string, boolean>]
  'row-click': [asset: Asset, event: MouseEvent]
  'selection-cleared': []
}>()

// Track the last selected row index for range selection
const lastSelectedIndex = ref<number | null>(null)
const isRangeSelecting = ref(false)
const rowSelection = ref<Record<string, boolean>>({})

const table = useVueTable({
  get data() {
    return props.data
  },
  get columns() {
    return props.columns
  },
  getCoreRowModel: getCoreRowModel(),
  getSortedRowModel: getSortedRowModel(),
  enableRowSelection: true,
  enableMultiRowSelection: true,
  getRowId: (row) => String(row.id),
  onSortingChange: (updaterOrValue) => {
    const newSorting =
      typeof updaterOrValue === 'function'
        ? updaterOrValue(props.sorting)
        : updaterOrValue
    emit('update:sorting', newSorting)
  },
  onColumnVisibilityChange: (updaterOrValue) => {
    const newVisibility =
      typeof updaterOrValue === 'function'
        ? updaterOrValue(props.columnVisibility)
        : updaterOrValue
    emit('update:columnVisibility', newVisibility)
  },
  // Re-add the onRowSelectionChange callback but make it work with our custom logic
  onRowSelectionChange: (updaterOrValue) => {
    const newSelection =
      typeof updaterOrValue === 'function'
        ? updaterOrValue(rowSelection.value)
        : updaterOrValue
    rowSelection.value = newSelection
  },
  state: {
    get sorting() {
      return props.sorting
    },
    get columnVisibility() {
      return props.columnVisibility
    },
    get rowSelection() {
      return rowSelection.value
    },
  },
})

const handleRowClick = (asset: Asset, event: MouseEvent, row: any) => {
  // If double-click handler will handle it, skip selection logic
  if (event.detail === 2) {
    return
  }

  // Check if we clicked on an interactive element (simplified check)
  const target = event.target as HTMLElement
  if (target) {
    // Check if we clicked on a button, checkbox, or other interactive element
    const interactiveElement = target.closest('button, input, select, textarea, a[href], [role="button"], [role="menuitem"]')
    if (interactiveElement) {
      return
    }
  }

  // Handle selection based on modifier keys
  handleRowSelection(row, event)
  emit('row-click', asset, event)
}

const handleRowSelection = (row: any, event: MouseEvent) => {
  const currentIndex = row.index
  const allRows = table.getRowModel().rows
  const assetId = String(row.id)
  
  if (event.shiftKey && lastSelectedIndex.value !== null) {
    // Prevent text selection when shift-clicking
    event.preventDefault()
    
    // Range selection
    const startIndex = Math.min(lastSelectedIndex.value, currentIndex)
    const endIndex = Math.max(lastSelectedIndex.value, currentIndex)
    
    // Create new selection object
    const newSelection: Record<string, boolean> = {}
    
    // Select all rows in the range
    for (let i = startIndex; i <= endIndex; i++) {
      if (allRows[i]) {
        newSelection[allRows[i].id] = true
      }
    }
    
    rowSelection.value = newSelection
    lastSelectedIndex.value = currentIndex
  } else if (event.ctrlKey || event.metaKey) {
    // Ctrl/Cmd + Click: Toggle individual selection (additional selection)
    const newSelection: Record<string, boolean> = { ...rowSelection.value }
    
    if (newSelection[assetId]) {
      // Row is selected, deselect it
      delete newSelection[assetId]
    } else {
      // Row is not selected, select it
      newSelection[assetId] = true
    }
    
    rowSelection.value = newSelection
    lastSelectedIndex.value = currentIndex
  } else {
    // Default: Single selection (clear others and select this one)
    // This applies even if the row is already selected - it becomes the only selection
    rowSelection.value = { [assetId]: true }
    lastSelectedIndex.value = currentIndex
  }
}

const handleMouseDown = (event: MouseEvent) => {
  // Detect if this is a range selection operation
  if (event.shiftKey) {
    isRangeSelecting.value = true
    // Prevent text selection immediately
    event.preventDefault()
  }
}

const handleMouseUp = () => {
  // Reset range selecting state
  isRangeSelecting.value = false
}

// Watch rowSelection changes and emit selection-change events
watch(
  rowSelection,
  (newSelection) => {
    emit('update:rowSelection', newSelection)
  },
  { deep: true }
)
</script>

<style scoped>
/* Prevent text selection during range selection */
.table-row-selectable.selecting {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

/* Prevent text selection on shift key operations */
.table-row-selectable {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

/* Allow text selection for specific elements that should be selectable */
.table-row-selectable input,
.table-row-selectable textarea,
.table-row-selectable [contenteditable] {
  -webkit-user-select: text;
  -moz-user-select: text;
  -ms-user-select: text;
  user-select: text;
}
</style>