<template>
  <div class="universal-query-builder bg-white rounded-lg shadow-lg p-6">
    <!-- 表选择 -->
    <div class="mb-6">
      <label class="block text-sm font-medium text-gray-700 mb-2"> 选择表 </label>
      <select
        v-model="selectedTable"
        @change="onTableChange"
        class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
      >
        <option value="">请选择表</option>
        <option v-for="table in availableTables" :key="table.key" :value="table.key">
          {{ table.name }}
        </option>
      </select>
    </div>

    <!-- 查询条件构造器 -->
    <div v-if="selectedTable && tableInfo" class="mb-6">
      <div class="flex items-center justify-between mb-4">
        <h3 class="text-lg font-medium text-gray-900">查询条件</h3>
        <button
          @click="addCondition"
          class="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500"
        >
          添加条件
        </button>
      </div>

      <!-- 条件列表 -->
      <div v-if="queryOptions.where && queryOptions.where.length > 0" class="space-y-4">
        <div
          v-for="(condition, index) in queryOptions.where"
          :key="index"
          class="flex items-center space-x-4 p-4 bg-gray-50 rounded-lg"
        >
          <!-- 逻辑操作符 -->
          <select
            v-if="index > 0"
            v-model="condition.logicalOperator"
            class="px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
          >
            <option value="AND">AND</option>
            <option value="OR">OR</option>
          </select>

          <!-- 字段选择 -->
          <select
            v-model="condition.field"
            @change="onFieldChange(condition)"
            class="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
          >
            <option value="">选择字段</option>
            <option v-for="field in tableInfo.fields" :key="field.name" :value="field.name">
              {{ field.name }} ({{ field.type }})
            </option>
          </select>

          <!-- 操作符选择 -->
          <select
            v-model="condition.operator"
            @change="onOperatorChange(condition)"
            class="px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
          >
            <option value="">选择操作符</option>
            <option
              v-for="operator in getAvailableOperators(condition.field)"
              :key="operator.value"
              :value="operator.value"
            >
              {{ operator.label }}
            </option>
          </select>

          <!-- 值输入 -->
          <div class="flex-1">
            <!-- 单值输入 -->
            <input
              v-if="
                !isMultiValueOperator(condition.operator) && !isNullOperator(condition.operator)
              "
              v-model="condition.value"
              :type="getInputType(condition.field, condition.operator)"
              :placeholder="getInputPlaceholder(condition.field, condition.operator)"
              class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
            />

            <!-- 多值输入 -->
            <div v-else-if="isMultiValueOperator(condition.operator)" class="space-y-2">
              <input
                v-if="condition.operator === 'between' || condition.operator === 'date_between'"
                v-model="condition.value[0]"
                :type="getInputType(condition.field, condition.operator)"
                placeholder="起始值"
                class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
              />
              <input
                v-if="condition.operator === 'between' || condition.operator === 'date_between'"
                v-model="condition.value[1]"
                :type="getInputType(condition.field, condition.operator)"
                placeholder="结束值"
                class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
              />
              <textarea
                v-if="condition.operator === 'in' || condition.operator === 'not_in'"
                v-model="condition.valueText"
                @input="onMultiValueInput(condition)"
                placeholder="输入多个值，用逗号分隔"
                rows="2"
                class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
              />
            </div>

            <!-- 空值操作符不需要输入 -->
            <span v-else-if="isNullOperator(condition.operator)" class="text-gray-500 italic">
              无需输入值
            </span>
          </div>

          <!-- 删除按钮 -->
          <button
            @click="removeCondition(index)"
            class="px-3 py-2 bg-red-500 text-white rounded-md hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500"
          >
            删除
          </button>
        </div>
      </div>

      <div v-else class="text-gray-500 text-center py-8">
        暂无查询条件，点击"添加条件"开始构建查询
      </div>
    </div>

    <!-- 搜索框 -->
    <div v-if="selectedTable && tableInfo" class="mb-6">
      <label class="block text-sm font-medium text-gray-700 mb-2"> 全文搜索 </label>
      <input
        v-model="queryOptions.search"
        type="text"
        placeholder="输入搜索关键词..."
        class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
      />
      <p class="text-sm text-gray-500 mt-1">搜索字段: {{ tableInfo.searchFields.join(', ') }}</p>
    </div>

    <!-- 排序设置 -->
    <div v-if="selectedTable && tableInfo" class="mb-6">
      <div class="flex items-center justify-between mb-4">
        <h3 class="text-lg font-medium text-gray-900">排序设置</h3>
        <button
          @click="addSortCondition"
          class="px-4 py-2 bg-green-500 text-white rounded-md hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-500"
        >
          添加排序
        </button>
      </div>

      <div v-if="queryOptions.orderBy && queryOptions.orderBy.length > 0" class="space-y-2">
        <div
          v-for="(sort, index) in queryOptions.orderBy"
          :key="index"
          class="flex items-center space-x-4 p-3 bg-gray-50 rounded-lg"
        >
          <select
            v-model="sort.field"
            class="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
          >
            <option value="">选择字段</option>
            <option v-for="field in tableInfo.sortableFields" :key="field" :value="field">
              {{ field }}
            </option>
          </select>

          <select
            v-model="sort.direction"
            class="px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
          >
            <option value="ASC">升序</option>
            <option value="DESC">降序</option>
          </select>

          <button
            @click="removeSortCondition(index)"
            class="px-3 py-2 bg-red-500 text-white rounded-md hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500"
          >
            删除
          </button>
        </div>
      </div>
    </div>

    <!-- 分页设置 -->
    <div v-if="selectedTable" class="mb-6">
      <h3 class="text-lg font-medium text-gray-900 mb-4">分页设置</h3>
      <div class="grid grid-cols-2 gap-4">
        <div>
          <label class="block text-sm font-medium text-gray-700 mb-2">页码</label>
          <input
            v-model.number="queryOptions.pagination.page"
            type="number"
            min="1"
            class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
          />
        </div>
        <div>
          <label class="block text-sm font-medium text-gray-700 mb-2">每页数量</label>
          <select
            v-model.number="queryOptions.pagination.limit"
            class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
          >
            <option :value="10">10</option>
            <option :value="20">20</option>
            <option :value="50">50</option>
            <option :value="100">100</option>
          </select>
        </div>
      </div>
    </div>

    <!-- 操作按钮 -->
    <div v-if="selectedTable" class="flex space-x-4">
      <button
        @click="executeQuery"
        :disabled="loading"
        class="flex-1 px-6 py-3 bg-blue-500 text-white rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:opacity-50"
      >
        {{ loading ? '查询中...' : '执行查询' }}
      </button>

      <button
        @click="executeAggregateQuery"
        :disabled="loading"
        class="px-6 py-3 bg-purple-500 text-white rounded-md hover:bg-purple-600 focus:outline-none focus:ring-2 focus:ring-purple-500 disabled:opacity-50"
      >
        聚合查询
      </button>

      <button
        @click="clearQuery"
        class="px-6 py-3 bg-gray-500 text-white rounded-md hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-500"
      >
        清空
      </button>
    </div>

    <!-- 查询结果 -->
    <div v-if="queryResult" class="mt-8">
      <h3 class="text-lg font-medium text-gray-900 mb-4">查询结果</h3>

      <!-- 结果统计 -->
      <div class="mb-4 p-4 bg-blue-50 rounded-lg">
        <p class="text-sm text-blue-800">
          <span v-if="queryResult.pagination">
            第 {{ queryResult.pagination.page }} 页，共 {{ queryResult.pagination.totalPages }} 页，
            总计 {{ queryResult.total }} 条记录
          </span>
          <span v-else> 总计 {{ queryResult.total }} 条记录 </span>
        </p>
      </div>

      <!-- 数据表格 -->
      <div class="overflow-x-auto">
        <table class="min-w-full divide-y divide-gray-200">
          <thead class="bg-gray-50">
            <tr>
              <th
                v-for="field in getDisplayFields()"
                :key="field"
                class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
              >
                {{ field }}
              </th>
            </tr>
          </thead>
          <tbody class="bg-white divide-y divide-gray-200">
            <tr v-for="(item, index) in queryResult.data" :key="index">
              <td
                v-for="field in getDisplayFields()"
                :key="field"
                class="px-6 py-4 whitespace-nowrap text-sm text-gray-900"
              >
                {{ formatValue(item[field]) }}
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>

    <!-- 聚合结果 -->
    <div v-if="aggregateResult" class="mt-8">
      <h3 class="text-lg font-medium text-gray-900 mb-4">聚合结果</h3>
      <div class="bg-gray-50 rounded-lg p-4">
        <pre class="text-sm">{{ JSON.stringify(aggregateResult, null, 2) }}</pre>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import type { AdvancedQueryOptions, QueryCondition, SortCondition } from '@nuxt4crud/shared/types'

