<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
import { useConfigStore } from '../../stores/config'
import { useUiStore } from '../../stores/ui'
import { configApi } from '../../services/configApi'
import ExcelUpload from '../upload/ExcelUpload.vue'
import ConfirmModal from '../ui/ConfirmModal.vue'

const configStore = useConfigStore()
const ui = useUiStore()

const sortedTables = computed(() =>
  [...configStore.tables].sort((a, b) => {
    const nameA = (a.display_name || a.local_table || a.source_table || '').toLowerCase()
    const nameB = (b.display_name || b.local_table || b.source_table || '').toLowerCase()
    return nameA.localeCompare(nameB)
  })
)
const showUpload = ref(false)
const syncing = ref<string | null>(null)
const syncJobId = ref<string | null>(null)
const syncProgress = ref<string | null>(null)
const syncStats = ref<{ rows: number; rate: number; batches: number } | null>(null)
const enriching = ref<string | null>(null)
const expandedTable = ref<string | null>(null)
const tableDetail = ref<any>(null)
const loadingDetail = ref(false)
const savingColumn = ref<string | null>(null)
const savingTable = ref(false)

// Editable table fields
const editTable = reactive<{ display_name: string; business_description: string; sync_schedule: string; sync_filter: string }>({
  display_name: '',
  business_description: '',
  sync_schedule: '',
  sync_filter: '',
})

async function toggleDetail(table: any) {
  if (expandedTable.value === table.id) {
    expandedTable.value = null
    tableDetail.value = null
    return
  }
  expandedTable.value = table.id
  loadingDetail.value = true
  try {
    const { data } = await configApi.getTable(table.id)
    // Load watch columns config
    await loadWatchColumns(table.id)
    const watchSet = new Map(watchColumns.value.map((w: any) => [w.column_name, w]))

    // Initialize editable fields on each column
    if (data.columns) {
      for (const col of data.columns) {
        col._editDisplayName = col.display_name || ''
        col._editDescription = col.business_description || ''
        const w = watchSet.get(col.column_name)
        col._isKey = w?.is_key_column || false
        col._isWatch = w?.is_status_column || false
        col._isDocNumber = w?.is_doc_number_column || false
      }
    }
    tableDetail.value = data
    editTable.display_name = data.display_name || ''
    editTable.business_description = data.business_description || ''
    editTable.sync_schedule = data.sync_schedule || ''
    editTable.sync_filter = data.sync_filter || ''
  } catch {
    ui.showToast('Failed to load table details', 'error')
  } finally {
    loadingDetail.value = false
  }
}

async function saveTableMeta(tableId: string) {
  savingTable.value = true
  try {
    await configApi.updateTable(tableId, {
      display_name: editTable.display_name || undefined,
      business_description: editTable.business_description || undefined,
      sync_schedule: editTable.sync_schedule || undefined,
      sync_filter: editTable.sync_filter || undefined,
    })
    ui.showToast('Table metadata saved', 'success')
    await configStore.fetchTables()
  } catch {
    ui.showToast('Save failed', 'error')
  } finally {
    savingTable.value = false
  }
}

async function saveColumn(col: any) {
  savingColumn.value = col.id
  try {
    await configApi.updateColumn(col.id, {
      display_name: col._editDisplayName || undefined,
      business_description: col._editDescription || undefined,
    })
    col.display_name = col._editDisplayName
    col.business_description = col._editDescription
    ui.showToast('Column saved', 'success')
  } catch {
    ui.showToast('Save failed', 'error')
  } finally {
    savingColumn.value = null
  }
}

async function enrichTable(table: any) {
  enriching.value = table.id
  try {
    const { data } = await configApi.enrichTable(table.id)
    ui.showToast(`Enriched ${data.enriched} columns`, 'success')
    // Reload detail to show new descriptions
    if (expandedTable.value === table.id) {
      await toggleDetail(table)
      expandedTable.value = null
      await toggleDetail(table)
    }
  } catch {
    ui.showToast('Enrichment failed — is Ollama running?', 'error')
  } finally {
    enriching.value = null
  }
}

