<template>
  <AppLayout>
    <div class="flex justify-between items-center mb-6 flex-wrap gap-4">
      <h1 class="text-2xl font-bold text-gray-900">OLAP Конструктор</h1>
      <div class="flex gap-3">
        <button @click="saveConfigAsJson" class="btn-secondary flex items-center gap-2">
          <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12" />
          </svg>
          Сохранить JSON
        </button>
        <label class="btn-secondary flex items-center gap-2 cursor-pointer">
          <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
          </svg>
          Загрузить JSON
          <input type="file" accept=".json" @change="loadConfigFromJson" class="hidden">
        </label>
      </div>
    </div>

    <div class="flex flex-row gap-6">
      <!-- Левая панель - поля (sticky, на всю высоту) -->
      <div class="w-72 shrink-0 card p-4 flex flex-col lg:sticky lg:top-4 h-[calc(100vh-12rem)]">
        <h3 class="text-lg font-bold mb-3">Поля</h3>
        <div class="mb-2">
          <input type="text" v-model="searchQuery" placeholder="Поиск по названию или тегам" class="input-field py-1.5 text-sm">
          <div class="text-xs text-gray-500 mt-1" v-if="searchQuery">Найдено: {{ filteredAvailableFields.length }} / {{ availableFields.length }}</div>
        </div>

        <div v-if="loading" class="text-center py-8">...</div>
        <div v-else-if="error" class="bg-red-50 text-red-700 p-3 rounded-xl text-sm">...</div>
        <div v-else-if="availableFields.length === 0" class="text-center py-8 text-gray-500">...</div>
        <div v-else class="flex-1 overflow-y-auto space-y-3 pr-1">
          <!-- Числовые -->
          <div>
            <div class="flex justify-between items-center cursor-pointer select-none" @click="toggleSection('number')">
              <h4 class="text-gray-600 text-sm font-bold">Числовые → VALUES</h4>
              <button class="text-gray-500 hover:text-gray-700">
                <svg v-if="collapsed.number" class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
                </svg>
                <svg v-else class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7" />
                </svg>
              </button>
            </div>
            <div v-show="!collapsed.number" class="mt-2 space-y-1.5">
              <div v-for="field in filteredNumberFields" :key="field.id"
                   class="bg-purple-600 text-white p-2 rounded-lg cursor-grab active:cursor-grabbing text-sm"
                   draggable="true" @dragstart="dragStart($event, field)" @dragend="dragEnd">
                {{ field.name }}
              </div>
            </div>
          </div>

          <!-- Категории -->
          <div>
            <div class="flex justify-between items-center cursor-pointer select-none" @click="toggleSection('category')">
              <h4 class="text-gray-600 text-sm font-bold">Категории → ROW / COLUMN</h4>
              <button class="text-gray-500 hover:text-gray-700">
                <svg v-if="collapsed.category" class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
                </svg>
                <svg v-else class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7" />
                </svg>
              </button>
            </div>
            <div v-show="!collapsed.category" class="mt-2 space-y-1.5">
              <div v-for="field in filteredCategoryFields" :key="field.id"
                   class="bg-pink-500 text-white p-2 rounded-lg cursor-grab active:cursor-grabbing text-sm"
                   draggable="true" @dragstart="dragStart($event, field)" @dragend="dragEnd">
                {{ field.name }}
              </div>
            </div>
          </div>

          <!-- Фильтры -->
          <div>
            <div class="flex justify-between items-center cursor-pointer select-none" @click="toggleSection('filter')">
              <h4 class="text-gray-600 text-sm font-bold">Фильтры</h4>
              <button class="text-gray-500 hover:text-gray-700">
                <svg v-if="collapsed.filter" class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
                </svg>
                <svg v-else class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7" />
                </svg>
              </button>
            </div>
            <div v-show="!collapsed.filter" class="mt-2 space-y-1.5">
              <div v-for="field in filteredFilterFields" :key="field.id"
                   class="bg-cyan-600 text-white p-2 rounded-lg cursor-grab active:cursor-grabbing text-sm"
                   draggable="true" @dragstart="dragStart($event, field)" @dragend="dragEnd">
                {{ field.name }}
              </div>
            </div>
          </div>
        </div>

        <div class="mt-3">
          <button @click="openResetModal" class="btn-secondary w-full py-1.5 text-sm">Сбросить всё</button>
        </div>
      </div>

      <!-- Правая часть -->
      <div class="flex-1 overflow-x-auto">
        <!-- Верхняя панель настроек -->
        <div class="card p-3 mb-4 flex flex-wrap items-center gap-3 justify-between">
          <div class="flex items-center gap-2">
            <span class="font-bold text-gray-700 text-sm">Тип отчета:</span>
            <select v-model="reportType" class="input-field w-auto py-1 text-sm">
              <option value="SALES">SALES</option>
              <option value="DELIVERIES">DELIVERIES</option>
              <option value="TRANSACTIONS">TRANSACTIONS</option>
            </select>
          </div>
          <label class="flex items-center gap-1.5 cursor-pointer text-sm">
            <input type="checkbox" v-model="buildSummary" class="w-4 h-4 rounded border-gray-300 text-primary-600">
            <span class="font-bold">buildSummary</span>
          </label>
          <label class="flex items-center gap-1.5 cursor-pointer text-sm">
            <input type="checkbox" v-model="active" class="w-4 h-4 rounded border-gray-300 text-primary-600">
            <span class="font-bold">Активно (UI)</span>
          </label>
        </div>

        <!-- Имя таблицы -->
        <div class="card p-3 mb-4">
          <label class="font-medium text-gray-700 text-sm">Имя таблицы ClickHouse</label>
          <input type="text" v-model="tableName" @input="validateTableName"
                 class="input-field mt-1 py-1.5 text-sm"
                 :class="{'border-green-500 bg-green-50': tableNameValid && tableName, 'border-red-500 bg-red-50': tableNameTouched && !tableNameValid && tableName}">
          <div v-if="tableNameTouched && tableName && !tableNameValid" class="text-red-500 text-xs mt-1">Должно начинаться с буквы</div>
        </div>

        <!-- Настройки даты -->
        <div class="card p-3 mb-4 grid grid-cols-2 gap-3">
          <div>
            <label class="font-medium text-gray-700 text-sm">Дата до (конец дня)</label>
            <input type="date" v-model="dateTo" class="input-field py-1.5 text-sm">
          </div>
          <div>
            <label class="font-medium text-gray-700 text-sm">Дней назад (≥1)</label>
            <input type="number" v-model.number="daysBack" min="1" step="1" class="input-field py-1.5 text-sm">
          </div>
        </div>

        <!-- Вкладки -->
        <div class="card overflow-hidden">
          <div class="flex border-b border-gray-200">
            <button @click="activeTab='table'"
                    class="px-3 py-1.5 text-sm font-medium transition-colors"
                    :class="activeTab==='table' ? 'text-primary-600 border-b-2 border-primary-600' : 'text-gray-500 hover:text-gray-700'">
              Таблица
            </button>
            <button @click="activeTab='sql'"
                    class="px-3 py-1.5 text-sm font-medium transition-colors"
                    :class="activeTab==='sql' ? 'text-primary-600 border-b-2 border-primary-600' : 'text-gray-500 hover:text-gray-700'">
              SQL скрипт
            </button>
          </div>
          <div class="p-3">
            <div v-if="activeTab==='table'">
              <!-- Фильтры -->
              <div class="mb-3"
                   @dragover.prevent="dragOverZone = 'filter'"
                   @dragleave="dragOverZone = null"
                   @drop="dropOnZone('filter', $event)"
                   :class="{'ring-2 ring-primary-400 bg-primary-50 rounded-lg': dragOverZone === 'filter'}">
                <h3 class="font-bold text-gray-800 text-sm mb-1.5">Пользовательские фильтры</h3>
                <div class="flex flex-wrap gap-2">
                  <div v-for="(f, idx) in filterFields" :key="f.id"
                       class="inline-flex items-center gap-1.5 bg-cyan-100 text-cyan-800 px-2 py-1 rounded-full text-xs">
                    {{ f.name }}
                    <div class="filter-control inline-flex gap-1 ml-1">
                      <select v-model="f.filterType" class="text-xs bg-transparent border rounded px-1 py-0">
                        <option value="IncludeValues">IncludeValues</option>
                        <option value="ExcludeValues">ExcludeValues</option>
                        <option value="EnumValue">EnumValue</option>
                        <option value="StringValue">StringValue</option>
                      </select>
                      <template v-if="f.filterType === 'IncludeValues' || f.filterType === 'ExcludeValues'">
                        <input type="text" v-model="f.valuesString" placeholder="знач1,знач2" class="text-xs border rounded px-1 w-24 py-0" @input="parseValues(f)">
                      </template>
                      <template v-else-if="f.filterType === 'EnumValue'">
                        <input v-model="f.enumKey" placeholder="enumKey" class="text-xs border rounded px-1 w-16 py-0">
                        <input v-model="f.enumValue" placeholder="значение" class="text-xs border rounded px-1 w-20 py-0">
                      </template>
                      <template v-else-if="f.filterType === 'StringValue'">
                        <input v-model="f.value" placeholder="значение" class="text-xs border rounded px-1 w-20 py-0">
                      </template>
                    </div>
                    <button @click="removeFilter(idx)" class="text-cyan-600 hover:text-cyan-800 ml-0.5">✕</button>
                  </div>
                  <div v-if="!filterFields.length" class="text-gray-400 text-xs">Перетащите поле фильтра</div>
                </div>
              </div>

              <!-- Таблица-сетка -->
              <div class="overflow-x-auto border rounded-lg">
                <table class="min-w-full divide-y divide-gray-200 text-sm">
                  <thead>
                    <tr>
                      <th class="bg-gray-100 p-1.5 text-center border-r border-gray-200"
                          :colspan="rowFields.length || 1"
                          @dragover.prevent="dragOverZone = 'row'"
                          @dragleave="dragOverZone = null"
                          @drop="dropOnZone('row', $event)"
                          :class="{'bg-primary-50': dragOverZone === 'row'}">
                        <div class="text-xs font-bold text-gray-600">ROW</div>
                        <div class="flex flex-wrap justify-center gap-1 mt-1">
                          <div v-for="(f, idx) in rowFields" :key="f.id"
                               class="inline-flex items-center gap-1 bg-pink-100 text-pink-800 px-1.5 py-0.5 rounded-full text-xs cursor-move"
                               draggable="true"
                               @dragstart="dragStartReorder($event, f, 'row', idx)"
                               @dragend="dragEndReorder"
                               @dragover.prevent="dragOverReorder($event, 'row', idx)"
                               @dragleave="dragLeaveReorder"
                               @drop="dropReorder($event, 'row', idx)">
                            {{ f.name }}
                            <button @click="removeRow(idx)" class="text-pink-600 hover:text-pink-800">✕</button>
                          </div>
                          <span v-if="!rowFields.length" class="text-gray-400 text-xs">Перетащите категорию</span>
                        </div>
                      </th>
                      <th class="bg-gray-100 p-1.5 text-center"
                          :colspan="columnFields.length + (valueFields.length || 1)"
                          @dragover.prevent="dragOverZone = 'column'"
                          @dragleave="dragOverZone = null"
                          @drop="dropOnZone('column', $event)"
                          :class="{'bg-primary-50': dragOverZone === 'column'}">
                        <div class="text-xs font-bold text-gray-600">COLUMN</div>
                        <div class="flex flex-wrap justify-center gap-1 mt-1">
                          <div v-for="(f, idx) in columnFields" :key="f.id"
                               class="inline-flex items-center gap-1 bg-blue-100 text-blue-800 px-1.5 py-0.5 rounded-full text-xs cursor-move"
                               draggable="true"
                               @dragstart="dragStartReorder($event, f, 'column', idx)"
                               @dragend="dragEndReorder"
                               @dragover.prevent="dragOverReorder($event, 'column', idx)"
                               @dragleave="dragLeaveReorder"
                               @drop="dropReorder($event, 'column', idx)">
                            {{ f.name }}
                            <button @click="removeColumn(idx)" class="text-blue-600 hover:text-blue-800">✕</button>
                          </div>
                          <span v-if="!columnFields.length" class="text-gray-400 text-xs">Перетащите категорию</span>
                        </div>
                      </th>
                    </tr>
                    <tr>
                      <th v-for="rf in rowFields" :key="'rh'+rf.id" class="bg-gray-50 p-1.5 text-left text-xs font-medium text-gray-500 border-r">{{ rf.name }}</th>
                      <th v-for="cf in columnFields" :key="'ch'+cf.id" class="bg-gray-50 p-1.5 text-left text-xs font-medium text-gray-500">{{ cf.name }}</th>
                      <th class="bg-gray-100 p-1.5 text-center"
                          :colspan="valueFields.length || 1"
                          @dragover.prevent="dragOverZone = 'value'"
                          @dragleave="dragOverZone = null"
                          @drop="dropOnZone('value', $event)"
                          :class="{'bg-primary-50': dragOverZone === 'value'}">
                        <div class="text-xs font-bold text-gray-600">VALUES</div>
                        <div class="flex flex-wrap justify-center gap-1 mt-1">
                          <div v-for="(f, idx) in valueFields" :key="f.id"
                               class="inline-flex items-center gap-1 bg-amber-100 text-amber-800 px-1.5 py-0.5 rounded-full text-xs cursor-move"
                               draggable="true"
                               @dragstart="dragStartReorder($event, f, 'value', idx)"
                               @dragend="dragEndReorder"
                               @dragover.prevent="dragOverReorder($event, 'value', idx)"
                               @dragleave="dragLeaveReorder"
                               @drop="dropReorder($event, 'value', idx)">
                            {{ f.name }}
                            <select v-model="f.aggregation" class="text-xs bg-transparent border rounded px-0.5 py-0" @click.stop>
                              <option value="sum">SUM</option>
                              <option value="avg">AVG</option>
                              <option value="count">COUNT</option>
                            </select>
                            <button @click="removeValue(idx)" class="text-amber-600 hover:text-amber-800">✕</button>
                          </div>
                          <span v-if="!valueFields.length" class="text-gray-400 text-xs">Перетащите число</span>
                        </div>
                      </th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr v-for="i in 3" :key="i" class="border-t">
                      <td v-for="rf in rowFields" :key="'rv'+rf.id" class="p-1.5 text-xs text-gray-400 border-r">—</td>
                      <td v-for="cf in columnFields" :key="'cv'+cf.id" class="p-1.5 text-xs text-gray-400">—</td>
                      <td v-for="vf in valueFields" :key="'vv'+vf.id" class="p-1.5 text-xs font-bold text-purple-700">—</td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </div>

            <div v-if="activeTab==='sql'">
              <div class="flex justify-between items-center mb-2">
                <h3 class="font-bold text-gray-800 text-sm">Скрипт для ClickHouse</h3>
                <button @click="copySQL" class="btn-secondary text-xs py-1 px-2">Копировать SQL</button>
              </div>
              <div class="bg-gray-900 text-gray-200 p-3 rounded-lg overflow-x-auto font-mono text-xs whitespace-pre-wrap">
                <pre>{{ sqlScript }}</pre>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- Модалка подтверждения сброса (без изменений) -->
    <Transition name="fade">
      <div v-if="resetModal.show" class="fixed inset-0 z-50 overflow-y-auto" @click.self="resetModal.show = false">
        <div class="fixed inset-0 bg-black/50 backdrop-blur-sm"></div>
        <div class="flex items-center justify-center min-h-screen p-4">
          <div class="relative bg-white rounded-2xl shadow-xl max-w-md w-full">
            <div class="p-6 text-center">
              <div class="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-red-100 mb-4">
                <svg class="h-6 w-6 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
                </svg>
              </div>
              <h3 class="text-lg font-medium text-gray-900 mb-2">Сброс всех настроек</h3>
              <p class="text-sm text-gray-500 mb-6">Вы уверены? Все выбранные поля, фильтры настройки будут удалены.</p>
              <div class="flex justify-center space-x-3">
                <button @click="resetModal.show = false" class="btn-secondary">Отмена</button>
                <button @click="confirmReset" class="bg-red-600 text-white px-4 py-2 rounded-lg hover:bg-red-700">Сбросить</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </Transition>
  </AppLayout>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue'
