<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useI18n } from 'vue-i18n'
import { toast } from 'vue-sonner'
import { useAppStore } from '@/stores/app'
import SearchSelect from '@/components/SearchSelect.vue'
import GroupedSearchSelect from '@/components/GroupedSearchSelect.vue'
import DkuSpinner from '@/components/DkuSpinner.vue'
import type { GroupedOption } from '@/components/GroupedSearchSelect.vue'
import { dssResourcesApi, autogenApi, type DSSProject } from '@/api'
import type {
  DSSDataset,
  AutogenModelResponse,
  EntityClass,
  Relationship,
  DSSLLM
} from '@/types'

const props = defineProps<{
  show: boolean
}>()

const emit = defineEmits<{
  close: []
  accept: [entities: EntityClass[], relationships: Relationship[]]
}>()

const appStore = useAppStore()
const { selectedLlmId } = storeToRefs(appStore)
const { t } = useI18n()
const DEFAULT_GENERATED_AUTO_VALUES_LIMIT = 5

// =============================================================================
// State
// =============================================================================

type Mode = 'manual' | 'generate'
type GeneratePhase = 'select' | 'generating' | 'summary'

const mode = ref<Mode>('manual')
const generatePhase = ref<GeneratePhase>('select')
const response = ref<AutogenModelResponse | null>(null)
const error = ref<string | null>(null)

// Manual mode state
const manualName = ref('')

// Manual mode - dataset source
const manualProject = ref('')
const manualDataset = ref('')

// Generate mode state
const selectedProject = ref('')
const selectedDataset = ref('')
const userInstructions = ref('')

// DSS Resources
const projects = ref<DSSProject[]>([])
const datasets = ref<DSSDataset[]>([])
const llms = ref<DSSLLM[]>([])
const loadingProjects = ref(false)
const loadingDatasets = ref(false)
const loadingLlms = ref(false)

// DSS Resources (manual mode - separate from generate mode)
const manualDatasets = ref<DSSDataset[]>([])
const loadingManualDatasets = ref(false)

// Processing state
const isProcessing = ref(false)

// =============================================================================
// Computed
// =============================================================================

const canGenerate = computed(() => {
  return (
    selectedProject.value &&
    selectedDataset.value &&
    selectedLlmId.value &&
    !isProcessing.value
  )
})

const canAddManual = computed(() => {
  return manualName.value.trim().length > 0
})

const coverage = computed(() => {
  return response.value?.coverage
})

const finalEntities = computed<EntityClass[]>(() => {
  return response.value?.model?.entities || []
})

const finalRelationships = computed(() => {
  return response.value?.model?.relationships || []
})

const warnings = computed(() => {
  return response.value?.warnings || []
})

const usageSummary = computed(() => {
  if (!coverage.value) return ''
  const total = coverage.value.total_columns
  const used = coverage.value.used_columns
  if (total <= 0) return ''
  if (used >= total) return 'All columns used'
  return `Used ${used} of ${total} columns`
})

const projectOptions = computed(() => {
  return projects.value.map(proj => ({
    value: proj.key,
    label: `${proj.name} (${proj.key})`,
  }))
})

const manualDatasetOptions = computed(() => {
  return manualDatasets.value.map(ds => ({
    value: ds.name,
    label: ds.name,
  }))
})

const datasetOptions = computed(() => {
  return datasets.value.map(ds => ({
    value: ds.name,
    label: `${ds.name} (${ds.type})`,
  }))
})

const llmOptions = computed((): GroupedOption[] => {
  return llms.value.map(llm => ({
    value: llm.id,
    label: llm.label || llm.id,
    type: llm.type || 'Unknown',
    connection: llm.connection,
  }))
})

const primaryButtonText = computed(() => {
  if (mode.value === 'manual') {
    return 'Add'
  }
  if (generatePhase.value === 'select') {
    return 'Generate'
  }
  if (generatePhase.value === 'summary') {
    return 'Add to Model'
  }
  return ''
})

const showPrimaryButton = computed(() => {
  return mode.value === 'manual' || generatePhase.value !== 'generating'
})

const isPrimaryDisabled = computed(() => {
  if (mode.value === 'manual') {
    return !canAddManual.value
  }
  if (generatePhase.value === 'select') {
    return !canGenerate.value
  }
  return false
})

// =============================================================================
// Lifecycle
// =============================================================================

