<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/components/ui/command'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { Check, ChevronsUpDown, X } from 'lucide-vue-next'
import { cn } from '@/lib/utils'
import type { FieldConfig } from '@/types/field-types'

interface Props {
  field: FieldConfig
  modelValue: string | null // The ID of the selected record
  readonly?: boolean
  baseUrl?: string // Base API URL, defaults to '/central'
  relationTypeValue?: string | null
}

const props = withDefaults(defineProps<Props>(), {
  // Default to runtime objects endpoint; override when consuming central entities
  baseUrl: '/runtime/objects',
  modelValue: null,
})

const emit = defineEmits<{
  'update:modelValue': [value: string | null]
  'update:relationTypeValue': [value: string | null]
}>()

const { api } = useApi()
const open = ref(false)
const searchQuery = ref('')
const records = ref<any[]>([])
const loading = ref(false)
const selectedRecord = ref<any | null>(null)
const selectedRelationObject = ref<string | null>(null)

// Get the relation configuration
const availableRelationObjects = computed(() => {
  if (props.field.relationObjects && props.field.relationObjects.length > 0) {
    return props.field.relationObjects
  }

  const fallback = props.field.relationObject || props.field.apiName.replace('Id', '')
  return fallback ? [fallback] : []
})

const relationObject = computed(() => selectedRelationObject.value || availableRelationObjects.value[0])
const displayField = computed(() => props.field.relationDisplayField || 'name')
const shouldShowTypeSelector = computed(() => availableRelationObjects.value.length > 1)

// Display value for the selected record
const displayValue = computed(() => {
  if (!selectedRecord.value) return 'Select...'
  return selectedRecord.value[displayField.value] || selectedRecord.value.id
})

// Filtered records based on search
const filteredRecords = computed(() => {
  if (!searchQuery.value) return records.value
  
  const query = searchQuery.value.toLowerCase()
  return records.value.filter(record => {
    const displayValue = record[displayField.value] || record.id
    return displayValue.toLowerCase().includes(query)
  })
})

// Fetch available records for the lookup
const fetchRecords = async () => {
  if (!relationObject.value) {
    records.value = []
    return
  }

  loading.value = true
  try {
    const endpoint = `${props.baseUrl}/${relationObject.value}/records`
    const response = await api.get(endpoint)
    records.value = response || []
    
    // If we have a modelValue, find the selected record
    if (props.modelValue) {
      selectedRecord.value = records.value.find(r => r.id === props.modelValue) || null
    }
  } catch (err) {
    console.error('Error fetching lookup records:', err)
  } finally {
    loading.value = false
  }
}

const handleRelationTypeChange = (value: string) => {
  selectedRelationObject.value = value
  emit('update:relationTypeValue', value)
  searchQuery.value = ''
  selectedRecord.value = null
  emit('update:modelValue', null)
  fetchRecords()
}

// Handle record selection
const selectRecord = (record: any) => {
  selectedRecord.value = record
  emit('update:modelValue', record.id)
  open.value = false
}

// Clear selection
const clearSelection = () => {
  selectedRecord.value = null
  emit('update:modelValue', null)
}

// Watch for external modelValue changes
watch(() => props.modelValue, (newValue) => {
  if (newValue && records.value.length > 0) {
    selectedRecord.value = records.value.find(r => r.id === newValue) || null
  } else if (!newValue) {
    selectedRecord.value = null
  }
})

watch(() => props.relationTypeValue, (newValue) => {
  if (!newValue) return
  if (availableRelationObjects.value.includes(newValue)) {
    selectedRelationObject.value = newValue
    fetchRecords()
  }
})

onMounted(() => {
  selectedRelationObject.value = props.relationTypeValue && availableRelationObjects.value.includes(props.relationTypeValue)
    ? props.relationTypeValue
    : availableRelationObjects.value[0] || null

  // Emit initial relation type if we have a default selection so hidden relationTypeField gets populated
  if (selectedRelationObject.value) {
    emit('update:relationTypeValue', selectedRelationObject.value)
  }

  fetchRecords()
})
</script>

<template>
  <div class="lookup-field space-y-2">
    <Popover v-model:open="open">
      <div class="flex gap-2">
        <Select
          v-if="shouldShowTypeSelector"
          :model-value="relationObject"
          :disabled="readonly || loading"
          @update:model-value="handleRelationTypeChange"
        >
          <SelectTrigger class="w-40">
            <SelectValue placeholder="Select type" />
          </SelectTrigger>
          <SelectContent>
            <SelectItem
              v-for="option in availableRelationObjects"
              :key="option"
              :value="option"
            >
              {{ option }}
            </SelectItem>
          </SelectContent>
        </Select>
        <PopoverTrigger as-child>
          <Button
            variant="outline"
            role="combobox"
            :aria-expanded="open"
            :disabled="readonly || loading"
            class="flex-1 justify-between"
          >
            <span class="truncate">{{ displayValue }}</span>
            <ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
          </Button>
        </PopoverTrigger>
        
        <Button
          v-if="selectedRecord && !readonly"
          variant="outline"
          size="icon"
          @click="clearSelection"
          class="shrink-0"
        >
          <X class="h-4 w-4" />
        </Button>
      </div>
      
      <PopoverContent class="w-[400px] p-0">
        <Command>
          <CommandInput 
            v-model="searchQuery"
            :placeholder="relationObject ? `Search ${relationObject}...` : 'Search...'" 
          />
          <CommandEmpty>
            {{ loading ? 'Loading...' : 'No results found.' }}
          </CommandEmpty>
          <CommandList>
            <CommandGroup>
              <CommandItem
                v-for="record in filteredRecords"
                :key="record.id"
                :value="record.id"
                @select="selectRecord(record)"
              >
                <Check
                  :class="cn(
                    'mr-2 h-4 w-4',
                    selectedRecord?.id === record.id ? 'opacity-100' : 'opacity-0'
                  )"
                />
                {{ record[displayField] || record.id }}
              </CommandItem>
            </CommandGroup>
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
    
    <!-- Display readonly value -->
    <div v-if="readonly && selectedRecord" class="text-sm text-muted-foreground">
      {{ selectedRecord[displayField] || selectedRecord.id }}
    </div>
  </div>
</template>

<style scoped>
.lookup-field {
  width: 100%;
}
</style>