import AppLayout from '@/components/Layout/AppLayout.vue'
import { useNotification } from '@/composables/useNotification'

const { showNotification } = useNotification()

// Типы (без изменений)
interface ApiColumn {
  fieldKey: string
  fieldKeyNormal: string
  name: string
  aggregationAllowed: boolean
  groupingAllowed: boolean
  filteringAllowed: boolean
  tags: string[]
  reportTypes: string[]
}

interface BaseField {
  id: string
  fieldKey: string
  fieldKeyNormal: string
  name: string
  tags: string[]
}

interface NumberField extends BaseField {
  role: 'number'
  aggregation: 'sum' | 'avg' | 'count'
}

interface CategoryField extends BaseField {
  role: 'category'
}

interface FilterField extends BaseField {
  role: 'filter'
  filterType: 'IncludeValues' | 'ExcludeValues' | 'EnumValue' | 'StringValue'
  valuesString: string
  values: string[]
  enumKey: string
  enumValue: string
  value: string
}

type AvailableField = NumberField | CategoryField | FilterField

interface IikoConfigFilter {
  filterType: string
  values?: string[]
  enumKey?: string
  enumValue?: string
  value?: string
  from?: string
  to?: string
  periodType?: string
}

interface IikoConfig {
  reportType: string
  buildSummary: boolean
  groupByRowFields: string[]
  groupByColFields: string[]
  aggregateFields: string[]
  filters: Record<string, IikoConfigFilter>
}