watch(() => props.show, async (show) => {
  if (show) {
    resetState()
    await Promise.all([loadProjects(), loadLlms()])
  }
})

function resetState() {
  mode.value = 'manual'
  generatePhase.value = 'select'
  response.value = null
  error.value = null

  // Manual mode
  manualName.value = ''

  // Manual mode source config
  manualProject.value = ''
  manualDataset.value = ''
  manualDatasets.value = []

  // Generate mode
  selectedProject.value = ''
  selectedDataset.value = ''
  userInstructions.value = ''
  datasets.value = []
  isProcessing.value = false
}

// =============================================================================
// Data Loading
// =============================================================================

async function loadProjects() {
  loadingProjects.value = true
  try {
    projects.value = await dssResourcesApi.listProjects()
  } catch (e) {
    console.error('Failed to load projects:', e)
    toast.error('Failed to load projects')
  } finally {
    loadingProjects.value = false
  }
}

async function loadLlms() {
  loadingLlms.value = true
  try {
    llms.value = await dssResourcesApi.listLlms()
    appStore.ensureDefaultLlm(llms.value)
  } catch (e) {
    console.error('Failed to load LLMs:', e)
    toast.error('Failed to load LLMs')
  } finally {
    loadingLlms.value = false
  }
}

async function loadDatasets() {
  if (!selectedProject.value) {
    datasets.value = []
    return
  }

  loadingDatasets.value = true
  try {
    datasets.value = await dssResourcesApi.listDatasets(selectedProject.value)
  } catch (e) {
    console.error('Failed to load datasets:', e)
    toast.error('Failed to load datasets')
    datasets.value = []
  } finally {
    loadingDatasets.value = false
  }
}

async function loadManualDatasets() {
  if (!manualProject.value) {
    manualDatasets.value = []
    return
  }
  loadingManualDatasets.value = true
  try {
    manualDatasets.value = await dssResourcesApi.listDatasets(manualProject.value)
  } catch (e) {
    console.error('Failed to load datasets:', e)
    toast.error('Failed to load datasets')
    manualDatasets.value = []
  } finally {
    loadingManualDatasets.value = false
  }
}

watch(selectedProject, () => {
  selectedDataset.value = ''
  loadDatasets()
})

// Manual mode - project change clears dataset
watch(manualProject, () => {
  manualDataset.value = ''
  loadManualDatasets()
})

// =============================================================================
// Actions
// =============================================================================

function handlePrimaryAction() {
  if (mode.value === 'manual') {
    handleAddManual()
  } else if (generatePhase.value === 'select') {
    handleGenerate()
  } else if (generatePhase.value === 'summary') {
    handleAcceptGenerated()
  }
}

function handleAddManual() {
  if (!manualName.value.trim()) {
    toast.error('Please enter an entity name')
    return
  }

  const entity: EntityClass = {
    name: manualName.value.trim(),
    description: '',
    type: 'DATASET',
    attributes: [],
    metrics: [],
    filters: [],
    tags: [],
    primaryKey: { attributes: [] },
    foreignKeys: [],
  }

  // Add source-specific fields
  if (manualProject.value && manualDataset.value) {
    entity.datasetRef = `${manualProject.value}.${manualDataset.value}`
  }

  emit('accept', [entity], [])
  emit('close')
}

function normalizeGeneratedEntities(entities: EntityClass[]): EntityClass[] {
  return entities.map((entity) => ({
    ...entity,
    attributes: (entity.attributes || []).map((attr) => {
      if (attr.type === 'EXPRESSION') {
        return attr
      }

      const hasManualValues = (attr.manualValues || []).length > 0
      const isManualMode = attr.distinctValuesHandlingMode === 'MANUAL'
      if (!hasManualValues && !isManualMode) {
        return attr
      }

      const sqlGenerationConfig = {
        ...(attr.sqlGenerationConfig || {}),
      } as Record<string, unknown>

      if (typeof sqlGenerationConfig.autoValuesLimit !== 'number') {
        sqlGenerationConfig.autoValuesLimit = DEFAULT_GENERATED_AUTO_VALUES_LIMIT
      }

      return {
        ...attr,
        manualValues: [],
        distinctValuesHandlingMode: 'AUTO_INDEX',
        indexDistinctValues: true,
        resolveInUserRequests: attr.resolveInUserRequests !== false,
        sqlGenerationConfig,
      }
    }),
  }))
}

