<script setup lang="ts">
import type { EventRule, EventRuleItem, RuleAttr } from '@/types'
import { Operation, Plus, CloseBold } from '@element-plus/icons-vue'
import { useMetaEvent } from '@/composables/useAllData'
import {
  stringOperatorList,
  numberOperatorList,
  dateOperatorList,
  happenInfoList,
  triggerInfoList
} from '@/utils/dictionary'
import { searchEventAttrs } from '@/api/base'

const { limit = Infinity } = defineProps<{ limit?: number }>()

// const eventAttrRule = ref(inject('eventAttrRule') as EventRule)
const eventAttrRule = defineModel<EventRule>({ default: { current_logic_operate: 'and', items: [] } })

const { metaEventList } = useMetaEvent()

const currentMetaEventList = computed(() => {
  return [{ id: '-1', name: '所有事件', event_attrs: [] }, ...metaEventList.value]
})

// 触发次数
const triggerNumberOperatorList = computed(() => {
  return numberOperatorList.filter(item => !['range', 'null', 'not null'].includes(item.value))
})

// 获取逻辑运算符名称
function getLogicalName(value: 'and' | 'or') {
  return value === 'or' ? '或' : '且'
}

// 获取运算符列表
function getOperatorList(type: string) {
  if (type === '1') return stringOperatorList
  if (type === '2' || type === '3') return numberOperatorList
  if (type === '4' || type === '5') return dateOperatorList
  return stringOperatorList
}

// 获取事件属性列表
function getEventAttrList(eventId: string) {
  return currentMetaEventList.value.find(item => item.id === eventId)?.event_attrs || []
}

// 切换逻辑运算符
function toggleOperate(rule: EventRule) {
  rule.current_logic_operate = rule.current_logic_operate === 'or' ? 'and' : 'or'
}

// 添加条件
function handleAdd(items: EventRuleItem[]) {
  items.push({
    happen_info: { is_happened: true, event_id: '', event_name: '', attr_list: [] },
    trigger_info: { operate: '', operate_name: '', value: '' }
  })
}

// 删除条件
function handleRemove(items: EventRuleItem[], index: number) {
  items.splice(index, 1)
}

// 添加属性条件
function handleAttrAdd(attrs: RuleAttr[]) {
  attrs.push({ attr_id: '', attr: '', attr_name: '', attr_type: '', operate: '', operate_name: '', value: '' })
}

// 删除属性条件
function handleAttrRemove(attrs: RuleAttr[], index: number) {
  attrs.splice(index, 1)
}

// 发生条件改变
function handleHappenOperateChange(value: string, item: EventRuleItem) {
  item.happen_info.attr_list = []
  item.trigger_info.value = ''
}

// 事件改变
function handleEventChange(value: string, item: EventRuleItem) {
  const currentEvent = currentMetaEventList.value.find(item => item.id === value)
  item.happen_info.event_name = currentEvent?.name || ''
  item.happen_info.attr_list = []
}

// 属性改变
function handleAttrChange(value: string, attr: RuleAttr, item: EventRuleItem) {
  const found = getEventAttrList(item.happen_info.event_id).find(item => item.id === value)
  attr.attr = found?.english_name || ''
  attr.attr_name = found?.name || ''
  attr.attr_type = found?.type || ''
  // 清空条件数据
  attr.operate = ''
  attr.operate_name = ''
  attr.value = ''
}

// 条件改变
function handleOperateChange(value: string, item: RuleAttr) {
  const found = getOperatorList(item.attr_type).find(item => item.value === value)
  item.operate_name = found?.label || ''
  item.value = ''
  // 区间
  if (value === 'range') {
    item.value = { start: undefined, end: undefined }
  }
}

// 触发条件改变
function handleTriggerOperateChange(value: string, item: EventRuleItem) {
  const found = numberOperatorList.find(item => item.value === value)
  item.trigger_info.operate_name = found?.label || ''
  item.trigger_info.value = ''
}