// Refs
const columnsData = ref<ApiColumn[]>([])
const loading = ref(true)
const error = ref<string | null>(null)

const rowFields = ref<CategoryField[]>([])
const columnFields = ref<CategoryField[]>([])
const valueFields = ref<NumberField[]>([])
const filterFields = ref<FilterField[]>([])
const availableFields = ref<AvailableField[]>([])

const dateTo = ref('')
const daysBack = ref(7)
const active = ref(true)
const tableName = ref('')
const tableNameValid = ref(true)
const tableNameTouched = ref(false)
const reportType = ref<'SALES' | 'DELIVERIES' | 'TRANSACTIONS'>('SALES')
const buildSummary = ref(false)
const searchQuery = ref('')
const activeTab = ref<'table' | 'sql'>('table')

// Состояние сворачивания секций
const collapsed = ref({
  number: false,
  category: false,
  filter: false
})

// Метод переключения
const toggleSection = (section: 'number' | 'category' | 'filter') => {
  collapsed.value[section] = !collapsed.value[section]
}

// Модалка сброса
const resetModal = ref({ show: false })

// Drag & drop state (без изменений)
let draggedItem: AvailableField | null = null
let draggedFromSidebar = true
const dragOverZone = ref<string | null>(null)
let dragReorderItem: CategoryField | NumberField | null = null
let dragReorderType: string | null = null
let dragReorderFromIdx: number | null = null