async function cleanupPatterns() {
  try {
    const { data } = await configApi.cleanupStalePatterns()
    ui.showToast(`Removed ${data.deleted} stale pattern(s)`, 'success')
  } catch {
    ui.showToast('Cleanup failed', 'error')
  }
}

// Confirmation modal
const confirmAction = ref<{
  title: string
  message: string
  detail?: string
  variant: 'warning' | 'danger' | 'info'
  onConfirm: () => void
} | null>(null)

function requestSync(table: any) {
  if (!table.connection_id) return
  const filterInfo = table.sync_filter ? `\nFilter: WHERE ${table.sync_filter}` : '\nFilter: none (all rows)'
  confirmAction.value = {
    title: 'Sync Table from Remote Database',
    message: `This will read data from the remote database and copy it to local PostgreSQL.`,
    detail: `Source: ${table.source_schema}.${table.source_table}\nLocal table: v3q_data."${table.local_table || table.source_table}"\nSource system: ${table.source_system || 'N/A'}${filterInfo}\n\nThis operation will:\n1. Connect to the remote database (read-only)\n2. SELECT rows from the source table${table.sync_filter ? ' (filtered)' : ''}\n3. TRUNCATE and re-insert into local PostgreSQL\n\nNo data is sent to the internet.`,
    variant: 'warning',
    onConfirm: () => doSync(table),
  }
}

async function doSync(table: any) {
  syncing.value = table.id
  syncProgress.value = 'Starting...'
  syncStats.value = null
  syncJobId.value = null

  try {
    // Fire-and-forget: POST returns immediately with job_id
    const { data } = await configApi.syncTable({
      connection_id: table.connection_id,
      source_schema: table.source_schema,
      source_table: table.source_table,
      local_table: table.local_table,
    })
    syncJobId.value = data.job_id
    syncProgress.value = 'Job created, waiting for start...'

    // Poll for progress
    await pollSyncJob(data.job_id, table)
  } catch {
    ui.showToast('Sync failed to start', 'error')
    syncing.value = null
    syncProgress.value = null
    syncStats.value = null
  }
}

async function pollSyncJob(jobId: string, table: any) {
  const POLL_INTERVAL = 2000 // 2 seconds

  const poll = async () => {
    try {
      const { data: job } = await configApi.getSyncJob(jobId)

      syncProgress.value = job.phase_detail || job.phase || job.status
      if (job.rows_inserted > 0 || job.rows_fetched > 0) {
        syncStats.value = {
          rows: job.rows_inserted,
          rate: job.insert_rate || job.fetch_rate || 0,
          batches: job.batches_done,
        }
      }

      if (job.status === 'completed') {
        ui.showToast(`Synced ${job.rows_inserted.toLocaleString()} rows`, 'success')
        await configStore.fetchTables()
        syncing.value = null
        syncProgress.value = null
        syncStats.value = null
        syncJobId.value = null
        return
      }

      if (job.status === 'failed') {
        ui.showToast(`Sync failed: ${job.error_message || 'Unknown error'}`, 'error')
        syncing.value = null
        syncProgress.value = null
        syncStats.value = null
        syncJobId.value = null
        return
      }

      if (job.status === 'cancelled') {
        ui.showToast('Sync cancelled', 'info')
        syncing.value = null
        syncProgress.value = null
        syncStats.value = null
        syncJobId.value = null
        return
      }

      // Still running — poll again
      setTimeout(poll, POLL_INTERVAL)
    } catch {
      // Network error — retry
      setTimeout(poll, POLL_INTERVAL * 2)
    }
  }

  setTimeout(poll, POLL_INTERVAL)
}

async function cancelSync() {
  if (!syncJobId.value) return
  try {
    await configApi.cancelSyncJob(syncJobId.value)
    ui.showToast('Cancelling sync...', 'info')
  } catch {
    ui.showToast('Failed to cancel', 'error')
  }
}

