<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { dssResourcesApi } from '@/api'
import { toast } from 'vue-sonner'
import type { EntityClass, Attribute } from '@/types'
import DkuSpinner from '@/components/DkuSpinner.vue'
import { Badge } from '@/components/ui/badge'

// Props
const props = defineProps<{
  show: boolean
  entity: EntityClass | null
  modelId: string
  versionId: string
  sampleLimit: number
  sampleLimitConfigured: boolean
  attrIndex: number
}>()

// Emits
type ValuesMode = 'AUTO' | 'MANUAL' | 'NONE'

const emit = defineEmits<{
  close: []
  'update:sample-limit': [attrIndex: number, limit: number]
  'update:manual-values': [attrIndex: number, values: string[]]
  'update:values-mode': [attrIndex: number, mode: ValuesMode]
}>()

// Local state
const limit = ref(5)
const search = ref('')
const loading = ref(false)
const values = ref<string[]>([])
const truncated = ref(false)
const manualValuesText = ref('')
const manualDisabled = computed(() => currentAttribute.value?.type === 'EXPRESSION')
const valuesMode = ref<ValuesMode>('NONE')
const isAutoMode = computed(() => valuesMode.value === 'AUTO')
const isManualMode = computed(() => valuesMode.value === 'MANUAL')
const modeDisabled = computed(() => manualDisabled.value)
const newValueInput = ref('')
const fetchLimit = ref(5)
const fetchLoading = ref(false)

// Computed for manual values as array
const manualValuesList = computed(() => {
  return manualValuesText.value
    .split('\n')
    .map(v => v.trim())
    .filter(v => v.length > 0)
})

// Current attribute
const currentAttribute = computed((): Attribute | null => {
  if (!props.entity || props.attrIndex < 0) return null
  return props.entity.attributes[props.attrIndex] || null
})

// Reset state when modal opens or attribute changes
watch([() => props.show, currentAttribute], ([show]) => {
  if (show && currentAttribute.value) {
    values.value = []
    truncated.value = false
    search.value = ''
    limit.value = props.sampleLimit || 5
    manualValuesText.value = (currentAttribute.value.manualValues || []).join('\n')
    const attrMode = currentAttribute.value.distinctValuesHandlingMode
    if (attrMode === 'MANUAL' || (currentAttribute.value.manualValues || []).length > 0) {
      valuesMode.value = 'MANUAL'
    } else if (attrMode === 'AUTO_INDEX' || props.sampleLimitConfigured) {
      valuesMode.value = 'AUTO'
    } else {
      valuesMode.value = 'NONE'
    }
  }
}, { immediate: true })

// Filtered values based on search
const filteredValues = computed(() => {
  if (!search.value) return values.value
  const searchLower = search.value.toLowerCase()
  return values.value.filter(v => v.toLowerCase().includes(searchLower))
})

async function fetchSampleValues() {
  if (!props.entity || props.attrIndex < 0) return

  const attr = currentAttribute.value
  if (!attr) return
  if (!isAutoMode.value) {
    setMode('AUTO')
  }

  if (attr.type === 'EXPRESSION') {
    toast.error('Computed attributes cannot fetch distinct values')
    return
  }

  const attributeName = attr.name
  if (!attributeName) {
    toast.error('Attribute name is missing')
    return
  }
  if (!props.modelId || !props.versionId) {
    toast.error('Semantic model context is missing')
    return
  }

  loading.value = true
  try {
    emit('update:sample-limit', props.attrIndex, limit.value)
    const result = await dssResourcesApi.fetchColumnValues({
      semantic_model_id: props.modelId,
      version_id: props.versionId,
      entity: props.entity.name,
      attribute: attributeName,
      limit: limit.value,
    })

    values.value = result.values
    truncated.value = result.truncated

    toast.success(`Fetched ${result.values.length} values`)
  } catch (e) {
    console.error('Failed to fetch column values:', e)
    toast.error('Failed to fetch column values')
  } finally {
    loading.value = false
  }
}

function clearSampleValues() {
  values.value = []
  truncated.value = false
  toast.success('Preview cleared')
}

function addManualValue() {
  const val = newValueInput.value.trim()
  if (!val) return
  if (manualValuesList.value.includes(val)) {
    toast.warning('Value already exists')
    return
  }
  manualValuesText.value = [...manualValuesList.value, val].join('\n')
  newValueInput.value = ''
}

function removeManualValue(value: string) {
  manualValuesText.value = manualValuesList.value
    .filter(v => v !== value)
    .join('\n')
}