// Функции (без изменений, кроме удаления collapsed)
const buildAvailableFields = (): AvailableField[] => {
  if (!columnsData.value.length) return []
  const selected = reportType.value
  const result: AvailableField[] = []
  for (const col of columnsData.value) {
    const okForReport = !col.reportTypes || col.reportTypes.length === 0 || col.reportTypes.includes(selected)
    if (!okForReport) continue

    if (col.aggregationAllowed) {
      result.push({
        id: `${col.fieldKey}_number`,
        fieldKey: col.fieldKey,
        fieldKeyNormal: col.fieldKeyNormal,
        name: col.name,
        role: 'number',
        tags: col.tags || [],
        aggregation: 'sum'
      } as NumberField)
    }
    if (col.groupingAllowed) {
      result.push({
        id: `${col.fieldKey}_category`,
        fieldKey: col.fieldKey,
        fieldKeyNormal: col.fieldKeyNormal,
        name: col.name,
        role: 'category',
        tags: col.tags || []
      } as CategoryField)
    }
    if (col.filteringAllowed) {
      result.push({
        id: `${col.fieldKey}_filter`,
        fieldKey: col.fieldKey,
        fieldKeyNormal: col.fieldKeyNormal,
        name: col.name,
        role: 'filter',
        tags: col.tags || []
      } as FilterField)
    }
  }
  return result
}