async function handleGenerate() {
  if (!canGenerate.value) return

  isProcessing.value = true
  error.value = null
  generatePhase.value = 'generating'

  try {
    const rawResult = await autogenApi.generateModel({
      project_key: selectedProject.value,
      dataset_name: selectedDataset.value,
      llm_id: selectedLlmId.value,
      user_instructions: userInstructions.value || undefined,
    })

    const result: AutogenModelResponse = rawResult.model
      ? {
          ...rawResult,
          model: {
            ...rawResult.model,
            entities: normalizeGeneratedEntities(rawResult.model.entities || []),
          },
        }
      : rawResult

    response.value = result

    if (result.status === 'completed') {
      generatePhase.value = 'summary'
      toast.success('Model generation completed!')
    } else if (result.status === 'failed') {
      error.value = result.error || 'Generation failed'
      generatePhase.value = 'select'
    }
  } catch (e: unknown) {
    console.error('Generation failed:', e)
    error.value = e instanceof Error ? e.message : 'Generation failed'
    generatePhase.value = 'select'
  } finally {
    isProcessing.value = false
  }
}

function handleAcceptGenerated() {
  if (finalEntities.value.length > 0) {
    emit('accept', finalEntities.value, finalRelationships.value)
    emit('close')
  }
}

function handleClose() {
  // Prevent closing during generation
  if (isProcessing.value) {
    return
  }
  emit('close')
}

function handleRetry() {
  error.value = null
  generatePhase.value = 'select'
}