async function fetchFromDataset() {
  if (!props.entity || props.attrIndex < 0) return
  const attr = currentAttribute.value
  if (!attr) return

  if (attr.type === 'EXPRESSION') {
    toast.error('Computed attributes cannot fetch distinct values')
    return
  }

  fetchLoading.value = true
  try {
    const result = await dssResourcesApi.fetchColumnValues({
      semantic_model_id: props.modelId,
      version_id: props.versionId,
      entity: props.entity.name,
      attribute: attr.name,
      limit: fetchLimit.value,
    })

    // Merge with existing, deduplicate
    const existing = manualValuesList.value
    const merged = [...new Set([...existing, ...result.values])]
    manualValuesText.value = merged.join('\n')

    const added = merged.length - existing.length
    toast.success(`Fetched ${result.values.length} values (${added} new)`)
  } catch (e) {
    console.error('Failed to fetch values:', e)
    toast.error('Failed to fetch values from dataset')
  } finally {
    fetchLoading.value = false
  }
}

function clearAllManualValues() {
  manualValuesText.value = ''
  toast.success('All values cleared')
}

function setMode(mode: ValuesMode) {
  if (modeDisabled.value) return
  if (valuesMode.value === mode) return
  valuesMode.value = mode
  emit('update:values-mode', props.attrIndex, mode)
}

function close() {
  emit('close')
}

function handleOk() {
  // Apply manual values if in manual mode
  if (isManualMode.value && !manualDisabled.value) {
    const valuesList = manualValuesText.value
      .split('\n')
      .map(v => v.trim())
      .filter(v => v.length > 0)
    emit('update:manual-values', props.attrIndex, valuesList)
  }
  emit('close')
}
</script>