const refreshFieldsAndReset = () => {
  availableFields.value = buildAvailableFields()
  rowFields.value = []
  columnFields.value = []
  valueFields.value = []
  filterFields.value = []
}

const fetchColumns = async () => {
  loading.value = true
  error.value = null
  try {
    const response = await fetch('/api/reports/olap/columns')
    if (!response.ok) throw new Error(`HTTP ${response.status}`)
    const data = await response.json()
    columnsData.value = data.columns || []
    refreshFieldsAndReset()
  } catch (err: any) {
    console.error(err)
    error.value = `Ошибка загрузки полей: ${err.message}`
    showNotification(error.value, 'error')
    columnsData.value = []
    refreshFieldsAndReset()
  } finally {
    loading.value = false
  }
}

watch(reportType, () => {
  refreshFieldsAndReset()
})

const matchesSearch = (f: AvailableField): boolean => {
  if (!searchQuery.value.trim()) return true
  const terms = searchQuery.value.toLowerCase().split(/\s+/)
  const nameMatch = terms.some(t => f.name.toLowerCase().includes(t))
  const tagsMatch = f.tags ? terms.some(t => f.tags.some(tag => tag.toLowerCase().includes(t))) : false
  return nameMatch || tagsMatch
}

const filteredAvailableFields = computed(() => availableFields.value.filter(matchesSearch))
const filteredNumberFields = computed(() => availableFields.value.filter((f): f is NumberField => f.role === 'number' && matchesSearch(f)))
const filteredCategoryFields = computed(() => availableFields.value.filter((f): f is CategoryField => f.role === 'category' && matchesSearch(f)))
const filteredFilterFields = computed(() => availableFields.value.filter((f): f is FilterField => f.role === 'filter' && matchesSearch(f)))

const validateTableName = () => {
  tableNameTouched.value = true
  if (!tableName.value) { tableNameValid.value = true; return }
  tableNameValid.value = /^[A-Za-zА-Яа-я]/.test(tableName.value)
}

const parseValues = (f: FilterField) => {
  f.values = f.valuesString ? f.valuesString.split(',').map(s => s.trim()).filter(s => s) : []
}

const createNewFilter = (src: FilterField): FilterField => ({
  ...src,
  id: Date.now() + Math.random().toString(),
  filterType: 'IncludeValues',
  valuesString: '',
  values: [],
  enumKey: '',
  enumValue: '',
  value: ''
})

const dragStart = (e: DragEvent, f: AvailableField) => {
  draggedItem = f
  draggedFromSidebar = true
  e.dataTransfer!.effectAllowed = 'copy'
  const target = e.target as HTMLElement
  target.classList.add('opacity-40')
}

const dragEnd = (e: DragEvent) => {
  const target = e.target as HTMLElement
  target.classList.remove('opacity-40')
  draggedItem = null
  draggedFromSidebar = true
  dragOverZone.value = null
}