/**
 * 组件属性
 * Component props
 */
interface Props {
  modelValue?: AdvancedQueryOptions
  table?: string
}

/**
 * 组件事件
 * Component events
 */
interface Emits {
  (e: 'update:modelValue', value: AdvancedQueryOptions): void
  (e: 'query', result: any): void
  (e: 'aggregate', result: any): void
  (e: 'search', options: AdvancedQueryOptions): void
  (e: 'reset'): void
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: () => ({
    where: [],
    orderBy: [],
    pagination: { page: 1, limit: 20 },
  }),
})

const emit = defineEmits<Emits>()

// 响应式数据
const selectedTable = ref(props.table || '')
const availableTables = ref<any[]>([])
const tableInfo = ref<any>(null)
const loading = ref(false)
const queryResult = ref<any>(null)
const aggregateResult = ref<any>(null)

// 监听table属性变化
watch(() => props.table, (newTable) => {
  if (newTable) {
    selectedTable.value = newTable
  }
})

// 查询选项
const queryOptions = ref<AdvancedQueryOptions>({
  where: [],
  orderBy: [],
  search: '',
  pagination: { page: 1, limit: 20 },
})

/**
 * 监听查询选项变化
 * Watch query options changes
 */
watch(
  queryOptions,
  newValue => {
    emit('update:modelValue', newValue)
  },
  { deep: true }
)

