<!-- eslint-disable vue/no-mutating-props -->
<script setup lang="ts">
import type {
  MjTableSelectMethods,
  MjTableSelectRenderOpts,
  SetSelectedItems,
} from '.'
import type { RenderParams } from '../mj-form-plugin'
import type { SelectedItems } from '../mj-table/const'

defineOptions({ name: 'MjTableSelectPlugin' })

const props = withDefaults(
  defineProps<{
    // props
    renderOpts: MjTableSelectRenderOpts
    // 表格、表单相关的一些数据
    renderParams: RenderParams
  }>(),
  {},
)

const selectRef = ref()

const selectedItems = ref({} as SelectedItems)
let _initializing = false
watch(
  () => selectedItems.value,
  (val) => {
    // 设置表单数据
    _setValue(val?.items)
    // 初始化阶段不触发 selectChange，避免级联重置下游渲染器的初始值
    if (_initializing) return
    const options = props.renderOpts.props
    // 回调外面
    const fn = options.selectChange
    if (!fn) return
    const len = val?.items?.length
    if (len) {
      // 获得第1个item的名字
      const item = val.items[0]
      let label = item.name
      if (options.title) {
        label = options.title(item)
      }
      // 如果是多选
      if (options.multiSelectable) {
        fn(
          val?.items,
          val?.items.map((item) => item.id),
          len > 1 ? `${label}等${len}项` : label,
        )
      } else {
        fn(val?.items, item.id, label)
      }
    } else {
      fn(val?.items, undefined, undefined)
    }
  },
)

function _reset() {
  selectedItems.value = {} as any
}

// 设置表单数据
function _setValue(items: any[]) {
  let val
  if (items?.length) {
    val = items.length === 1 ? items[0].id : items.map((item) => item.id)
  }
  const field = props.renderParams.field
  const data = props.renderParams.data
  data[field] = val
}

function _getMethods(): MjTableSelectMethods {
  const renderProps = props.renderOpts.props
  let methods = renderProps._methods
  if (!methods) {
    methods = {} as any
    renderProps._methods = methods
  }
  return methods as any
}

function _setSelectedItems(val: SetSelectedItems) {
  let { items } = val
  if (!Array.isArray(items) && items) {
    items = [items]
  }

  selectedItems.value = {
    item: items?.length ? items[0] : undefined,
    items,
  } as SelectedItems
  // 单个的话，设值
  _setValue(items)
}

// 监听属性
watch(
  () => props.renderOpts.props,
  (val) => {
    // 外面传进来的默认值
    if (val.selectedItems) {
      _setSelectedItems({ items: val.selectedItems })
    }
  },
  {
    deep: true,
  },
)

onMounted(() => {
  _setValue([])

  const methods = _getMethods()
  // 重置
  methods.reset = _reset
  // 设置默认值
  methods.setSelectedItems = _setSelectedItems
  methods.getSelectedItems = () => toRaw(selectedItems.value.items)
  methods.updateProps = (val: any) => {
    props.renderOpts.props = {
      ...props.renderOpts.props,
      ...val,
    }
  }
  // 显示
  methods.show = () => {
    // 被禁用了，就不显示出来
    const renderProps = props.renderOpts.props
    if (renderProps.disabled) return

    const fn = selectRef.value.show
    fn && fn()
  }

  // 应用初始的 selectedItems（renderOpts.props 是普通对象，deep watcher 无法感知其变化）
  const initialItems = props.renderOpts.props.selectedItems
  if (initialItems) {
    _initializing = true
    _setSelectedItems({ items: initialItems })
    nextTick(() => {
      _initializing = false
    })
  }
})
</script>

<template>
  <mj-table-select
    ref="selectRef"
    class="mj-table-select-plugin"
    v-model="selectedItems"
    v-bind="renderOpts.props"
  />
</template>

<style lang="scss" scoped></style>