const dropOnZone = (zone: string, e: DragEvent) => {
  e.preventDefault()
  dragOverZone.value = null
  if (!draggedItem || !draggedFromSidebar) return
  const item = draggedItem
  if (zone === 'row' && item.role !== 'category') return
  if (zone === 'column' && item.role !== 'category') return
  if (zone === 'value' && item.role !== 'number') return
  if (zone === 'filter' && item.role !== 'filter') return

  const idx = availableFields.value.findIndex(f => f.id === item.id)
  if (idx === -1) return
  availableFields.value.splice(idx, 1)

  if (zone === 'filter') {
    const newField = createNewFilter(item as FilterField)
    filterFields.value.push(newField)
  } else if (zone === 'value') {
    const newField: NumberField = { ...(item as NumberField), id: Date.now() + Math.random().toString(), aggregation: 'sum' }
    valueFields.value.push(newField)
  } else {
    const newField = { ...item, id: Date.now() + Math.random().toString() } as CategoryField
    if (zone === 'row') rowFields.value.push(newField)
    else if (zone === 'column') columnFields.value.push(newField)
  }
  draggedItem = null
}

const dragStartReorder = (e: DragEvent, f: CategoryField | NumberField, type: string, idx: number) => {
  e.dataTransfer!.effectAllowed = 'move'
  dragReorderItem = f
  dragReorderType = type
  dragReorderFromIdx = idx
  const target = e.target as HTMLElement
  target.classList.add('opacity-40')
}

const dragEndReorder = (e: DragEvent) => {
  const target = e.target as HTMLElement
  target.classList.remove('opacity-40')
  dragReorderItem = null
  dragReorderType = null
  dragReorderFromIdx = null
}

const dragOverReorder = (e: DragEvent, type: string, idx: number) => {
  e.preventDefault()
  if (dragReorderType !== type) return
  if (dragReorderFromIdx === idx) return
  const target = e.target as HTMLElement
  const chip = target.closest('.cursor-move') as HTMLElement
  if (chip) chip.classList.add('ring-2', 'ring-primary-400')
}

const dragLeaveReorder = (e: DragEvent) => {
  const target = e.target as HTMLElement
  const chip = target.closest('.cursor-move') as HTMLElement
  if (chip) chip.classList.remove('ring-2', 'ring-primary-400')
}

const dropReorder = (e: DragEvent, type: string, toIdx: number) => {
  e.preventDefault()
  const target = e.target as HTMLElement
  const chip = target.closest('.cursor-move') as HTMLElement
  if (chip) chip.classList.remove('ring-2', 'ring-primary-400')
  if (dragReorderType !== type) return
  let arr: (CategoryField | NumberField)[]
  if (type === 'row') arr = rowFields.value
  else if (type === 'column') arr = columnFields.value
  else if (type === 'value') arr = valueFields.value
  else return
  const fromIdx = dragReorderFromIdx!
  const item = arr[fromIdx]
  arr.splice(fromIdx, 1)
  arr.splice(toIdx, 0, item)
  dragReorderItem = null
  dragReorderType = null
  dragReorderFromIdx = null
}

const restoreFieldToAvailable = (field: AvailableField, expectedRole: string) => {
  const exists = availableFields.value.some(f => f.fieldKey === field.fieldKey && f.role === expectedRole)
  if (!exists) {
    const originalCol = columnsData.value.find(c => c.fieldKey === field.fieldKey)
    if (originalCol) {
      if (expectedRole === 'number' && originalCol.aggregationAllowed) {
        availableFields.value.push({
          id: `${field.fieldKey}_number`,
          fieldKey: field.fieldKey,
          fieldKeyNormal: originalCol.fieldKeyNormal,
          name: originalCol.name,
          role: 'number',
          tags: originalCol.tags || [],
          aggregation: 'sum'
        } as NumberField)
      } else if (expectedRole === 'category' && originalCol.groupingAllowed) {
        availableFields.value.push({
          id: `${field.fieldKey}_category`,
          fieldKey: field.fieldKey,
          fieldKeyNormal: originalCol.fieldKeyNormal,
          name: originalCol.name,
          role: 'category',
          tags: originalCol.tags || []
        } as CategoryField)
      } else if (expectedRole === 'filter' && originalCol.filteringAllowed) {
        availableFields.value.push({
          id: `${field.fieldKey}_filter`,
          fieldKey: field.fieldKey,
          fieldKeyNormal: originalCol.fieldKeyNormal,
          name: originalCol.name,
          role: 'filter',
          tags: originalCol.tags || []
        } as FilterField)
      }
    } else {
      availableFields.value.push({ ...field, id: `${field.fieldKey}_${expectedRole}` } as AvailableField)
    }
  }
}