// Watch columns for change detection
const watchColumns = ref<any[]>([])
const savingWatch = ref(false)

async function loadWatchColumns(tableId: string) {
  try {
    const { data } = await configApi.getWatchColumns(tableId)
    watchColumns.value = data.columns || []
  } catch {
    watchColumns.value = []
  }
}

async function saveWatchColumns(tableId: string) {
  if (!tableDetail.value?.columns) return
  savingWatch.value = true
  try {
    const columns = tableDetail.value.columns
      .filter((c: any) => c._isKey || c._isWatch || c._isDocNumber)
      .map((c: any) => ({
        column_name: c.column_name,
        is_key_column: !!c._isKey,
        is_status_column: !!c._isWatch,
        is_doc_number_column: !!c._isDocNumber,
      }))
    await configApi.configureWatchColumns({ table_id: tableId, columns })
    ui.showToast(`Saved ${columns.length} watch column(s)`, 'success')
  } catch {
    ui.showToast('Failed to save watch config', 'error')
  } finally {
    savingWatch.value = false
  }
}

function onDocNumberToggle(toggled: any) {
  // Only one column can be Doc# per table — uncheck others
  if (toggled._isDocNumber && tableDetail.value?.columns) {
    for (const col of tableDetail.value.columns) {
      if (col !== toggled) col._isDocNumber = false
    }
  }
}

const SCHEDULE_OPTIONS = [
  { value: '', label: 'Manual only' },
  { value: '*/5 * * * *', label: 'Every 5 minutes' },
  { value: '*/15 * * * *', label: 'Every 15 minutes' },
  { value: '*/30 * * * *', label: 'Every 30 minutes' },
  { value: '0 * * * *', label: 'Every hour' },
  { value: '0 */6 * * *', label: 'Every 6 hours' },
  { value: '0 0 * * *', label: 'Daily (midnight)' },
]
</script>

