<script lang="ts" setup>
import {
  TableColumn,
  TableColumnSelectable
} from '@idux/components/table'
import { TablePagination } from '@idux/components/table/src/types'
import { useAccessorAndControl } from '@idux/cdk/forms'
import { useFormItemRegister } from '@idux/components/form'

const props = defineProps<{
  control?: string | number | (string | number)[] | object
  disabled?: boolean
  value?: string
  placeholder?: string
  searchFormPlaceholder?: string
  columns: TableColumn<any>[]
  getDatasource: (params: any) => Promise<G.PageResult<any>>
  getKey: string | ((record: any) => any)
  getLabel: string | ((record: any) => any)
}>()

// const emit = defineEmits([ 'update:value' ])

// useAccessorAndControl 内部对 props 中的 control, disabled, value 进行了处理
const {accessor, control: controlRef} = useAccessorAndControl()

// 在 FormItem 组件中注册 control, 让 FormItem 获取控件的验证状态
useFormItemRegister(controlRef)
// 表单 blur 状态
const onBlur = () => {
  accessor.markAsBlurred()
}

const inputStatus = ref<'valid' | 'invalid' | 'validating'>('validating')


const valueRef = reactive<{
  key?: string
  label?: string
}>({})
controlRef.value?.watchStatus(it => {
  if (it === 'valid') {
    inputStatus.value = 'valid'
  } else if (it === 'invalid') {
    if (controlRef.value?.dirty.value) {
      inputStatus.value = 'invalid'
    } else {
      inputStatus.value = 'validating'
    }
  } else {
    inputStatus.value = 'validating'
  }
})

controlRef.value?.watchValue((newVal) => {
  if (newVal == null) {
    valueRef.label = ''
  }
})
const visible = ref(false)
const selectedRowKeys = ref<string[]>([])
const selectableColumn = reactive<TableColumnSelectable<ComboboxTableTypes.TableData>>({
  type: 'selectable',
  align: 'center',
  multiple: false,
  showIndex: false,
  trigger: 'click',
  onChange: (selectedKeys, selectedRows) => {
    if (selectedKeys.length === 0) {
      valueRef.key = undefined
      valueRef.label = undefined
    } else {
      valueRef.key = selectedKeys[0] as string
      if (props.getLabel instanceof Function) {
        valueRef.label = props.getLabel(selectedRows[0])
      } else {
        valueRef.label = selectedRows[0][props.getLabel as string]
      }
    }
    accessor.setValue(valueRef.key)
    // emit('update:value', valueRef.key)
  },
})
const columns_: TableColumn<any>[] = [
  selectableColumn,
  ...props.columns
]
const datasource = ref<ComboboxTableTypes.TableData[]>([])
const tableSpin = ref(false)
const keywords = ref('')

function obtainData() {
  tableSpin.value = true
  props.getDatasource({
    pageIndex: pagination.pageIndex,
    pageSize: pagination.pageSize,
    keywords: keywords.value
  }).then(res => {
    pagination.pageIndex = res.current
    pagination.pageSize = res.size
    pagination.total = res.total
    datasource.value = res.records
  }).finally(() => {
    tableSpin.value = false
  })
}

const pagination = reactive<TablePagination>({
  pageIndex: 1,
  pageSize: 10,
  total: 0,
  size: 'sm',
  showTotal: true,
  onChange: obtainData
})

watch(visible, (newVal) => {
  if (newVal) {
    obtainData()
  }
})

</script>

<template>
  <IxPopover v-model:visible="visible" closable placement="bottom" trigger="click">
    <IxInput v-model:value="valueRef.label" :placeholder="placeholder" :status="inputStatus" readonly @blur="onBlur"/>
    <template #header>
      <IxForm class="search-form" layout="inline" @submit.prevent="obtainData">
        <IxFormItem>
          <IxInput v-model:value="keywords" :placeholder="searchFormPlaceholder" clearable @clear="obtainData"/>
        </IxFormItem>
        <IxFormItem>
          <IxButton mode="primary" type="submit">查询</IxButton>
        </IxFormItem>
      </IxForm>
    </template>
    <template #content>
      <IxTable v-model:selectedRowKeys="selectedRowKeys" :columns="columns_" :dataSource="datasource" :get-key="getKey" :pagination="pagination" :spin="tableSpin"/>
    </template>
  </IxPopover>
</template>

<style lang="stylus" scoped>
.search-form {
  width 100%
  height 4rem
  padding: var(--ix-padding-size-sm) var(--ix-padding-size-md);
  border 1px solid #E5E7EB
}
</style>
