<template>
  <div class="page-layout-editor">
    <div class="flex h-full">
      <!-- Main Grid Area -->
      <div class="flex-1 p-4 overflow-auto">
        <div class="mb-4 flex justify-between items-center">
          <h3 class="text-lg font-semibold">{{ layoutName || 'Page Layout' }}</h3>
          <div class="flex gap-2">
            <Button variant="outline" size="sm" @click="handleClear">
              Clear All
            </Button>
            <Button size="sm" @click="handleSave">
              Save Layout
            </Button>
          </div>
        </div>
        
        <div class="border rounded-lg bg-slate-50 dark:bg-slate-900 p-4 min-h-[600px]">
          <div 
            ref="gridContainer" 
            class="grid-stack"
            @dragover.prevent="handleDragOver"
            @drop="handleDrop"
          >
            <!-- Grid items will be dynamically added here -->
          </div>
        </div>
      </div>

      <!-- Available Fields Sidebar -->
      <div class="w-80 border-l bg-white dark:bg-slate-950 p-4 overflow-auto space-y-6">
        <div>
          <h3 class="text-lg font-semibold mb-4">Available Fields</h3>
          <p class="text-xs text-muted-foreground mb-4">Click or drag to add field to grid</p>
          <div class="space-y-2" id="sidebar-fields">
            <div
              v-for="field in availableFields"
              :key="field.id"
              class="p-3 border rounded cursor-move bg-white dark:bg-slate-900 hover:border-primary hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors"
              :data-field-id="field.id"
              draggable="true"
              @dragstart="handleDragStart($event, field)"
              @click="addFieldToGrid(field)"
            >
              <div class="font-medium text-sm">{{ field.label }}</div>
              <div class="text-xs text-muted-foreground">{{ field.apiName }}</div>
              <div class="text-xs text-muted-foreground">Type: {{ field.type }}</div>
            </div>
          </div>
        </div>

        <div v-if="relatedLists.length > 0">
          <h3 class="text-lg font-semibold mb-2">Related Lists</h3>
          <p class="text-xs text-muted-foreground mb-4">Select related lists to show on detail views</p>
          <div class="space-y-2">
            <label
              v-for="list in relatedLists"
              :key="list.relationName"
              class="flex items-center gap-2 text-sm"
            >
              <input
                type="checkbox"
                class="h-4 w-4"
                :value="list.relationName"
                v-model="selectedRelatedLists"
              />
              <span>{{ list.title }}</span>
            </label>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch, computed } from 'vue'
import { GridStack } from 'gridstack'
import 'gridstack/dist/gridstack.min.css'
import type { FieldLayoutItem } from '~/types/page-layout'
import type { FieldConfig, RelatedListConfig } from '~/types/field-types'
import { Button } from '@/components/ui/button'

const props = defineProps<{
  fields: FieldConfig[]
  relatedLists?: RelatedListConfig[]
  initialLayout?: FieldLayoutItem[]
  initialRelatedLists?: string[]
  layoutName?: string
}>()

const emit = defineEmits<{
  save: [layout: { fields: FieldLayoutItem[]; relatedLists: string[] }]
}>()

const gridContainer = ref<HTMLElement | null>(null)
let grid: GridStack | null = null
const gridItems = ref<Map<string, any>>(new Map())
const selectedRelatedLists = ref<string[]>(props.initialRelatedLists || [])

// Fields that are already on the grid
const placedFieldIds = ref<Set<string>>(new Set())

// Fields available to be added
const availableFields = computed(() => {
  return props.fields.filter(field => !placedFieldIds.value.has(field.id))
})

const relatedLists = computed(() => {
  return props.relatedLists || []
})

const initGrid = () => {
  if (!gridContainer.value) return

  grid = GridStack.init({
    column: 6,
    cellHeight: 80,
    minRow: 10,
    float: true,
    animate: true,
    acceptWidgets: true,
    disableOneColumnMode: true,
    resizable: {
      handles: 'e, w'
    }
  }, gridContainer.value)

  // Listen for changes
  grid.on('change', () => {
    updatePlacedFields()
  })

  // Listen for item removal
  grid.on('removed', (event, items) => {
    items.forEach(item => {
      const contentEl = item.el?.querySelector('.grid-stack-item-content')
      const fieldId = contentEl?.getAttribute('data-field-id')
      if (fieldId) {
        placedFieldIds.value.delete(fieldId)
        gridItems.value.delete(fieldId)
      }
    })
  })

  // Load initial layout if provided
  if (props.initialLayout && props.initialLayout.length > 0) {
    loadLayout(props.initialLayout)
  }
}

const loadLayout = (layout: FieldLayoutItem[]) => {
  if (!grid) return

  layout.forEach(item => {
    const field = props.fields.find(f => f.id === item.fieldId)
    if (field) {
      addFieldToGrid(field, item.x, item.y, item.w, item.h)
    }
  })
}

const handleDragStart = (event: DragEvent, field: FieldConfig) => {
  if (event.dataTransfer) {
    event.dataTransfer.effectAllowed = 'copy';
    event.dataTransfer.setData('application/json', JSON.stringify(field));
  }
}

const handleDragOver = (event: DragEvent) => {
  event.preventDefault();
  if (event.dataTransfer) {
    event.dataTransfer.dropEffect = 'copy';
  }
};

