<template>
  <el-select
    ref="selectRef"
    v-model="localValue"
    :placeholder="placeholder"
    :disabled="disabled"
    filterable
    clearable
    :filter-method="handleSearch"
    @visible-change="handleVisibleChange"
    @clear="handleClear"
    @change="handleChange"
    class="paged-select"
    :teleported="false"
    :popper-options="{
      modifiers: [{ name: 'eventListeners', options: { scroll: false, resize: false } }],
    }"
  >
    <el-option
      v-for="item in optionList"
      :key="item[valueKey]"
      :label="item[labelKey]"
      :value="item[valueKey]"
    />
    <el-option v-if="loading && hasMore" label="加载中..." disabled />
    <el-option v-if="!hasMore && optionList.length" label="没有更多了~" disabled />
  </el-select>
</template>

<script>
import axios from 'axios';

export default {
  name: 'DynamicPagedSelect',
  props: {
    value: [String, Number],
    apiUrl: { type: String, required: true },
    apiMethod: { type: String, default: 'get' },
    params: { type: Object, default: () => ({}) },
    listKey: { type: String, required: true },
    totalKey: { type: String, required: true },
    labelKey: { type: String, required: true },
    valueKey: { type: String, required: true },
    searchKey: { type: String, default: 'keyword' },
    pageSize: { type: Number, default: 10 },
    placeholder: String,
    disabled: Boolean,
    debounceTime: { type: Number, default: 500 },
    echoApi: { type: String, default: '' },
    echoMethod: { type: String, default: 'get' },
  },
  data() {
    return {
      localValue: this.value,
      optionList: [],
      pageNum: 1,
      loading: false,
      hasMore: true,
      searchText: '',
      scrollEl: null,
      dropdownVisible: false,
      bindTimer: null,
      total: 0,
    };
  },
  watch: {
    value(val) {
      this.localValue = val;
      this.initEcho();
    },
    localValue(val) {
      this.$emit('input', val);
    },
    optionList() {
      if (this.dropdownVisible && this.optionList.length > 0) {
        this.$nextTick(() => {
          this.bindScroll();
        });
      }
    },
  },
  mounted() {
    this.debounceSearch = this.debounce(this.fetchData, this.debounceTime);
    this.initEcho();
  },
  beforeUnmount() {
    this.cleanup();
  },
  methods: {
    debounce(func, wait) {
      let timeout = null;
      return (...args) => {
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(this, args), wait);
      };
    },

    cleanup() {
      if (this.scrollEl) {
        this.scrollEl.removeEventListener('scroll', this.handleScroll);
        this.scrollEl = null;
      }
      if (this.bindTimer) {
        clearTimeout(this.bindTimer);
        this.bindTimer = null;
      }
    },

    findScrollContainer() {
      const selectRef = this.$refs.selectRef;
      if (!selectRef) return null;

      const popper = selectRef.popperRef?.$el || selectRef.popperRef;
      if (!popper) return null;

      const wrap = popper.querySelector('.el-scrollbar__wrap');
      if (wrap) return wrap;

      const altWrap = popper.querySelector('.el-select-dropdown__wrap');
      return altWrap || null;
    },

    bindScroll() {
      this.cleanup();

      const tryBind = (attempt = 1) => {
        if (!this.dropdownVisible) return;

        const scrollEl = this.findScrollContainer();
        if (scrollEl) {
          this.scrollEl = scrollEl;
          scrollEl.addEventListener('scroll', this.handleScroll, { passive: true });
        } else if (attempt < 5) {
          this.bindTimer = setTimeout(() => tryBind(attempt + 1), 100 * attempt);
        }
      };

      tryBind();
    },

    handleScroll(e) {
      const { scrollTop, scrollHeight, clientHeight } = e.target;
      const threshold = scrollHeight - clientHeight - 10;

      if (this.loading || !this.hasMore) return;

      if (scrollTop >= threshold) {
        this.loadMore();
      }
    },

    handleVisibleChange(visible) {
      this.dropdownVisible = visible;

      if (visible) {
        this.reset();
        this.fetchData().then(() => {
          this.bindScroll();
        });
      } else {
        this.cleanup();
      }
    },

    handleSearch(val) {
      this.searchText = val;
      this.reset();
      this.debounceSearch();
    },

    loadMore() {
      if (this.loading || !this.hasMore) return;
      this.pageNum++;
      this.fetchData();
    },

    handleClear() {
      this.localValue = '';
      this.reset();
      this.$emit('clear');
    },

    // 关键修改：选中后返回完整 item
    handleChange(val) {
      console.log('选中值:', val);
      
      // 从当前列表查找
      let selectedItem = this.optionList.find(item => item[this.valueKey] === val);
      console.log('从列表找到:', selectedItem);
      
      // 如果没找到且有回显接口，通过接口获取
      if (!selectedItem && this.echoApi) {
        console.log('列表未找到，通过接口获取');
        this.getEchoData(val).then(item => {
          console.log('接口返回:', item);
          this.$emit('change', val, item);
        });
      } else {
        // 确保发射事件
        this.$nextTick(() => {
          this.$emit('change', val, selectedItem);
        });
      }
    },

    // 新增：通过接口获取完整数据
    async getEchoData(val) {
      try {
        const params = { [this.valueKey]: val };
        let res;
        if (this.echoMethod.toLowerCase() === 'post') {
          res = await axios.post(this.echoApi, params);
        } else {
          res = await axios.get(this.echoApi, { params });
        }
        return res.data.data || {};
      } catch (e) {
        console.error('获取选中项详情失败', e);
        return null;
      }
    },

    async initEcho() {
      const val = this.localValue;
      if (!val || !this.echoApi) return;
      const has = this.optionList.some(item => item[this.valueKey] === val);
      if (has) return;
      
      const info = await this.getEchoData(val);
      if (info[this.labelKey] && info[this.valueKey]) {
        const exist = this.optionList.some(i => i[this.valueKey] === info[this.valueKey]);
        if (!exist) this.optionList.unshift(info);
      }
    },

    async fetchData() {
      this.loading = true;
      try {
        const sendData = {
          current: this.pageNum,
          size: this.pageSize,
          [this.searchKey]: this.searchText,
          ...this.params,
        };
        let res;
        if (this.apiMethod.toLowerCase() === 'post') {
          res = await axios.post(this.apiUrl, sendData);
        } else {
          res = await axios.get(this.apiUrl, { params: sendData });
        }
        const data = res.data.data || {};
        const list = data[this.listKey] || [];
        const total = data[this.totalKey] || 0;

        this.total = total;

        if (this.pageNum === 1) {
          this.optionList = list;
        } else {
          this.optionList = this.optionList.concat(list);
        }

        this.hasMore = this.optionList.length < total;

        this.$nextTick(() => {
          this.bindScroll();
        });
      } catch (e) {
        console.error('请求失败', e);
      } finally {
        this.loading = false;
      }
    },

    reset() {
      this.pageNum = 1;
      this.optionList = [];
      this.hasMore = true;
      this.total = 0;
      this.cleanup();
    },
  },
};
</script>
<style lang="scss" scoped>
:deep(.el-select-dropdown) {
  height: 200px !important;
  overflow: hidden !important;
}
:deep(.el-select-dropdown .el-scrollbar__wrap) {
  height: 200px !important;
  overflow-y: auto !important;
  overflow-x: hidden !important;
}
</style>