<template>
  <div class="max-w-5xl">
    <div class="flex items-center justify-between mb-4">
      <h2 class="text-lg font-semibold">Table Registry</h2>
      <div class="flex gap-2">
        <button @click="cleanupPatterns" class="btn-secondary text-xs">Cleanup Stale Patterns</button>
        <button @click="showUpload = !showUpload" class="btn-primary text-sm">
          {{ showUpload ? 'Close' : 'Import Excel/CSV' }}
        </button>
      </div>
    </div>

    <ExcelUpload v-if="showUpload" @imported="showUpload = false; configStore.fetchTables()" />

    <!-- Table list -->
    <div class="space-y-1">
      <div v-for="table in sortedTables" :key="table.id">
        <!-- Table row -->
        <div
          @click="toggleDetail(table)"
          class="flex items-center gap-2 px-3 py-2.5 rounded-lg cursor-pointer transition-colors"
          :class="expandedTable === table.id ? 'bg-dark-700' : 'hover:bg-dark-800'"
        >
          <span class="text-dark-500 text-xs font-mono">{{ expandedTable === table.id ? '&#9660;' : '&#9654;' }}</span>
          <div class="flex-1 min-w-0">
            <div class="text-sm font-medium text-dark-200 truncate">{{ table.display_name || table.local_table || table.source_table }}</div>
            <div class="text-xs text-dark-500 truncate">{{ table.local_table }}</div>
          </div>
          <span class="text-xs text-dark-500 shrink-0">{{ table.source_system || 'excel' }}</span>
          <span class="text-xs text-dark-400 shrink-0 w-16 text-right">{{ table.row_count?.toLocaleString() ?? '-' }} rows</span>
          <span :class="table.is_synced ? 'text-green-400' : 'text-dark-600'" class="text-xs shrink-0 w-8">{{ table.is_synced ? 'OK' : '--' }}</span>
          <div class="flex gap-1 shrink-0" @click.stop>
            <template v-if="syncing === table.id">
              <button @click="cancelSync" class="btn-secondary text-xs text-red-400 border-red-400/30">Cancel</button>
            </template>
            <template v-else>
              <button
                v-if="table.connection_id"
                @click="requestSync(table)"
                :disabled="!!syncing"
                class="btn-secondary text-xs"
              >Sync</button>
            </template>
            <button
              @click="enrichTable(table)"
              :disabled="enriching === table.id"
              class="btn-secondary text-xs"
              title="Run local LLM to auto-generate column descriptions"
            >{{ enriching === table.id ? 'Enriching...' : 'Enrich' }}</button>
          </div>
        </div>

        <!-- Sync progress bar -->
        <div v-if="syncing === table.id && syncProgress" class="mx-3 mb-1 px-3 py-2 bg-dark-800 border border-primary-500/20 rounded-lg">
          <div class="flex items-center justify-between text-xs">
            <span class="text-primary-400 truncate flex-1">{{ syncProgress }}</span>
            <span v-if="syncStats" class="text-dark-400 ml-3 shrink-0">
              {{ syncStats.rows.toLocaleString() }} rows
              <span v-if="syncStats.rate"> &middot; {{ Math.round(syncStats.rate).toLocaleString() }} rows/s</span>
              <span v-if="syncStats.batches"> &middot; batch {{ syncStats.batches }}</span>
            </span>
          </div>
        </div>

        <!-- Expanded detail panel -->
        <div v-if="expandedTable === table.id" class="ml-6 mr-2 mb-3 bg-dark-800 border border-dark-700 rounded-lg p-4">
          <div v-if="loadingDetail" class="text-dark-500 text-sm py-4 text-center">Loading...</div>

          <template v-else-if="tableDetail">
            <!-- Table metadata -->
            <div class="grid gap-3 mb-3" :class="table.connection_id ? 'grid-cols-3' : 'grid-cols-2'">
              <div>
                <label class="text-xs text-dark-500 block mb-1">Display Name</label>
                <input v-model="editTable.display_name" class="w-full bg-dark-900 border border-dark-600 rounded px-2 py-1.5 text-sm text-dark-200 focus:border-primary-500 focus:outline-none" placeholder="Human-friendly name" />
              </div>
              <div>
                <label class="text-xs text-dark-500 block mb-1">Business Description</label>
                <input v-model="editTable.business_description" class="w-full bg-dark-900 border border-dark-600 rounded px-2 py-1.5 text-sm text-dark-200 focus:border-primary-500 focus:outline-none" placeholder="What this table contains" />
              </div>
              <div v-if="table.connection_id">
                <label class="text-xs text-dark-500 block mb-1">Sync Schedule</label>
                <select v-model="editTable.sync_schedule" class="w-full bg-dark-900 border border-dark-600 rounded px-2 py-1.5 text-sm text-dark-200 focus:border-primary-500 focus:outline-none">
                  <option v-for="opt in SCHEDULE_OPTIONS" :key="opt.value" :value="opt.value">{{ opt.label }}</option>
                </select>
              </div>
            </div>
            <div v-if="table.connection_id" class="mb-4">
              <label class="text-xs text-dark-500 block mb-1">Sync Filter <span class="text-dark-600">(WHERE clause applied during sync, e.g. MANDT='001')</span></label>
              <input v-model="editTable.sync_filter" class="w-full bg-dark-900 border border-dark-600 rounded px-2 py-1.5 text-sm text-dark-200 font-mono focus:border-primary-500 focus:outline-none" placeholder="e.g. MANDT = '001' AND BUKRS = '1000'" />
            </div>
            <div class="mb-4">
              <button @click="saveTableMeta(table.id)" :disabled="savingTable" class="btn-primary text-xs">
                {{ savingTable ? 'Saving...' : 'Save Table Metadata' }}
              </button>
            </div>

            <!-- Columns -->
            <h4 class="text-sm font-medium text-dark-300 mb-2">
              Columns ({{ tableDetail.columns?.length || 0 }})
              <span class="text-dark-500 font-normal ml-2">Key = row identifier &middot; Watch = detect changes &middot; Doc# = document number column</span>
            </h4>

            <div v-if="!tableDetail.columns?.length" class="text-dark-500 text-xs py-3">
              No columns registered. Try re-importing or syncing this table.
            </div>

            <template v-else>
              <!-- Column header -->
              <div class="flex items-center gap-2 px-2 py-1 text-xs text-dark-500 border-b border-dark-700">
                <span class="w-40 shrink-0">Column</span>
                <span class="w-20 shrink-0">Type</span>
                <span class="w-8 shrink-0 text-center" title="Row identifier for change detection">Key</span>
                <span class="w-10 shrink-0 text-center" title="Watch this column for changes during sync">Watch</span>
                <span class="w-10 shrink-0 text-center" title="Column containing the document number (Belegnummer)">Doc#</span>
                <span class="flex-1">Display Name</span>
                <span class="flex-[2]">Business Description</span>
                <span class="w-8 shrink-0"></span>
              </div>

              <div class="space-y-0.5 max-h-96 overflow-y-auto">
                <div
                  v-for="col in tableDetail.columns"
                  :key="col.id"
                  class="flex items-center gap-2 px-2 py-1.5 rounded bg-dark-900/50 hover:bg-dark-900"
                >
                  <span class="text-xs font-mono text-dark-300 w-40 shrink-0 truncate" :title="col.column_name">{{ col.column_name }}</span>
                  <span class="text-xs text-dark-500 w-20 shrink-0 truncate">{{ col.data_type }}</span>
                  <label class="w-8 shrink-0 flex justify-center">
                    <input type="checkbox" v-model="col._isKey" class="accent-yellow-500" />
                  </label>
                  <label class="w-10 shrink-0 flex justify-center">
                    <input type="checkbox" v-model="col._isWatch" class="accent-primary-500" />
                  </label>
                  <label class="w-10 shrink-0 flex justify-center">
                    <input type="checkbox" v-model="col._isDocNumber" class="accent-orange-500" @change="onDocNumberToggle(col)" />
                  </label>
                  <input
                    v-model="col._editDisplayName"
                    class="flex-1 bg-transparent border border-transparent hover:border-dark-600 focus:border-primary-500 rounded px-1.5 py-0.5 text-xs text-dark-300 focus:outline-none min-w-0"
                    placeholder="Display name"
                  />
                  <input
                    v-model="col._editDescription"
                    class="flex-[2] bg-transparent border border-transparent hover:border-dark-600 focus:border-primary-500 rounded px-1.5 py-0.5 text-xs text-dark-300 focus:outline-none min-w-0"
                    placeholder="Business description"
                  />
                  <button
                    v-if="col._editDisplayName !== col.display_name || col._editDescription !== col.business_description"
                    @click="saveColumn(col)"
                    :disabled="savingColumn === col.id"
                    class="text-xs text-primary-400 hover:text-primary-300 shrink-0 w-8"
                  >{{ savingColumn === col.id ? '...' : 'Save' }}</button>
                  <span v-else class="w-8 shrink-0"></span>
                </div>
              </div>

              <!-- Save watch config -->
              <div class="mt-3 flex items-center gap-3">
                <button @click="saveWatchColumns(table.id)" :disabled="savingWatch" class="btn-primary text-xs">
                  {{ savingWatch ? 'Saving...' : 'Save Watch Config' }}
                </button>
                <span class="text-xs text-dark-500">
                  Key columns identify rows &middot; Watched columns trigger sync_events on change
                </span>
              </div>
            </template>
          </template>
        </div>
      </div>
    </div>

    <p v-if="!configStore.tables.length" class="text-dark-500 text-center py-8">No tables registered yet.</p>

    <!-- Confirmation modal -->
    <ConfirmModal
      v-if="confirmAction"
      :title="confirmAction.title"
      :message="confirmAction.message"
      :detail="confirmAction.detail"
      :variant="confirmAction.variant"
      @confirm="confirmAction.onConfirm(); confirmAction = null"
      @cancel="confirmAction = null"
    />
  </div>
</template>
