<template>
  <div class="kole-select" :class="{ 'is-open': open, 'is-disabled': disabled }" ref="root">
    <div class="kole-select-trigger" @click="toggle" tabindex="0">
      <template v-if="multiple">
        <span v-if="!selectedArr.length" class="placeholder">{{ placeholder }}</span>
        <span v-for="v in selectedArr" :key="v" class="tag">
          {{ labelOf(v) }}<span class="x" @click.stop="remove(v)">✕</span>
        </span>
      </template>
      <span v-else-if="selectedVal == null" class="placeholder">{{ placeholder }}</span>
      <span v-else>{{ labelOf(selectedVal) }}</span>
      <span class="caret">▾</span>
    </div>

    <div class="kole-select-panel" v-show="open">
      <div v-if="searchable" class="kole-select-search">
        <input v-model="keyword" placeholder="输入关键字" @click.stop>
      </div>

      <template v-if="groups && groups.length">
        <template v-for="g in filteredGroups">
          <div class="kole-select-group-label">{{ g.label }}</div>
          <div
            v-for="o in g.options" :key="o.value"
            class="kole-select-option"
            :class="{ 'is-selected': isSelected(o.value), 'is-disabled': o.disabled }"
            @click="choose(o)"
          >
            {{ o.label }}<span class="check">✓</span>
          </div>
        </template>
      </template>

      <template v-else>
        <div
          v-for="o in filteredOptions" :key="o.value"
          class="kole-select-option"
          :class="{ 'is-selected': isSelected(o.value), 'is-disabled': o.disabled }"
          @click="choose(o)"
        >
          {{ o.label }}<span class="check">✓</span>
        </div>
      </template>

      <div v-if="isEmpty" class="kole-select-empty">无匹配选项</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'KoleSelect',
  props: {
    value: { type: [String, Number, Array], default: null },
    options: { type: Array, default: () => [] },          // [{ value, label, disabled? }]
    groups: { type: Array, default: null },                // [{ label, options: [...] }]
    multiple: { type: Boolean, default: false },
    searchable: { type: Boolean, default: false },
    disabled: { type: Boolean, default: false },
    placeholder: { type: String, default: '请选择' }
  },
  data() {
    return { open: false, keyword: '' };
  },
  computed: {
    selectedArr() { return Array.isArray(this.value) ? this.value : []; },
    selectedVal() { return Array.isArray(this.value) ? null : this.value; },
    filteredOptions() {
      if (!this.searchable || !this.keyword) return this.options;
      const q = this.keyword.trim().toLowerCase();
      return this.options.filter(o => String(o.label).toLowerCase().includes(q));
    },
    filteredGroups() {
      if (!this.groups) return [];
      if (!this.searchable || !this.keyword) return this.groups;
      const q = this.keyword.trim().toLowerCase();
      return this.groups
        .map(g => ({ label: g.label, options: g.options.filter(o => String(o.label).toLowerCase().includes(q)) }))
        .filter(g => g.options.length);
    },
    isEmpty() {
      return this.groups ? this.filteredGroups.length === 0 : this.filteredOptions.length === 0;
    }
  },
  watch: {
    open(v) { if (v && this.searchable) this.keyword = ''; }
  },
  methods: {
    toggle() {
      if (this.disabled) return;
      this.open = !this.open;
    },
    isSelected(v) {
      return this.multiple ? this.selectedArr.includes(v) : this.selectedVal === v;
    },
    labelOf(v) {
      const flat = this.options.length ? this.options : (this.groups || []).flatMap(g => g.options);
      const found = flat.find(o => o.value === v);
      return found ? found.label : v;
    },
    choose(o) {
      if (o.disabled) return;
      if (this.multiple) {
        const next = this.selectedArr.includes(o.value)
          ? this.selectedArr.filter(x => x !== o.value)
          : [...this.selectedArr, o.value];
        this.$emit('input', next);
        this.$emit('change', next);
      } else {
        this.$emit('input', o.value);
        this.$emit('change', o.value);
        this.open = false;
      }
    },
    remove(v) {
      this.$emit('input', this.selectedArr.filter(x => x !== v));
      this.$emit('change', this.selectedArr.filter(x => x !== v));
    },
    onDocClick(e) {
      if (this.$refs.root && !this.$refs.root.contains(e.target)) this.open = false;
    }
  },
  mounted() { document.addEventListener('click', this.onDocClick); },
  beforeDestroy() { document.removeEventListener('click', this.onDocClick); }
};
</script>

<!-- 样式对齐 components.css 与 select.json 契约（触发器样式同 Input） -->
<style>
.kole-select { position: relative; display: inline-block; min-width: 220px; }
.kole-select-trigger {
  display: flex; align-items: center; gap: 8px; min-height: 32px; height: auto;
  padding: 2px 28px 2px 12px; background: #fff; border: 1px solid #E8ECF1;
  border-radius: 4px; box-sizing: border-box; cursor: pointer; transition: border-color .15s, box-shadow .15s;
  font-size: 14px; color: #262626; flex-wrap: wrap; position: relative;
}
.kole-select-trigger:hover { border-color: #2F54EB; }
.kole-select.is-open .kole-select-trigger { border-color: #2F54EB; box-shadow: 0 0 0 2px rgba(47,84,235,0.2); }
.kole-select.is-disabled .kole-select-trigger { background: #F5F5F5; border-color: transparent; color: #BFBFBF; cursor: not-allowed; }
.kole-select-trigger .placeholder { color: #767676; }
.kole-select-trigger .caret { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); transition: transform .15s; color: #6E6E6E; }
.kole-select.is-open .caret { transform: translateY(-50%) rotate(180deg); }
.kole-select-trigger .tag {
  display: inline-flex; align-items: center; gap: 4px; background: #F0F5FF; color: #2F54EB;
  border-radius: 2px; padding: 1px 6px; font-size: 12px; line-height: 20px;
}
.kole-select-trigger .tag .x { cursor: pointer; }
.kole-select-panel {
  position: absolute; z-index: 10; top: calc(100% + 4px); left: 0; right: 0;
  background: #fff; border-radius: 4px; box-shadow: 0 4px 16px rgba(0,0,0,0.12);
  max-height: 256px; overflow-y: auto; padding: 4px 0;
}
.kole-select-search { padding: 6px 8px; border-bottom: 1px solid #F0F0F0; }
.kole-select-search input { width: 100%; box-sizing: border-box; border: 1px solid #E8ECF1; border-radius: 4px; padding: 4px 8px; font-size: 13px; outline: none; }
.kole-select-search input:focus { border-color: #2F54EB; }
.kole-select-group-label { padding: 6px 12px; font-size: 12px; color: #6E6E6E; }
.kole-select-option {
  display: flex; align-items: center; gap: 8px; padding: 0 12px; height: 32px; cursor: pointer;
  font-size: 14px; color: #262626; box-sizing: border-box;
}
.kole-select-option:hover { background: #F5F7FA; }
.kole-select-option.is-selected { background: #F0F5FF; color: #2F54EB; }
.kole-select-option .check { visibility: hidden; margin-left: auto; }
.kole-select-option.is-selected .check { visibility: visible; }
.kole-select-option.is-disabled { color: #BFBFBF; cursor: not-allowed; }
.kole-select-empty { padding: 16px 12px; text-align: center; color: #767676; font-size: 13px; }
</style>