function querySearch(rule: EventRuleItem, attr: RuleAttr, search: string, cb: (arg: any) => void) {
  const found = getEventAttrList(rule.happen_info.event_id).find(item => item.id === attr.attr_id)
  const experiment_meta_event_id = found?.experiment_meta_event_id || ''
  searchEventAttrs({
    search,
    experiment_meta_event_id: experiment_meta_event_id,
    experiment_meta_event_attr_id: attr.attr_id,
    per_page: 1000
  }).then(res => {
    const list: string[] = []
    res.data.list.forEach((item: any) => {
      try {
        const fields = JSON.parse(item.fields)
        const value = fields[attr.attr_id]
        if (!list.includes(value)) list.push(value)
      } catch (error) {
        console.log(error)
      }
    })
    cb(list.map((item: string) => ({ value: item })))
  })
}

const options = ref<{ label: string; value: string }[]>([])
const loading = ref(false)
function remoteMethod(rule: EventRuleItem, attr: RuleAttr, search: string) {
  const found = getEventAttrList(rule.happen_info.event_id).find(item => item.id === attr.attr_id)
  const experiment_meta_event_id = found?.experiment_meta_event_id || ''
  loading.value = true
  searchEventAttrs({
    search,
    experiment_meta_event_id: experiment_meta_event_id,
    experiment_meta_event_attr_id: attr.attr_id,
    per_page: 1000
  }).then(res => {
    const list: string[] = []
    res.data.list.forEach((item: any) => {
      try {
        const fields = JSON.parse(item.fields)
        const value = fields[attr.attr_id]
        if (!list.includes(value)) list.push(value)
      } catch (error) {
        console.log(error)
      }
    })
    options.value = list.map((item: string) => ({ value: item, label: item }))
    loading.value = false
  })
}
</script>