const removeRow = (idx: number) => {
  const f = rowFields.value[idx]
  rowFields.value.splice(idx, 1)
  restoreFieldToAvailable(f, 'category')
}

const removeColumn = (idx: number) => {
  const f = columnFields.value[idx]
  columnFields.value.splice(idx, 1)
  restoreFieldToAvailable(f, 'category')
}

const removeValue = (idx: number) => {
  const f = valueFields.value[idx]
  valueFields.value.splice(idx, 1)
  restoreFieldToAvailable(f, 'number')
}

const removeFilter = (idx: number) => {
  const f = filterFields.value[idx]
  filterFields.value.splice(idx, 1)
  restoreFieldToAvailable(f, 'filter')
}

const openResetModal = () => {
  resetModal.value.show = true
}

const confirmReset = () => {
  resetModal.value.show = false
  refreshFieldsAndReset()
  dateTo.value = ''
  daysBack.value = 7
  active.value = true
  tableName.value = ''
  tableNameValid.value = true
  tableNameTouched.value = false
  buildSummary.value = true
  searchQuery.value = ''
  showNotification('Все настройки сброшены', 'success')
}

const saveConfigAsJson = () => {
  const userFilters: Record<string, IikoConfigFilter> = {}
  filterFields.value.forEach(f => {
    if (f.filterType === 'IncludeValues' || f.filterType === 'ExcludeValues') {
      userFilters[f.fieldKey] = { filterType: f.filterType, values: f.values || [] }
    } else if (f.filterType === 'EnumValue') {
      userFilters[f.fieldKey] = { filterType: 'EnumValue', enumKey: f.enumKey || '', enumValue: f.enumValue || '' }
    } else if (f.filterType === 'StringValue') {
      userFilters[f.fieldKey] = { filterType: 'StringValue', value: f.value || '' }
    }
  })

  const getDateFilter = (): Record<string, IikoConfigFilter> => {
    let toDate = dateTo.value ? new Date(dateTo.value) : new Date()
    toDate.setHours(23, 59, 59, 999)
    let fromDate = new Date(toDate)
    const days = Math.max(1, daysBack.value || 1)
    fromDate.setDate(toDate.getDate() - days)
    fromDate.setHours(0, 0, 0, 0)
    const formatDateTime = (date: Date) => date.toISOString()
    const filterKey = reportType.value === 'TRANSACTIONS' ? 'DateTime.DateTyped' : 'OpenDate.Typed'
    return { [filterKey]: { filterType: "DateRange", periodType: "CUSTOM", from: formatDateTime(fromDate), to: formatDateTime(toDate) } }
  }

  const systemFilters: Record<string, IikoConfigFilter> = {
    "DeletedWithWriteoff": { filterType: "ExcludeValues", values: ["DELETED_WITH_WRITEOFF", "DELETED_WITHOUT_WRITEOFF"] },
    "OrderDeleted": { filterType: "IncludeValues", values: ["NOT_DELETED"] }
  }
  const allFilters = { ...userFilters, ...getDateFilter(), ...systemFilters }

  const config: IikoConfig = {
    reportType: reportType.value,
    buildSummary: buildSummary.value,
    groupByRowFields: rowFields.value.map(f => f.fieldKey),
    groupByColFields: columnFields.value.map(f => f.fieldKey),
    aggregateFields: valueFields.value.map(f => f.fieldKey),
    filters: allFilters
  }
  const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `iiko_olap_${reportType.value.toLowerCase()}.json`
  a.click()
  URL.revokeObjectURL(url)
  showNotification('JSON для iiko API сохранён', 'success')
}

