<template>
  <div class="crud-datatable">
    <Card>
      <template #content>
        <!-- Header mit Buttons -->
        <div class="flex justify-between items-center mb-4">
          <div class="font-semibold text-xl">{{ title }}</div>
          <div class="flex gap-2">
            <Button 
              v-if="enableColumnConfig"
              label="Spalten anpassen" 
              icon="pi pi-cog" 
              outlined
              @click="columnConfigDialog = true" 
            />
            <slot name="header-actions">
              <Button 
                :label="createLabel" 
                icon="pi pi-plus" 
                @click="$emit('create')" 
              />
            </slot>
          </div>
        </div>

        <!-- Optional: Custom Filter Buttons -->
        <slot name="filter-buttons" :load-data="loadData"></slot>

        <!-- DataTable -->
        <DataTable
          v-model:filters="internalFilters"
          :value="data"
          :loading="loading"
          v-bind="mergedTableProps"
          filterDisplay="menu"
        >
          <!-- Header mit Globaler Suche -->
          <template #header>
            <div class="flex justify-between flex-wrap gap-2">
              <slot name="filter-row"></slot>
              <IconField>
                <InputIcon><i class="pi pi-search" /></InputIcon>
                <InputText
                  v-model="internalFilters['global'].value"
                  placeholder="Suchen..."
                />
              </IconField>
            </div>
          </template>

          <!-- Dynamische Spalten basierend auf Config -->
          <template v-for="column in visibleColumnsOrdered" :key="column.key">
            <Column
              :field="column.field || column.key"
              :header="column.label"
              :sortable="column.sortable !== false"
              :style="column.style"
              :dataType="column.dataType"
              :showFilterMatchModes="column.showFilterMatchModes !== false"
              :showFilterOperator="column.showFilterOperator !== false"
            >
              <!-- Custom Body Template (via Slot) -->
              <template v-if="$slots[`body-${column.key}`]" #body="slotProps">
                <slot :name="`body-${column.key}`" v-bind="slotProps" />
              </template>

              <!-- Default Body Template -->
              <template v-else #body="{ data }">
                {{ getNestedValue(data, column.field || column.key) }}
              </template>

              <!-- Custom Filter Template -->
              <template v-if="column.filterable !== false" #filter="{ filterModel }">
                <slot :name="`filter-${column.key}`" :filterModel="filterModel">
                  <InputText 
                    v-model="filterModel.value" 
                    type="text" 
                    :placeholder="'Suche nach ' + column.label"
                  />
                </slot>
              </template>
            </Column>
          </template>

          <!-- Actions Column (immer sichtbar) -->
          <Column :exportable="false" style="min-width: 120px" header="Aktionen">
            <template #body="slotProps">
              <slot name="actions" v-bind="slotProps">
                <div class="flex gap-2">
                  <Button
                    v-if="showViewButton"
                    icon="pi pi-eye"
                    outlined
                    rounded
                    @click="$emit('view', slotProps.data)"
                    size="small"
                    severity="secondary"
                  />
                  <Button
                    v-if="showEditButton"
                    icon="pi pi-pencil"
                    outlined
                    rounded
                    @click="$emit('edit', slotProps.data)"
                    size="small"
                  />
                  <Button
                    v-if="showDeleteButton"
                    icon="pi pi-trash"
                    outlined
                    rounded
                    severity="danger"
                    @click="$emit('delete', slotProps.data)"
                    size="small"
                  />
                </div>
              </slot>
            </template>
          </Column>

          <template #empty>{{ emptyMessage }}</template>
          <template #loading>Lädt Daten. Bitte warten...</template>
        </DataTable>
      </template>
    </Card>

    <!-- Column Config Dialog (wiederverwendbar) -->
    <ColumnConfigDialog
      v-model:visible="columnConfigDialog"
      v-model:columns="availableColumns"
      v-model:visible-columns="visibleColumns"
      @save="saveColumnConfig"
    />
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { useToast } from 'primevue/usetoast'
import { FilterMatchMode, FilterOperator } from '@primevue/core/api'
import DataTable from 'primevue/datatable'
import Column from 'primevue/column'
import Button from 'primevue/button'
import InputText from 'primevue/inputtext'
import Card from 'primevue/card'
import IconField from 'primevue/iconfield'
import InputIcon from 'primevue/inputicon'
import ColumnConfigDialog from './ColumnConfigDialog.vue'

