<template>
  <section class="chart-block-config-form">
    <el-tabs v-model="activeTab">
      <el-tab-pane label="数据" name="data">
        <el-form label-position="top">
          <el-form-item label="数据表" required :error="errorFor('table')">
            <el-select
              :model-value="dataset.table || ''"
              filterable
              placeholder="选择数据表"
              @change="changeTable"
            >
              <el-option
                v-for="table in tables"
                :key="table.tableName"
                :label="table.tableComment || table.tableName"
                :value="table.tableName"
              />
            </el-select>
          </el-form-item>

          <template v-if="definition.chartType !== 'metric'">
            <el-form-item label="维度字段" required :error="errorFor('dimension.field')">
              <el-select
                :model-value="dataset.dimension?.field || ''"
                filterable
                placeholder="选择维度字段"
                @change="patchDimension({ field: $event, timeUnit: '' })"
              >
                <el-option
                  v-for="column in columns"
                  :key="fieldKey(column)"
                  :label="column.columnComment || column.javaField || column.columnName"
                  :value="fieldKey(column)"
                />
              </el-select>
            </el-form-item>

            <el-form-item v-if="selectedDimensionIsTemporal" label="时间粒度">
              <el-select
                :model-value="dataset.dimension?.timeUnit || ''"
                clearable
                @change="patchDimension({ timeUnit: $event })"
              >
                <el-option label="按天" value="day" />
                <el-option label="按周" value="week" />
                <el-option label="按月" value="month" />
              </el-select>
            </el-form-item>
          </template>

          <el-form-item label="指标" required :error="errorFor('metrics')">
            <div class="metric-list">
              <div v-for="(metric, index) in metrics" :key="index" class="metric-row">
                <el-select
                  :model-value="metric.field || ''"
                  clearable
                  filterable
                  placeholder="字段；COUNT 可留空"
                  @change="updateMetric(index, { field: $event, aggregate: defaultAggregate($event) })"
                >
                  <el-option label="整表计数" value="" />
                  <el-option
                    v-for="column in columns"
                    :key="fieldKey(column)"
                    :label="column.columnComment || column.javaField || column.columnName"
                    :value="fieldKey(column)"
                  />
                </el-select>
                <el-select
                  :model-value="metric.aggregate || 'count'"
                  @change="updateMetric(index, { aggregate: $event })"
                >
                  <el-option
                    v-for="option in aggregateOptions(columnByField(metric.field))"
                    :key="option.value"
                    :label="option.label"
                    :value="option.value"
                  />
                </el-select>
                <el-input
                  :model-value="metric.label || ''"
                  placeholder="显示名称"
                  @input="updateMetric(index, { label: $event })"
                />
                <el-button
                  v-if="metrics.length > 1"
                  type="danger"
                  link
                  @click="removeMetric(index)"
                >删除</el-button>
              </div>
              <el-button v-if="canAddMetric" @click="addMetric">+ 添加指标</el-button>
            </div>
          </el-form-item>

          <el-form-item label="筛选条件">
            <ChartFilterEditor
              :model-value="dataset.filters || []"
              :columns="columns"
              @update:model-value="patchDataset({ filters: $event })"
            />
          </el-form-item>

          <el-form-item label="日期范围">
            <div class="date-range-row">
              <el-select
                :model-value="dataset.dateRange?.field || ''"
                clearable
                placeholder="日期字段"
                @change="changeDateRangeField"
              >
                <el-option
                  v-for="column in temporalColumns"
                  :key="fieldKey(column)"
                  :label="column.columnComment || column.javaField || column.columnName"
                  :value="fieldKey(column)"
                />
              </el-select>
              <el-select
                v-if="dataset.dateRange?.field"
                :model-value="dataset.dateRange?.preset || 'last_30_days'"
                @change="patchDateRange({ preset: $event })"
              >
                <el-option label="今天" value="today" />
                <el-option label="最近 7 天" value="last_7_days" />
                <el-option label="最近 30 天" value="last_30_days" />
                <el-option label="本月" value="this_month" />
                <el-option label="本年" value="this_year" />
                <el-option label="固定日期" value="fixed" />
              </el-select>
              <el-date-picker
                v-if="dataset.dateRange?.preset === 'fixed'"
                :model-value="[dataset.dateRange?.start, dataset.dateRange?.end]"
                type="daterange"
                value-format="YYYY-MM-DD"
                @change="changeFixedDateRange"
              />
            </div>
          </el-form-item>

          <div v-if="definition.chartType !== 'metric'" class="form-grid">
            <el-form-item label="排序依据">
              <el-select
                :model-value="dataset.sort?.by || 'dimension'"
                @change="patchSort({ by: $event })"
              >
                <el-option label="维度" value="dimension" />
                <el-option
                  v-for="metric in metrics"
                  :key="metric.alias"
                  :label="metric.label || metric.alias"
                  :value="metric.alias"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="排序方向">
              <el-select
                :model-value="dataset.sort?.order || 'asc'"
                @change="patchSort({ order: $event })"
              >
                <el-option label="升序" value="asc" />
                <el-option label="降序" value="desc" />
              </el-select>
            </el-form-item>
          </div>

          <div class="form-grid">
            <el-form-item label="分组上限">
              <el-input-number
                :model-value="dataset.limit || defaultLimit"
                :min="1"
                :max="500"
                @change="patchDataset({ limit: $event })"
              />
            </el-form-item>
            <el-form-item label="块宽度">
              <el-select :model-value="span" @change="emit('update:span', $event)">
                <el-option label="整行" :value="12" />
                <el-option label="半行" :value="6" />
                <el-option label="三分之一" :value="4" />
              </el-select>
            </el-form-item>
          </div>
        </el-form>
      </el-tab-pane>

      <el-tab-pane label="展示" name="display">
        <el-form label-position="top">
          <el-form-item label="空数据文案">
            <el-input
              :model-value="display.emptyText || '暂无数据'"
              @input="patchDisplay({ emptyText: $event })"
            />
          </el-form-item>
          <el-form-item label="显示标题">
            <el-switch
              :model-value="display.showTitle !== false"
              @change="patchDisplay({ showTitle: $event })"
            />
          </el-form-item>
          <el-form-item v-if="definition.chartType !== 'metric'" label="显示图例">
            <el-switch
              :model-value="display.showLegend !== false"
              @change="patchDisplay({ showLegend: $event })"
            />
          </el-form-item>
          <el-form-item v-if="definition.chartType === 'line'" label="平滑曲线">
            <el-switch
              :model-value="Boolean(display.smooth)"
              @change="patchDisplay({ smooth: $event })"
            />
          </el-form-item>
          <el-form-item v-if="definition.chartType === 'line'" label="面积填充">
            <el-switch
              :model-value="Boolean(display.area)"
              @change="patchDisplay({ area: $event })"
            />
          </el-form-item>
          <el-form-item v-if="definition.chartType === 'bar'" label="横向柱状图">
            <el-switch
              :model-value="Boolean(display.horizontal)"
              @change="patchDisplay({ horizontal: $event })"
            />
          </el-form-item>
          <el-form-item v-if="definition.chartType === 'bar'" label="堆叠">
            <el-switch
              :model-value="Boolean(display.stacked)"
              @change="patchDisplay({ stacked: $event })"
            />
          </el-form-item>
          <el-form-item v-if="definition.chartType === 'pie'" label="环形图">
            <el-switch
              :model-value="display.donut !== false"
              @change="patchDisplay({ donut: $event })"
            />
          </el-form-item>
          <el-form-item v-if="definition.chartType === 'pie'" label="显示标签">
            <el-switch
              :model-value="display.showLabel !== false"
              @change="patchDisplay({ showLabel: $event })"
            />
          </el-form-item>
        </el-form>
      </el-tab-pane>

      <el-tab-pane label="权限" name="permission">
        <el-alert
          title="继承所在后台页面；一期不支持块级覆盖"
          type="info"
          :closable="false"
          show-icon
        />
      </el-tab-pane>
    </el-tabs>
  </section>