function switchMode(newMode: Mode) {
  if (isProcessing.value) return
  mode.value = newMode
  // Reset generate phase when switching to generate mode
  if (newMode === 'generate') {
    generatePhase.value = 'select'
    error.value = null
  }
}
</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-3xl flex-col rounded-lg bg-background shadow-lg"
        style="max-height: 90vh"
      >
        <!-- Header -->
        <div class="border-b px-6 py-4">
          <h2 class="text-lg font-semibold">Add Entity</h2>
          <p class="text-sm text-muted-foreground">
            Create a new entity manually or generate from a dataset
          </p>
        </div>

        <!-- Mode Tabs -->
        <div class="flex border-b px-6">
          <button
            class="relative px-4 py-3 text-sm font-medium transition-colors"
            :class="[
              mode === 'manual'
                ? 'text-primary'
                : 'text-muted-foreground hover:text-foreground',
            ]"
            :disabled="isProcessing"
            @click="switchMode('manual')"
          >
            Manual
            <span
              v-if="mode === 'manual'"
              class="absolute bottom-0 left-0 right-0 h-0.5 bg-primary"
            />
          </button>
          <button
            class="relative px-4 py-3 text-sm font-medium transition-colors"
            :class="[
              mode === 'generate'
                ? 'text-primary'
                : 'text-muted-foreground hover:text-foreground',
            ]"
            :disabled="isProcessing"
            @click="switchMode('generate')"
          >
            Automatic
            <span
              v-if="mode === 'generate'"
              class="absolute bottom-0 left-0 right-0 h-0.5 bg-primary"
            />
          </button>
        </div>

        <!-- Body -->
        <div class="flex-1 overflow-auto p-6">
          <!-- ============================================================= -->
          <!-- MANUAL MODE -->
          <!-- ============================================================= -->
          <div v-if="mode === 'manual'" class="space-y-4">
            <!-- Name -->
            <div>
              <label class="mb-1 block text-sm font-medium">Name</label>
              <input
                v-model="manualName"
                type="text"
                class="w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
                placeholder="e.g., Orders"
                @keydown.enter="handleAddManual"
              />
            </div>

            <div>
              <label class="mb-1 block text-sm font-medium">Project</label>
              <SearchSelect
                :model-value="manualProject"
                :options="projectOptions"
                placeholder="Select a project..."
                search-placeholder="Search projects..."
                empty-text="No projects found"
                :disabled="loadingProjects"
                @update:model-value="(val: string) => manualProject = val"
              />
            </div>

            <div>
              <label class="mb-1 block text-sm font-medium">Dataset</label>
              <SearchSelect
                :model-value="manualDataset"
                :options="manualDatasetOptions"
                placeholder="Select a dataset..."
                search-placeholder="Search datasets..."
                empty-text="No datasets found"
                :disabled="!manualProject || loadingManualDatasets"
                @update:model-value="(val: string) => manualDataset = val"
              />
            </div>
          </div>

          <!-- ============================================================= -->
          <!-- GENERATE MODE -->
          <!-- ============================================================= -->
          <div v-else>
            <!-- Error Display -->
            <div
              v-if="error"
              class="mb-6 flex items-start gap-3 rounded-md border border-destructive/50 bg-destructive/10 p-4"
            >
              <i class="dku-icon-error-circle-outline-20 mt-0.5 text-destructive" />
              <div class="flex-1">
                <p class="font-medium text-destructive">Error</p>
                <p class="text-sm text-destructive/80">{{ error }}</p>
              </div>
              <button
                class="rounded-md border border-destructive/50 px-3 py-1 text-sm text-destructive hover:bg-destructive/10"
                @click="handleRetry"
              >
                Retry
              </button>
            </div>

            <!-- Select Phase -->
            <div v-if="generatePhase === 'select'" class="space-y-6">
              <!-- Project Selection -->
              <div>
                <label class="mb-2 block text-sm font-medium">Project</label>
                <SearchSelect
                  :model-value="selectedProject"
                  :options="projectOptions"
                  placeholder="Select a project..."
                  search-placeholder="Search projects..."
                  empty-text="No projects found"
                  :disabled="loadingProjects"
                  @update:model-value="(val: string) => selectedProject = val"
                />
              </div>

              <!-- Dataset Selection -->
              <div>
                <label class="mb-2 block text-sm font-medium">Dataset</label>
                <SearchSelect
                  :model-value="selectedDataset"
                  :options="datasetOptions"
                  placeholder="Select a dataset..."
                  search-placeholder="Search datasets..."
                  empty-text="No datasets found"
                  :disabled="!selectedProject || loadingDatasets"
                  @update:model-value="(val: string) => selectedDataset = val"
                />
                <p class="mt-1 text-xs text-muted-foreground">
                  Only SQL-compatible datasets are shown
                </p>
              </div>

              <!-- LLM Selection -->
              <div>
                <label class="mb-2 block text-sm font-medium">LLM</label>
                <GroupedSearchSelect
                  :model-value="selectedLlmId"
                  :options="llmOptions"
                  placeholder="Select an LLM..."
                  search-placeholder="Filter..."
                  empty-text="No LLMs found"
                  :disabled="loadingLlms"
                  @update:model-value="(val: string) => selectedLlmId = val"
                />
              </div>

              <!-- User Instructions -->
              <div>
                <label class="mb-2 block text-sm font-medium">
                  Additional Instructions
                  <span class="font-normal text-muted-foreground">(optional)</span>
                </label>
                <textarea
                  v-model="userInstructions"
                  class="w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
                  rows="3"
                  placeholder="E.g., 'Group customer info separately from order info', 'Create separate entities for products and categories'..."
                ></textarea>
              </div>
            </div>

            <!-- Generating Phase -->
            <div v-else-if="generatePhase === 'generating'" class="py-12">
              <div class="flex flex-col items-center">
                <i class="dku-icon-stars-16 text-4xl text-primary" />
                <h3 class="mt-6 text-lg font-medium">Generating Entities...</h3>
                <p class="mt-2 text-sm text-muted-foreground">
                  Analyzing schema and creating attributes, metrics, and filters
                </p>
                <DkuSpinner size="lg" class="mt-6" />
                <p class="mt-4 text-xs text-muted-foreground">
                  This may take a moment. Please don't close this window.
                </p>
              </div>
            </div>

            <!-- Summary Phase -->
            <div v-else-if="generatePhase === 'summary'" class="space-y-6">
              <!-- Success header -->
              <div class="rounded-md bg-green-50 p-4 dark:bg-green-950/20">
                <div class="flex items-center gap-2">
                  <i class="dku-icon-checkmark-20 text-green-500" />
                  <span class="font-medium text-green-700 dark:text-green-400">
                    Generation Complete
                  </span>
                </div>
                <p class="mt-1 text-sm text-green-600 dark:text-green-500">
                  {{ t('entities.generated', finalEntities.length) }}.
                  <span v-if="usageSummary">
                    {{ usageSummary }}
                  </span>
                </p>
              </div>

              <!-- Warnings -->
              <div
                v-if="warnings.length > 0"
                class="rounded-md border border-amber-500/50 bg-amber-50 p-4 dark:bg-amber-950/20"
              >
                <div class="flex items-start gap-2">
                  <i class="dku-icon-warning-outline-20 mt-0.5 text-amber-600 dark:text-amber-400" />
                  <div>
                    <p class="font-medium text-amber-700 dark:text-amber-400">
                      {{ t('warnings.count', warnings.length) }}
                    </p>
                    <ul class="mt-1 text-sm text-amber-600 dark:text-amber-500">
                      <li v-for="(warning, i) in warnings.slice(0, 5)" :key="i">
                        {{ warning }}
                      </li>
                      <li v-if="warnings.length > 5" class="text-muted-foreground">
                        ...and {{ warnings.length - 5 }} more
                      </li>
                    </ul>
                  </div>
                </div>
              </div>

              <!-- Generated Entities -->
              <div class="space-y-4">
                <h3 class="font-medium">Generated Entities ({{ finalEntities.length }})</h3>
                <div
                  v-for="entity in finalEntities"
                  :key="entity.name"
                  class="rounded-md border p-4"
                >
                  <div class="flex items-start justify-between">
                    <div>
                      <h4 class="font-medium">{{ entity.name }}</h4>
                      <p v-if="entity.description" class="mt-1 text-sm text-muted-foreground line-clamp-2">
                        {{ entity.description }}
                      </p>
                    </div>
                  </div>
                  <div class="mt-3 flex gap-4 text-sm text-muted-foreground">
                    <span>{{ t('attributes.count', entity.attributes?.length || 0) }}</span>
                    <span>{{ t('metrics.count', entity.metrics?.length || 0) }}</span>
                    <span>{{ t('filters.count', entity.filters?.length || 0) }}</span>
                  </div>
                </div>
              </div>

              <!-- Relationships -->
              <div v-if="finalRelationships.length > 0" class="space-y-4">
                <h3 class="font-medium">Relationships ({{ finalRelationships.length }})</h3>
                <div class="space-y-2">
                  <div
                    v-for="(rel, i) in finalRelationships"
                    :key="i"
                    class="flex items-center gap-2 rounded-md border px-3 py-2 text-sm"
                  >
                    <span class="font-mono">{{ rel.firstEntity }}</span>
                    <i class="dku-icon-chevron-right-16 text-muted-foreground" />
                    <span class="font-mono">{{ rel.secondEntity }}</span>
                  </div>
                </div>
              </div>

              <!-- Unassigned Columns -->
              <div v-if="coverage?.unassigned_columns?.length" class="space-y-2">
                <h3 class="font-medium text-muted-foreground">
                  Unassigned Columns ({{ coverage.unassigned_columns.length }})
                </h3>
                <div class="flex flex-wrap gap-1">
                  <span
                    v-for="col in coverage.unassigned_columns.slice(0, 20)"
                    :key="col"
                    class="rounded bg-amber-100 px-2 py-0.5 font-mono text-xs text-amber-700 dark:bg-amber-900/30 dark:text-amber-400"
                  >
                    {{ col }}
                  </span>
                  <span
                    v-if="coverage.unassigned_columns.length > 20"
                    class="rounded bg-muted px-2 py-0.5 text-xs text-muted-foreground"
                  >
                    +{{ coverage.unassigned_columns.length - 20 }} more
                  </span>
                </div>
                <p class="text-xs text-muted-foreground">
                  You can add these columns to entities later in the editor.
                </p>
              </div>
            </div>
          </div>
        </div>

        <!-- Footer -->
        <div class="flex items-center justify-end gap-2 border-t px-6 py-4">
          <button
            class="btn-secondary disabled:opacity-50"
            :disabled="isProcessing"
            @click="handleClose"
          >
            Cancel
          </button>
          <button
            v-if="showPrimaryButton"
            class="btn-primary inline-flex items-center gap-2 disabled:opacity-50"
            :disabled="isPrimaryDisabled"
            @click="handlePrimaryAction"
          >
            <i v-if="mode === 'generate' && generatePhase === 'select'" class="dku-icon-stars-16" />
            <i v-if="mode === 'generate' && generatePhase === 'summary'" class="dku-icon-checkmark-16" />
            {{ primaryButtonText }}
          </button>
        </div>
      </div>
    </div>
  </Teleport>
</template>