const props = defineProps({
  title: { 
    type: String, 
    required: true 
  },
  entityName: { 
    type: String, 
    default: '' 
  },
  columns: { 
    type: Array, 
    required: true 
  },
  dataSource: { 
    type: String, 
    required: true 
  },
  storageKey: { 
    type: String, 
    required: true 
  },
  enableColumnConfig: { 
    type: Boolean, 
    default: true 
  },
  showViewButton: {
    type: Boolean,
    default: false
  },
  showEditButton: {
    type: Boolean,
    default: true
  },
  showDeleteButton: {
    type: Boolean,
    default: true
  },
  emptyMessage: { 
    type: String, 
    default: 'Keine Daten gefunden.' 
  },
  tableProps: { 
    type: Object, 
    default: () => ({}) 
  }
})

const emit = defineEmits(['create', 'edit', 'delete', 'view', 'data-loaded'])

const toast = useToast()
const data = ref([])
const loading = ref(false)
const columnConfigDialog = ref(false)

// Computed create button label
const createLabel = computed(() => {
  if (props.entityName) {
    return `Neue${props.entityName.endsWith('e') ? 'r' : 'n'} ${props.entityName}`
  }
  return 'Neu'
})

// Default table props
const defaultTableProps = {
  paginator: true,
  rows: 10,
  rowsPerPageOptions: [10, 25, 50, 100],
  rowHover: true,
  showGridlines: true,
  scrollable: true,
  scrollHeight: 'flex',
  paginatorTemplate: 'FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown',
  currentPageReportTemplate: 'Zeige {first} bis {last} von {totalRecords} Einträgen'
}

// Merge user props with defaults
const mergedTableProps = computed(() => ({
  ...defaultTableProps,
  ...props.tableProps
}))

// Column Management
const availableColumns = ref([])
const visibleColumns = ref({})

const visibleColumnsOrdered = computed(() => 
  availableColumns.value.filter(col => visibleColumns.value[col.key])
)

// Filter Setup
const internalFilters = ref({
  global: { value: null, matchMode: FilterMatchMode.CONTAINS }
})

// Helper function to get nested object values
function getNestedValue(obj, path) {
  return path.split('.').reduce((current, prop) => current?.[prop], obj)
}

function loadColumnConfig() {
  const saved = localStorage.getItem(props.storageKey)
  if (saved) {
    const config = JSON.parse(saved)
    
    // Handle both old and new format
    if (config.visibility) {
      // Apply saved order
      if (config.order) {
        const ordered = []
        config.order.forEach(key => {
          const col = props.columns.find(c => c.key === key)
          if (col) ordered.push(col)
        })
        // Add new columns not in saved order
        props.columns.forEach(col => {
          if (!ordered.find(c => c.key === col.key)) {
            ordered.push(col)
          }
        })
        availableColumns.value = ordered
      } else {
        availableColumns.value = [...props.columns]
      }
      return config.visibility
    } else {
      // Old format - just visibility object
      availableColumns.value = [...props.columns]
      return config
    }
  }
  
  // Default: Use column defaults
  availableColumns.value = [...props.columns]
  return props.columns.reduce((acc, col) => {
    acc[col.key] = col.default !== false
    return acc
  }, {})
}

function saveColumnConfig() {
  const config = {
    visibility: visibleColumns.value,
    order: availableColumns.value.map(col => col.key)
  }
  localStorage.setItem(props.storageKey, JSON.stringify(config))
  columnConfigDialog.value = false
  
  toast.add({
    severity: 'success',
    summary: 'Gespeichert',
    detail: 'Spaltenkonfiguration wurde gespeichert',
    life: 3000
  })
}

async function loadData(params = {}) {
  loading.value = true
  try {
    const url = new URL(props.dataSource, window.location.origin)
    url.searchParams.append('itemsPerPage', '5000')
    
    // Add custom params
    Object.entries(params).forEach(([key, value]) => {
      if (value !== null && value !== undefined) {
        url.searchParams.append(key, value)
      }
    })
    
    const response = await fetch(url, { 
      credentials: 'include',
      headers: {
        'Accept': 'application/ld+json'
      }
    })
    
    if (!response.ok) {
      const error = await response.json()
      throw new Error(error['hydra:description'] || 'Fehler beim Laden der Daten')
    }
    
    const json = await response.json()
    data.value = json['hydra:member'] || json.member || json
    emit('data-loaded', data.value)
  } catch (error) {
    console.error('Error loading data:', error)
    toast.add({
      severity: 'error',
      summary: 'Fehler',
      detail: error.message || 'Daten konnten nicht geladen werden',
      life: 3000
    })
  } finally {
    loading.value = false
  }
}

// Initialize
onMounted(() => {
  visibleColumns.value = loadColumnConfig()
  
  // Initialize column-specific filters with operator structure for menu mode
  props.columns.forEach(col => {
    if (col.filterable !== false) {
      internalFilters.value[col.key] = {
        operator: FilterOperator.AND,
        constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }]
      }
    }
  })
  
  // Auto-load data
  loadData()
})

// Expose loadData for parent component
defineExpose({ loadData })
</script>