</template>

<script setup>
import { computed, ref } from 'vue'
import ChartFilterEditor from './ChartFilterEditor.vue'

const props = defineProps({
  definition: { type: Object, required: true },
  dataset: { type: Object, default: () => ({}) },
  display: { type: Object, default: () => ({}) },
  span: { type: Number, default: 12 },
  tables: { type: Array, default: () => [] },
  errors: { type: Array, default: () => [] }
})

const emit = defineEmits(['update:dataset', 'update:display', 'update:span'])
const activeTab = ref('data')
const metrics = computed(() => props.dataset.metrics || [])
const selectedTable = computed(() => props.tables.find((item) => item.tableName === props.dataset.table) || null)
const columns = computed(() => selectedTable.value?.columns || selectedTable.value?.table?.columns || [])
const temporalColumns = computed(() => columns.value.filter(isTemporal))
const selectedDimensionIsTemporal = computed(() => isTemporal(columnByField(props.dataset.dimension?.field)))
const maxMetrics = computed(() => ['metric', 'pie'].includes(props.definition.chartType) ? 1 : 3)
const canAddMetric = computed(() => metrics.value.length < maxMetrics.value)
const defaultLimit = computed(() => {
  if (props.definition.chartType === 'metric') return 1
  if (props.definition.chartType === 'pie') return 10
  if (props.definition.chartType === 'bar') return 20
  return 100
})