/**
 * 监听外部传入的值
 * Watch external value changes
 */
watch(
  () => props.modelValue,
  newValue => {
    if (newValue && JSON.stringify(newValue) !== JSON.stringify(queryOptions.value)) {
      queryOptions.value = { ...newValue }
    }
  },
  { immediate: true }
)

/**
 * 获取可用表列表
 * Get available tables
 */
async function loadAvailableTables() {
  try {
    const response = await $fetch('/api/table-info')
    if (response.success) {
      availableTables.value = response.data.tables
    } else {
      // 提供默认的表列表，确保能够正确加载用户表和文章表
      availableTables.value = [
        {
          key: 'User',
          name: '用户表'
        },
        {
          key: 'Post',
          name: '文章表'
        }
      ]
    }
  } catch (error) {
    console.error('Failed to load tables:', error)
    // 错误时提供默认的表列表
    availableTables.value = [
      {
        key: 'User',
        name: '用户表'
      },
      {
        key: 'Post',
        name: '文章表'
      }
    ]
  }
}

/**
 * 表选择变化处理
 * Handle table selection change
 */
async function onTableChange() {
  if (!selectedTable.value) {
    tableInfo.value = null
    return
  }

  try {
    const response = await $fetch(`/api/table-info?table=${selectedTable.value}`)
    if (response.success) {
      tableInfo.value = response.data.table
      // 清空之前的查询条件
      clearQuery()
    }
  } catch (error) {
    console.error('Failed to load table info:', error)
  }
}

/**
 * 添加查询条件
 * Add query condition
 */
function addCondition() {
  const condition: QueryCondition & { logicalOperator?: string; valueText?: string } = {
    field: '',
    operator: 'equals' as any,
    value: '',
    logicalOperator: queryOptions.value.where!.length > 0 ? 'AND' : undefined,
    valueText: '',
  }

  if (!queryOptions.value.where) {
    queryOptions.value.where = []
  }

  queryOptions.value.where.push(condition as any)
}

/**
 * 删除查询条件
 * Remove query condition
 */
function removeCondition(index: number) {
  if (queryOptions.value.where) {
    queryOptions.value.where.splice(index, 1)
  }
}

/**
 * 字段变化处理
 * Handle field change
 */
function onFieldChange(condition: any) {
  // 重置操作符和值
  condition.operator = 'equals'
  condition.value = ''
  condition.valueText = ''
}

/**
 * 操作符变化处理
 * Handle operator change
 */
function onOperatorChange(condition: any) {
  // 根据操作符类型初始化值
  if (isMultiValueOperator(condition.operator)) {
    if (condition.operator === 'between' || condition.operator === 'date_between') {
      condition.value = ['', '']
    } else {
      condition.value = []
      condition.valueText = ''
    }
  } else if (isNullOperator(condition.operator)) {
    condition.value = null
  } else {
    condition.value = ''
  }
}

/**
 * 多值输入处理
 * Handle multi-value input
 */
function onMultiValueInput(condition: any) {
  if (condition.valueText) {
    condition.value = condition.valueText
      .split(',')
      .map((v: string) => v.trim())
      .filter(Boolean)
  } else {
    condition.value = []
  }
}

/**
 * 获取可用操作符
 * Get available operators for field
 */
function getAvailableOperators(fieldName: string) {
  if (!tableInfo.value || !fieldName) return []

  const field = tableInfo.value.fields.find((f: any) => f.name === fieldName)
  if (!field) return []

  return tableInfo.value.operators.filter((op: any) => op.types.includes(field.type))
}

/**
 * 判断是否为多值操作符
 * Check if operator requires multiple values
 */
function isMultiValueOperator(operator: string): boolean {
  return ['in', 'not_in', 'between', 'date_between'].includes(operator)
}

/**
 * 判断是否为空值操作符
 * Check if operator is null operator
 */