<template>
  <Teleport to="body">
    <div
      v-if="show"
      class="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
    >
      <div class="flex w-full max-w-lg flex-col rounded-lg bg-background shadow-lg" style="max-height: 80vh">
        <!-- Modal Header -->
        <div class="border-b px-6 py-4">
          <h2 class="text-lg font-semibold">Sample Values</h2>
          <p class="text-sm text-muted-foreground">
            {{ currentAttribute?.name || 'Attribute' }}
          </p>
        </div>

        <!-- Modal Body -->
        <div class="flex-1 overflow-auto p-6">
          <!-- Mode selection -->
          <div class="mb-5">
            <label class="mb-1 block text-sm font-medium">Values mode</label>
            <select
              :value="valuesMode"
              :disabled="modeDisabled"
              class="w-48 rounded-md border border-input bg-background px-2 py-1.5 text-sm disabled:opacity-50"
              @change="setMode(($event.target as HTMLSelectElement).value as ValuesMode)"
            >
              <option value="AUTO">Auto</option>
              <option value="MANUAL">Manual</option>
              <option value="NONE">No Values</option>
            </select>
            <p v-if="modeDisabled" class="mt-2 text-xs text-muted-foreground">
              Sample values are available only for column attributes.
            </p>
          </div>

          <!-- Fetch Controls -->
          <div v-if="isAutoMode" class="mb-4 flex items-end gap-3">
            <div>
              <label class="mb-1 block text-sm font-medium">Number of values</label>
              <input
                v-model.number="limit"
                type="number"
                min="1"
                max="10000"
                class="h-8 w-24 rounded-md border border-input bg-background px-2 text-sm disabled:opacity-50"
                @change="emit('update:sample-limit', props.attrIndex, limit)"
              />
            </div>
            <div class="inline-flex items-center gap-1">
              <DkuSpinner v-if="loading" size="md" />
              <i v-else class="dku-icon-dataset-16 text-primary" />
              <button
                class="btn-tertiary h-8 disabled:opacity-50"
                :disabled="loading"
                @click="fetchSampleValues"
              >
                Preview
              </button>
            </div>
          </div>
          <p v-if="isAutoMode" class="mb-4 text-xs text-muted-foreground">
            Requires DSS indexing for this version.
          </p>

          <!-- Values Display -->
          <div v-if="isAutoMode && values.length > 0" class="space-y-3">
            <!-- Search -->
            <div class="relative">
              <i class="dku-icon-search-16 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" />
              <input
                v-model="search"
                type="text"
                class="w-full rounded-md border border-input bg-background py-2 pl-9 pr-3 text-sm"
                placeholder="Search values..."
              />
            </div>

            <!-- Values Count -->
            <div class="flex items-center justify-between text-sm text-muted-foreground">
              <span>
                {{ filteredValues.length }} of {{ values.length }} values
                <span v-if="truncated" class="text-amber-500">
                  (more values exist)
                </span>
              </span>
              <button
                class="text-destructive hover:underline"
                @click="clearSampleValues"
              >
                Clear Preview
              </button>
            </div>

            <!-- Values List -->
            <div class="max-h-64 overflow-auto rounded-md border">
              <div
                v-for="(value, index) in filteredValues"
                :key="index"
                class="border-b px-3 py-2 text-sm last:border-b-0"
                :class="{ 'bg-muted/50': index % 2 === 0 }"
              >
                {{ value || '(empty)' }}
              </div>
            </div>
          </div>

          <!-- Empty State -->
          <div v-else-if="isAutoMode" class="rounded-md border border-dashed p-8 text-center text-muted-foreground">
            <i class="dku-icon-list-32 mx-auto mb-2 opacity-50" />
            <p>No sample values fetched yet.</p>
            <p class="text-sm">Click "Preview" to load distinct values for this attribute.</p>
          </div>

          <p v-else-if="valuesMode === 'NONE'" class="mt-3 text-xs text-muted-foreground">
            Sample values are disabled for this attribute.
          </p>

          <!-- Manual Values -->
          <div v-if="isManualMode" class="space-y-4">
            <!-- Header with count -->
            <div class="flex items-center justify-between">
              <h3 class="text-sm font-semibold">Manual Values</h3>
              <span class="text-sm text-muted-foreground">
                {{ manualValuesList.length }} value{{ manualValuesList.length !== 1 ? 's' : '' }}
              </span>
            </div>

            <!-- Add input -->
            <div class="flex gap-2">
              <input
                v-model="newValueInput"
                type="text"
                class="flex-1 rounded-md border border-input bg-background px-3 py-1.5 text-sm"
                placeholder="Add value..."
                :disabled="manualDisabled"
                @keydown.enter.prevent="addManualValue"
              />
              <button
                class="btn-secondary h-8 px-3"
                :disabled="manualDisabled || !newValueInput.trim()"
                @click="addManualValue"
              >
                + Add
              </button>
            </div>

            <!-- Badges container -->
            <div
              v-if="manualValuesList.length > 0"
              class="flex flex-wrap gap-2 rounded-md border bg-muted/30 p-3 max-h-48 overflow-auto"
            >
              <Badge
                v-for="value in manualValuesList"
                :key="value"
                variant="secondary"
                class="gap-1.5 pr-1"
              >
                <span class="max-w-32 truncate">{{ value }}</span>
                <button
                  type="button"
                  class="flex h-4 w-4 items-center justify-center rounded-full text-muted-foreground hover:bg-destructive hover:text-destructive-foreground"
                  :disabled="manualDisabled"
                  @click.stop="removeManualValue(value)"
                >
                  <i class="dku-icon-dismiss-12" />
                </button>
              </Badge>
            </div>
            <div
              v-else
              class="rounded-md border border-dashed p-6 text-center text-muted-foreground"
            >
              <p class="text-sm">No values added yet</p>
            </div>

            <!-- Fetch from dataset -->
            <div class="border-t pt-4">
              <p class="mb-2 text-sm font-medium">Fetch from dataset</p>
              <div class="flex items-center gap-3">
                <div class="flex items-center gap-2">
                  <label class="text-sm text-muted-foreground">Limit:</label>
                  <input
                    v-model.number="fetchLimit"
                    type="number"
                    min="1"
                    max="10000"
                    class="h-8 w-20 rounded-md border border-input bg-background px-2 text-sm"
                    :disabled="manualDisabled"
                  />
                </div>
                <div class="inline-flex items-center gap-1">
                  <DkuSpinner v-if="fetchLoading" size="md" />
                  <i v-else class="dku-icon-dataset-16 text-primary" />
                  <button
                    class="btn-tertiary h-8"
                    :disabled="manualDisabled || fetchLoading"
                    @click="fetchFromDataset"
                  >
                    Fetch
                  </button>
                </div>
              </div>
              <p class="mt-1 text-xs text-muted-foreground">
                Fetches distinct values from the indexed dataset and adds them to the list.
              </p>
            </div>

            <!-- Clear all -->
            <div class="flex justify-end">
              <button
                class="text-sm text-destructive hover:underline"
                :disabled="manualDisabled || manualValuesList.length === 0"
                @click="clearAllManualValues"
              >
                Clear All
              </button>
            </div>

            <p v-if="manualDisabled" class="text-xs text-muted-foreground">
              Manual values are available only for column attributes.
            </p>
          </div>
        </div>

        <!-- Modal Footer -->
        <div class="flex justify-end gap-2 border-t px-6 py-4">
          <button
            class="btn-secondary"
            @click="close"
          >
            Cancel
          </button>
          <button
            class="btn-primary"
            @click="handleOk"
          >
            OK
          </button>
        </div>
      </div>
    </div>
  </Teleport>
</template>