function patchDataset(patch) {
  emit('update:dataset', { ...props.dataset, ...patch })
}

function patchDisplay(patch) {
  emit('update:display', { ...props.display, ...patch })
}

function changeTable(table) {
  patchDataset({
    table,
    dimension: props.definition.chartType === 'metric' ? null : { field: '', timeUnit: '' },
    metrics: [{
      field: '',
      aggregate: props.definition.chartType === 'metric' ? 'count' : 'sum',
      alias: 'metric1',
      label: '指标 1'
    }],
    filters: [],
    dateRange: null
  })
}

function patchDimension(patch) {
  patchDataset({ dimension: { ...(props.dataset.dimension || {}), ...patch } })
}

function addMetric() {
  if (!canAddMetric.value) return
  const index = metrics.value.length + 1
  patchDataset({
    metrics: metrics.value.concat({
      field: '',
      aggregate: 'sum',
      alias: `metric${index}`,
      label: `指标 ${index}`
    })
  })
}

function updateMetric(index, patch) {
  patchDataset({
    metrics: metrics.value.map((metric, currentIndex) => (
      currentIndex === index ? { ...metric, ...patch } : metric
    ))
  })
}

function removeMetric(index) {
  patchDataset({ metrics: metrics.value.filter((_, currentIndex) => currentIndex !== index) })
}

function aggregateOptions(column) {
  const numeric = ['Integer', 'Long', 'Double', 'Float', 'Short', 'BigDecimal']
    .includes(column?.javaType)
  return numeric
    ? [
        { value: 'count', label: '计数' },
        { value: 'sum', label: '求和' },
        { value: 'avg', label: '平均值' }
      ]
    : [{ value: 'count', label: '计数' }]
}

function defaultAggregate(field) {
  return columnByField(field) && aggregateOptions(columnByField(field)).some((item) => item.value === 'sum')
    ? 'sum'
    : 'count'
}

function changeDateRangeField(field) {
  patchDataset({
    dateRange: field ? { field, preset: 'last_30_days', start: '', end: '' } : null
  })
}

function patchDateRange(patch) {
  patchDataset({ dateRange: { ...(props.dataset.dateRange || {}), ...patch } })
}

function changeFixedDateRange(value) {
  const [start = '', end = ''] = Array.isArray(value) ? value : []
  patchDateRange({ start, end })
}

function patchSort(patch) {
  patchDataset({ sort: { ...(props.dataset.sort || { by: 'dimension', order: 'asc' }), ...patch } })
}

function errorFor(key) {
  return props.errors.find((item) => item.key === key)?.message || ''
}

function columnByField(field) {
  return columns.value.find((column) => fieldKey(column) === field) || null
}

function fieldKey(column) {
  return column?.javaField || column?.columnName || ''
}

function isTemporal(column) {
  const type = String(column?.columnType || '').toLowerCase()
  return ['Date', 'LocalDate', 'LocalDateTime'].includes(column?.javaType)
    || type.includes('date')
    || type.includes('time')
    || type.includes('timestamp')
    || type.includes('year')
}
</script>

<style scoped lang="scss">
.chart-block-config-form {
  min-width: 0;
}

.chart-block-config-form :deep(.el-select),
.chart-block-config-form :deep(.el-input),
.chart-block-config-form :deep(.el-input-number),
.chart-block-config-form :deep(.el-date-editor) {
  width: 100%;
}

.metric-list,
.metric-row,
.date-range-row,
.form-grid {
  display: grid;
  gap: 8px;
  width: 100%;
}

.metric-row {
  grid-template-columns: minmax(130px, 1fr) minmax(90px, 0.65fr) minmax(110px, 0.8fr) auto;
  align-items: center;
}

.date-range-row {
  grid-template-columns: minmax(130px, 1fr) minmax(130px, 1fr);
}

.date-range-row :deep(.el-date-editor) {
  grid-column: 1 / -1;
}

.form-grid {
  grid-template-columns: 1fr 1fr;
}

@media (max-width: 720px) {
  .metric-row,
  .date-range-row,
  .form-grid {
    grid-template-columns: 1fr;
  }
}
</style>
