<script setup lang="ts">
import { ref, computed, watch } from 'vue';
import { Select, Divider, Row } from 'ant-design-vue';
import { ChevronLeft, ChevronRight } from '@vben/icons';
import { postTreeModelDevicePatchListAsync } from '#/api-client';
import { $t } from '#/locales';
import { useDebounceFn } from '@vueuse/core';

interface Props {
  value?: string;
  placeholder?: string;
  disabled?: boolean;
  allowClear?: boolean;
  ioTDataType?: string;
}

const props = withDefaults(defineProps<Props>(), {
  placeholder: $t('common.pleaseSelect') + $t('abp.log.deviceInfo'),
  disabled: false,
  allowClear: true,
  ioTDataType: '',
});

const emit = defineEmits<{
  'update:value': [string];
  change: [string];
  'device-change': [any];
}>();

const VNodes = (_, { attrs }: any) => {
  return attrs.vnodes;
};

const options = ref<any[]>([]);
const query = ref({
  pageIndex: 1,
  pageSize: 10,
  deviceAddress: '', // 搜索关键词
});
const total = ref(0);
const loading = ref<boolean>(false);
const searchInput = ref<string>('');

// 最大页码
const maxPage = computed(() => {
  return Math.ceil(total.value / query.value.pageSize);
});

/**
 * 获取设备列表数据
 */
const fetchData = async () => {
  if (!props.ioTDataType) {
    options.value = [];
    total.value = 0;
    return;
  }

  loading.value = true;
  try {
    const { data } = await postTreeModelDevicePatchListAsync({
      body: {
        pageIndex: query.value.pageIndex,
        pageSize: query.value.pageSize,
        ioTDataType: props.ioTDataType,
        deviceAddress: query.value.deviceAddress || undefined,
      },
    });

    if (data?.items) {
      options.value = data.items.map((item: any) => ({
        label: item.Device,
        value: item.Device,
        ...item,
      }));
      total.value = data.totalCount || 0;
    }
    loading.value = false;
  } catch (error) {
    console.error('获取设备列表失败:', error);
    loading.value = false;
  }
};

/**
 * 处理搜索输入
 */
const handleSearch = useDebounceFn((value: string) => {
  query.value.deviceAddress = value;
  query.value.pageIndex = 1; // 搜索时重置到第一页
  fetchData();
}, 300);

/**
 * 上下页
 * @param type 1: 下一页, 0: 上一页
 */
const changePage = (type: number) => {
  if (type === 1) {
    if (query.value.pageIndex >= maxPage.value) return;
    query.value.pageIndex += 1;
    fetchData();
  } else {
    if (query.value.pageIndex <= 1) return;
    query.value.pageIndex -= 1;
    fetchData();
  }
};

// 监听 ioTDataType 变化，重新加载数据
watch(
  () => props.ioTDataType,
  (newVal) => {
    query.value.pageIndex = 1;
    query.value.deviceAddress = ''; // 重置搜索关键词
    searchInput.value = '';
    if (newVal) {
      fetchData();
    } else {
      options.value = [];
      total.value = 0;
    }
  },
  { immediate: true },
);

// 处理值变化
const handleValueChange = (value: string) => {
  emit('update:value', value);
  emit('change', value);

  if (value) {
    const selectedDevice = options.value.find((option) => option.value === value);
    if (selectedDevice) {
      emit('device-change', selectedDevice);
    }
  } else {
    emit('device-change', null);
  }
};

// 暴露方法给父组件调用
defineExpose({
  getSelectedDevice: () => {
    if (props.value) {
      return options.value.find((option) => option.value === props.value);
    }
    return null;
  },
});
</script>

<template>
  <Select
    :value="value"
    :showSearch="true"
    :options="options"
    :placeholder="placeholder"
    :filter-option="false"
    :disabled="disabled || !ioTDataType"
    :allow-clear="allowClear"
    :loading="loading"
    :search-value="searchInput"
    @change="handleValueChange"
    @search="handleSearch"
  >
    <template #dropdownRender="{ menuNode: menu }">
      <v-nodes :vnodes="menu" />
      <Divider style="margin: 4px 0" />
      <div @mousedown="(e) => e.preventDefault()">
        <Row type="flex" justify="space-around" align="middle">
          <ChevronLeft
            @click="changePage(0)"
            :class="{ 'text-gray-400': query.pageIndex <= 1 }"
            style="cursor: pointer; width: 16px; height: 16px"
          />
          <div>{{ `${query.pageIndex}/${maxPage}` }}</div>
          <ChevronRight
            @click="changePage(1)"
            :class="{ 'text-gray-400': query.pageIndex >= maxPage }"
            style="cursor: pointer; width: 16px; height: 16px"
          />
        </Row>
      </div>
    </template>
  </Select>
</template>

<style lang="less" scoped>
.text-gray-400 {
  color: #9ca3af;
  cursor: not-allowed !important;
}
</style>