const loadConfigFromJson = (event: Event) => {
  const input = event.target as HTMLInputElement
  const file = input.files?.[0]
  if (!file) return
  const reader = new FileReader()
  reader.onload = (e) => {
    try {
      const config: IikoConfig = JSON.parse(e.target?.result as string)
      if (config.reportType) reportType.value = config.reportType as 'SALES' | 'DELIVERIES' | 'TRANSACTIONS'
      if (typeof config.buildSummary === 'boolean') buildSummary.value = config.buildSummary

      const filterKey = reportType.value === 'TRANSACTIONS' ? 'DateTime.DateTyped' : 'OpenDate.Typed'
      const dateFilter = config.filters?.[filterKey]
      if (dateFilter && dateFilter.filterType === 'DateRange') {
        if (dateFilter.to) {
          const toD = new Date(dateFilter.to)
          if (!isNaN(toD.getTime())) dateTo.value = toD.toISOString().split('T')[0]
        }
        if (dateFilter.from && dateFilter.to) {
          const fromD = new Date(dateFilter.from), toD = new Date(dateFilter.to)
          const diff = Math.ceil((toD.getTime() - fromD.getTime()) / (1000 * 3600 * 24))
          if (diff > 0) daysBack.value = diff
        }
      }

      refreshFieldsAndReset()

      const addFieldByKey = (zoneType: string, fieldKey: string, expectedRole: string, extra: Partial<NumberField> = {}) => {
        const found = availableFields.value.find(f => f.fieldKey === fieldKey && f.role === expectedRole)
        if (found) {
          const idx = availableFields.value.indexOf(found)
          availableFields.value.splice(idx, 1)
          const newField = { ...found, id: Date.now() + Math.random().toString(), ...extra } as AvailableField
          if (zoneType === 'row') rowFields.value.push(newField as CategoryField)
          else if (zoneType === 'column') columnFields.value.push(newField as CategoryField)
          else if (zoneType === 'value') valueFields.value.push(newField as NumberField)
          else if (zoneType === 'filter') filterFields.value.push(newField as FilterField)
        }
      }

      if (config.groupByRowFields) config.groupByRowFields.forEach(fk => addFieldByKey('row', fk, 'category'))
      if (config.groupByColFields) config.groupByColFields.forEach(fk => addFieldByKey('column', fk, 'category'))
      if (config.aggregateFields) config.aggregateFields.forEach(fk => addFieldByKey('value', fk, 'number', { aggregation: 'sum' }))

      if (config.filters) {
        Object.entries(config.filters).forEach(([fk, filterDef]) => {
          if (fk === 'OpenDate.Typed' || fk === 'DateTime.DateTyped' || fk === 'DeletedWithWriteoff' || fk === 'OrderDeleted') return
          const availableFilter = availableFields.value.find(f => f.fieldKey === fk && f.role === 'filter') as FilterField | undefined
          if (availableFilter) {
            const idx = availableFields.value.indexOf(availableFilter)
            availableFields.value.splice(idx, 1)
            const newFilter = createNewFilter(availableFilter)
            newFilter.filterType = filterDef.filterType as FilterField['filterType']
            if (filterDef.filterType === 'IncludeValues' || filterDef.filterType === 'ExcludeValues') {
              newFilter.values = filterDef.values || []
              newFilter.valuesString = newFilter.values.join(', ')
            } else if (filterDef.filterType === 'EnumValue') {
              newFilter.enumKey = filterDef.enumKey || ''
              newFilter.enumValue = filterDef.enumValue || ''
            } else if (filterDef.filterType === 'StringValue') {
              newFilter.value = filterDef.value || ''
            }
            filterFields.value.push(newFilter)
          }
        })
      }
      showNotification('Конфигурация iiko загружена', 'success')
    } catch (err: any) {
      showNotification('Ошибка при загрузке JSON: ' + err.message, 'error')
    }
    input.value = ''
  }
  reader.readAsText(file)
}

const sqlScript = computed(() => {
  const dateCol = reportType.value === 'TRANSACTIONS' ? 'DateTime_DateTyped' : 'OpenDate_Typed'
  const columns: { name: string; type: string }[] = [{ name: dateCol, type: 'Date' }]
  rowFields.value.forEach(rf => columns.push({ name: rf.fieldKeyNormal, type: 'String' }))
  columnFields.value.forEach(cf => columns.push({ name: cf.fieldKeyNormal, type: 'String' }))
  valueFields.value.forEach(vf => columns.push({ name: vf.fieldKeyNormal, type: 'Int64' }))
  if (columns.length === 1) columns.push({ name: 'dummy', type: 'String' })
  let table = tableName.value.trim() || 'olap_table'
  table = table.replace(/[^a-zA-Z0-9_]/g, '_')
  if (!table.match(/^[a-zA-Z_]/)) table = '_' + table
  const fullTable = `\`default\`.\`${table}\``
  const colDefs = columns.map(c => `    \`${c.name}\` ${c.type}`).join(',\n')
  const orderBy = `\`${dateCol}\``
  const colNames = columns.map(c => `\`${c.name}\``).join(', ')
  return `CREATE TABLE IF NOT EXISTS ${fullTable} (\n${colDefs}\n) ENGINE = ReplacingMergeTree()\nORDER BY (${orderBy})\nSETTINGS index_granularity = 8192;\n\nINSERT INTO ${fullTable} (${colNames}) VALUES\n`
})

const copySQL = () => {
  navigator.clipboard.writeText(sqlScript.value)
  showNotification('SQL скрипт скопирован', 'success')
}

onMounted(() => {
  fetchColumns()
})
</script>

<style scoped>
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.2s ease;
}
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

/* Стили для скроллбара внутри левой панели */
.overflow-y-auto::-webkit-scrollbar {
  width: 6px;
}
.overflow-y-auto::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 4px;
}
.overflow-y-auto::-webkit-scrollbar-thumb {
  background: #cbd5e1;
  border-radius: 4px;
}
</style>