<template>
  <el-card shadow="never" class="event-rule">
    <template #header>
      <el-button circle color="#f90" :icon="Operation"></el-button>
      事件属性满足以下条件
    </template>
    <div class="rule" v-if="eventAttrRule.items.length">
      <div class="rule-operator">
        <span @click="toggleOperate(eventAttrRule)">{{ getLogicalName(eventAttrRule.current_logic_operate) }}</span>
      </div>
      <div class="rule-list">
        <section class="rule-item" v-for="(rule, index) in eventAttrRule.items" :key="index">
          <el-row>
            <!-- 发生 -->
            <el-form-item>
              <el-select
                v-model="rule.happen_info.is_happened"
                @change="value => handleHappenOperateChange(value, rule)"
              >
                <el-option v-for="option in happenInfoList" :key="option.label" v-bind="option"></el-option>
              </el-select>
            </el-form-item>
            <el-form-item>
              <el-select v-model="rule.happen_info.event_id" @change="value => handleEventChange(value, rule)">
                <el-option
                  v-for="option in currentMetaEventList"
                  :key="option.id"
                  :label="option.name"
                  :value="option.id"
                ></el-option>
              </el-select>
            </el-form-item>
            <el-button text :icon="Plus" @click="handleAttrAdd(rule.happen_info.attr_list)">添加条件</el-button>
            <el-button
              text
              :icon="CloseBold"
              @click="handleRemove(eventAttrRule.items, index)"
              v-if="limit !== 1"
            ></el-button>
          </el-row>
          <!-- 属性条件 -->
          <el-row
            justify="space-between"
            class="rule-item"
            v-for="(attr, index) in rule.happen_info.attr_list"
            :key="index"
          >
            <div>
              <el-form-item>
                <el-select v-model="attr.attr_id" @change="value => handleAttrChange(value, attr, rule)">
                  <el-option
                    v-for="option in getEventAttrList(rule.happen_info.event_id)"
                    :key="option.id"
                    :label="option.name"
                    :value="option.id"
                  ></el-option>
                </el-select>
              </el-form-item>
              <el-form-item>
                <el-select v-model="attr.operate" @change="value => handleOperateChange(value, attr)">
                  <el-option
                    v-for="option in getOperatorList(attr.attr_type)"
                    :key="option.value"
                    :label="option.alias || option.label"
                    :value="option.value"
                  ></el-option>
                </el-select>
              </el-form-item>
              <el-form-item v-if="!['null', 'not null'].includes(attr.operate)">
                <!-- 数字区间 -->
                <template v-if="['2', '3'].includes(attr.attr_type) && attr.operate === 'range'">
                  <el-input-number step-strictly :controls="false" :min="0" v-model="attr.value.start" />
                  <el-input-number step-strictly :controls="false" :min="0" v-model="attr.value.end" />
                </template>
                <!-- 日期区间 -->
                <template v-else-if="attr.attr_type === '4' && attr.operate === 'range'">
                  <el-date-picker v-model="attr.value.start" type="date" value-format="YYYY-MM-DD" />
                  <el-date-picker v-model="attr.value.end" type="date" value-format="YYYY-MM-DD" />
                </template>
                <!-- 时间区间 -->
                <template v-else-if="attr.attr_type === '5' && attr.operate === 'range'">
                  <el-date-picker
                    v-model="attr.value.start"
                    type="datetime"
                    value-format="YYYY-MM-DD HH:mm:ss"
                    style="width: 180px"
                  />
                  <el-date-picker
                    v-model="attr.value.end"
                    type="datetime"
                    value-format="YYYY-MM-DD HH:mm:ss"
                    style="width: 180px"
                  />
                </template>
                <template v-else-if="attr.attr_type === '4' && (attr.operate === 'after' || attr.operate === 'before')">
                  <el-date-picker v-model="attr.value" type="date" value-format="YYYY-MM-DD" />
                </template>
                <template v-else-if="attr.attr_type === '5' && (attr.operate === 'after' || attr.operate === 'before')">
                  <el-date-picker
                    v-model="attr.value"
                    type="datetime"
                    value-format="YYYY-MM-DD HH:mm:ss"
                    style="width: 180px"
                  />
                </template>
                <template v-else>
                  <el-select
                    v-model="attr.value"
                    filterable
                    remote
                    allow-create
                    multiple
                    :remote-method="(query:string) => remoteMethod(rule, attr, query)"
                    :loading="loading"
                    style="width: 320px"
                    v-if="['in', 'not in'].includes(attr.operate)"
                  >
                    <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
                  </el-select>
                  <el-autocomplete
                    v-model="attr.value"
                    :fetch-suggestions="(query, cb) => querySearch(rule, attr, query, cb)"
                    style="width: 320px"
                    v-else
                  />
                </template>
              </el-form-item>
            </div>
            <el-button text :icon="CloseBold" @click="handleAttrRemove(rule.happen_info.attr_list, index)"></el-button>
          </el-row>
          <!-- 触发 -->
          <el-row style="margin-top: 10px" v-if="rule.happen_info.is_happened">
            <el-form-item>
              <el-select model-value="触发次数">
                <el-option v-for="option in triggerInfoList" :key="option.value" v-bind="option"></el-option>
              </el-select>
            </el-form-item>
            <el-form-item>
              <el-select v-model="rule.trigger_info.operate" @change="value => handleTriggerOperateChange(value, rule)">
                <el-option
                  v-for="option in triggerNumberOperatorList"
                  :key="option.value"
                  :label="option.alias || option.label"
                  :value="option.value"
                />
              </el-select>
            </el-form-item>
            <el-form-item>
              <el-input v-model="rule.trigger_info.value" />
            </el-form-item>
          </el-row>
        </section>
      </div>
    </div>
    <el-button text :icon="Plus" @click="handleAdd(eventAttrRule.items)" v-if="eventAttrRule.items.length < limit"
      >添加事件</el-button
    >
    <slot name="footer"></slot>
  </el-card>
</template>

<style src="@/assets/styles/rule.scss"></style>