const handleDrop = (event: DragEvent) => {
  event.preventDefault();
  
  const fieldData = event.dataTransfer?.getData('application/json');
  if (!fieldData || !grid) return;
  
  const field = JSON.parse(fieldData);
  
  // Get the grid bounding rect
  const gridRect = gridContainer.value?.getBoundingClientRect();
  if (!gridRect) return;
  
  // Calculate grid position from drop coordinates
  const x = event.clientX - gridRect.left;
  const y = event.clientY - gridRect.top;
  
  // Convert pixels to grid coordinates (approx)
  const cellWidth = gridRect.width / 6; // 6 columns
  const cellHeight = 80; // from our config
  
  const gridX = Math.floor(x / cellWidth);
  const gridY = Math.floor(y / cellHeight);
  
  // Add the field at the calculated position
  addFieldToGrid(field, gridX, gridY);
};

const addFieldToGrid = (field: FieldConfig, x?: number, y?: number, w: number = 3, h: number = 1) => {
  if (!grid || placedFieldIds.value.has(field.id)) return

  // Create the widget element manually
  const widgetEl = document.createElement('div')
  widgetEl.className = 'grid-stack-item'
  
  const contentEl = document.createElement('div')
  contentEl.className = 'grid-stack-item-content bg-white dark:bg-slate-900 border rounded p-3 shadow-sm'
  contentEl.setAttribute('data-field-id', field.id)
  
  contentEl.innerHTML = `
    <div class="flex justify-between items-start">
      <div class="flex-1">
        <div class="font-medium text-sm">${field.label}</div>
        <div class="text-xs text-muted-foreground">${field.apiName}</div>
        <div class="text-xs text-muted-foreground">Type: ${field.type}</div>
      </div>
      <button class="remove-btn text-destructive hover:text-destructive/80 text-xl leading-none ml-2" type="button">
        ×
      </button>
    </div>
  `

  // Add click handler for remove button
  const removeBtn = contentEl.querySelector('.remove-btn')
  if (removeBtn) {
    removeBtn.addEventListener('click', (e) => {
      e.stopPropagation()
      if (grid) {
        grid.removeWidget(widgetEl)
        placedFieldIds.value.delete(field.id)
        gridItems.value.delete(field.id)
      }
    })
  }

  widgetEl.appendChild(contentEl)
  
  // Use makeWidget for GridStack v11+
  grid.makeWidget(widgetEl)
  
  // Set grid position after making it a widget
  grid.update(widgetEl, {
    x: x,
    y: y,
    w: w,
    h: h,
    minW: 1,
    maxW: 6,
  })
  
  placedFieldIds.value.add(field.id)
  gridItems.value.set(field.id, widgetEl)
}

const updatePlacedFields = () => {
  if (!grid) return
  
  const items = grid.getGridItems()
  const newPlacedIds = new Set<string>()
  
  items.forEach(item => {
    const contentEl = item.querySelector('.grid-stack-item-content')
    const fieldId = contentEl?.getAttribute('data-field-id')
    if (fieldId) {
      newPlacedIds.add(fieldId)
    }
  })
  
  placedFieldIds.value = newPlacedIds
}

const handleClear = () => {
  if (!grid) return
  
  if (confirm('Are you sure you want to clear all fields from the layout?')) {
    grid.removeAll()
    placedFieldIds.value.clear()
    gridItems.value.clear()
  }
}

const handleSave = () => {
  if (!grid) return

  const items = grid.getGridItems()
  const layout: FieldLayoutItem[] = []

  items.forEach(item => {
    // Look for data-field-id in the content element
    const contentEl = item.querySelector('.grid-stack-item-content')
    const fieldId = contentEl?.getAttribute('data-field-id')
    const node = (item as any).gridstackNode
    
    if (fieldId && node) {
      layout.push({
        fieldId,
        x: node.x,
        y: node.y,
        w: node.w,
        h: node.h,
      })
    }
  })

  emit('save', {
    fields: layout,
    relatedLists: selectedRelatedLists.value,
  })
}

onMounted(() => {
  initGrid()
})

onBeforeUnmount(() => {
  if (grid) {
    grid.destroy(false)
  }
})

// Watch for fields changes
watch(() => props.fields, () => {
  updatePlacedFields()
}, { deep: true })

watch(
  () => props.initialRelatedLists,
  (value) => {
    selectedRelatedLists.value = value ? [...value] : []
  },
)
</script>

<style>
.grid-stack {
  background: transparent;
}

.grid-stack-item {
  cursor: move;
}

.grid-stack-item-content {
  cursor: move;
  overflow: hidden;
}

.grid-stack-item .remove-btn {
  cursor: pointer;
  font-size: 20px;
  line-height: 1;
  padding: 4px 8px;
}

/* Customize grid appearance */
.grid-stack > .grid-stack-item > .ui-resizable-se {
  background: none;
}

.grid-stack > .grid-stack-item > .ui-resizable-handle {
  background-color: rgba(0, 0, 0, 0.1);
}

/* Dark mode adjustments */
.dark .grid-stack > .grid-stack-item > .ui-resizable-handle {
  background-color: rgba(255, 255, 255, 0.1);
}
</style>