function isNullOperator(operator: string): boolean {
  return ['is_null', 'is_not_null'].includes(operator)
}

/**
 * 获取输入框类型
 * Get input type for field and operator
 */
function getInputType(fieldName: string, operator: string): string {
  if (!tableInfo.value || !fieldName) return 'text'

  const field = tableInfo.value.fields.find((f: any) => f.name === fieldName)
  if (!field) return 'text'

  if (operator.startsWith('date_') || field.type === 'datetime') {
    return 'datetime-local'
  } else if (field.type === 'number') {
    return 'number'
  }

  return 'text'
}

/**
 * 获取输入框占位符
 * Get input placeholder
 */
function getInputPlaceholder(fieldName: string, operator: string): string {
  if (!tableInfo.value || !fieldName) return ''

  const field = tableInfo.value.fields.find((f: any) => f.name === fieldName)
  if (!field) return ''

  return `请输入${field.name}的值`
}

/**
 * 添加排序条件
 * Add sort condition
 */
function addSortCondition() {
  const sortCondition: SortCondition = {
    field: '',
    direction: 'ASC',
  }

  if (!queryOptions.value.orderBy) {
    queryOptions.value.orderBy = []
  }

  queryOptions.value.orderBy.push(sortCondition)
}

/**
 * 删除排序条件
 * Remove sort condition
 */
function removeSortCondition(index: number) {
  if (queryOptions.value.orderBy) {
    queryOptions.value.orderBy.splice(index, 1)
  }
}

/**
 * 执行查询
 * Execute query
 */
async function executeQuery() {
  if (!selectedTable.value) return

  loading.value = true
  queryResult.value = null
  aggregateResult.value = null
  
  // 发出搜索事件，传递查询选项
  emit('search', queryOptions.value)

  try {
    const response = await $fetch('/api/universal-query', {
      method: 'POST',
      body: {
        table: selectedTable.value,
        options: queryOptions.value,
        mode: 'query',
      },
    })

    if (response.success) {
      queryResult.value = response.data
      emit('query', response.data)
    }
  } catch (error) {
    console.error('Query failed:', error)
    alert('查询失败: ' + (error as any).data?.message || '未知错误')
  } finally {
    loading.value = false
  }
}

/**
 * 执行聚合查询
 * Execute aggregate query
 */
async function executeAggregateQuery() {
  if (!selectedTable.value) return

  loading.value = true
  queryResult.value = null
  aggregateResult.value = null

  try {
    // 构建聚合选项
    const aggregateOptions = {
      ...queryOptions.value,
      aggregate: {
        count: true,
        sum: tableInfo.value.fields.filter((f: any) => f.type === 'number').map((f: any) => f.name),
        avg: tableInfo.value.fields.filter((f: any) => f.type === 'number').map((f: any) => f.name),
        min: tableInfo.value.fields.filter((f: any) => f.type === 'number').map((f: any) => f.name),
        max: tableInfo.value.fields.filter((f: any) => f.type === 'number').map((f: any) => f.name),
      },
    }

    const response = await $fetch('/api/universal-query', {
      method: 'POST',
      body: {
        table: selectedTable.value,
        options: aggregateOptions,
        mode: 'aggregate',
      },
    })

    if (response.success) {
      aggregateResult.value = response.data.result
      emit('aggregate', response.data)
    }
  } catch (error) {
    console.error('Aggregate query failed:', error)
    alert('聚合查询失败: ' + (error as any).data?.message || '未知错误')
  } finally {
    loading.value = false
  }
}

/**
 * 清空查询
 * Clear query
 */
function clearQuery() {
  queryOptions.value = {
    where: [],
    orderBy: tableInfo.value?.defaultOrderBy || [],
    search: '',
    pagination: { page: 1, limit: 20 },
  }
  queryResult.value = null
  aggregateResult.value = null
  // 发出重置事件
  emit('reset')
}

/**
 * 获取显示字段
 * Get display fields
 */
function getDisplayFields(): string[] {
  if (!queryResult.value?.data || queryResult.value.data.length === 0) return []
  return Object.keys(queryResult.value.data[0])
}

/**
 * 格式化值显示
 * Format value for display
 */
function formatValue(value: any): string {
  if (value === null || value === undefined) return '-'
  if (typeof value === 'object') return JSON.stringify(value)
  if (typeof value === 'string' && value.includes('T')) {
    // 可能是日期时间
    try {
      return new Date(value).toLocaleString()
    } catch {
      return value
    }
  }
  return String(value)
}

// 组件挂载时加载表列表
onMounted(() => {
  loadAvailableTables()
})
</script>

<style scoped>
.universal-query-builder {
  max-width: 100%;
}
</style>
