<script setup lang="ts">
import { computed, nextTick, onMounted, ref, watch } from 'vue';

import { useVModel } from '@vueuse/core';
import { Avatar, Empty, Input, Popover, Spin } from 'ant-design-vue';

import { getStoreOption } from '#/views/system/store/api';
import SensitiveText from '#/components/sensitive-text/SensitiveText.vue';
import { resolveAvatarUrl } from '#/views/system/store-input/utils/inputUser';

defineOptions({
  name: 'StorePicker',
  inheritAttrs: false,
});

const props = defineProps<{
  value?: number;
  disabled?: boolean;
}>();

const emits = defineEmits<{
  'update:value': [value: number | undefined];
}>();

const mValue = useVModel(props, 'value', emits, { passive: true });

type StoreOption = {
  id: number;
  name: string;
  pic?: string;
  mobile?: string;
};

const open = ref(false);
const loading = ref(false);
const searchKeyword = ref('');
const options = ref<StoreOption[]>([]);
const searchInputRef = ref<InstanceType<typeof Input> | null>(null);

/** 按关键词过滤诊所列表 */
function filterStoreOptions(keyword: string, list: StoreOption[]) {
  const q = keyword.trim().toLowerCase();
  if (!q) return list;
  return list.filter((item) => {
    const name = (item.name || '').toLowerCase();
    const mobile = (item.mobile || '').toLowerCase();
    const idText = String(item.id);
    return name.includes(q) || mobile.includes(q) || idText.includes(q);
  });
}

const filteredOptions = computed(() =>
  filterStoreOptions(searchKeyword.value, options.value),
);

const selectedOption = computed(() =>
  options.value.find((item) => item.id === mValue.value),
);

/** 加载诊所选项（含 pic、mobile 供卡片展示） */
async function loadOptions() {
  loading.value = true;
  try {
    options.value = (await getStoreOption({})) || [];
  } finally {
    loading.value = false;
  }
}

function selectOption(item: StoreOption) {
  mValue.value = item.id;
  open.value = false;
  searchKeyword.value = '';
}

function clearSelection() {
  mValue.value = undefined;
}

function onOpenChange(next: boolean) {
  if (props.disabled) return;
  open.value = next;
  if (next) {
    searchKeyword.value = '';
    if (!options.value.length) {
      loadOptions();
    }
    nextTick(() => searchInputRef.value?.focus?.());
  }
}

watch(
  () => props.disabled,
  (disabled) => {
    if (disabled) open.value = false;
  },
);

onMounted(() => {
  loadOptions();
});
</script>

<template>
  <Popover
    :open="open"
    trigger="click"
    placement="bottomLeft"
    overlay-class-name="store-picker-popover"
    @open-change="onOpenChange"
  >
    <template #content>
      <div class="store-panel">
        <Input
          ref="searchInputRef"
          v-model:value="searchKeyword"
          allow-clear
          placeholder="搜索诊所名称、电话、ID"
          class="store-search"
        />
        <Spin :spinning="loading">
          <div v-if="filteredOptions.length" class="store-grid">
            <button
              v-for="item in filteredOptions"
              :key="item.id"
              type="button"
              class="store-card"
              :class="{ active: item.id === mValue }"
              @click="selectOption(item)"
            >
              <Avatar :src="resolveAvatarUrl(item.pic)" :size="36" shape="square">
                {{ (item.name || '?').charAt(0) }}
              </Avatar>
              <div class="store-card-name" :title="item.name">
                {{ item.name || '-' }}
              </div>
              <div v-if="item.mobile" class="store-card-sub">
                <SensitiveText :record="item" field="mobile" :show-eye="false" />
              </div>
              <div class="store-card-sub">ID: {{ item.id }}</div>
            </button>
          </div>
          <Empty v-else description="无匹配诊所" class="store-empty" />
        </Spin>
      </div>
    </template>
    <div class="store-trigger" :class="{ disabled: disabled }">
      <div v-if="selectedOption" class="store-selected-card">
        <Avatar :src="resolveAvatarUrl(selectedOption.pic)" :size="36" shape="square">
          {{ (selectedOption.name || '?').charAt(0) }}
        </Avatar>
        <div class="store-selected-info">
          <div class="store-selected-name">{{ selectedOption.name }}</div>
          <div class="store-selected-sub">
            <SensitiveText
              v-if="selectedOption.mobile"
              :record="selectedOption"
              field="mobile"
              :show-eye="false"
            />
            <span v-else>ID: {{ selectedOption.id }}</span>
          </div>
        </div>
        <span
          v-if="!disabled"
          class="store-clear-btn"
          title="清除"
          @click.stop="clearSelection"
        >
          ×
        </span>
      </div>
      <div v-else-if="mValue" class="store-selected-card">
        <div class="store-selected-info">
          <div class="store-selected-name">诊所 #{{ mValue }}</div>
        </div>
        <span
          v-if="!disabled"
          class="store-clear-btn"
          title="清除"
          @click.stop="clearSelection"
        >
          ×
        </span>
      </div>
      <div v-else class="store-trigger-placeholder">请选择诊所</div>
    </div>
  </Popover>
</template>

<style scoped lang="scss">
@use './picker-card-theme.scss' as theme;

.store-trigger {
  width: 100%;
}

.store-trigger.disabled {
  cursor: not-allowed;
  opacity: 0.65;
}

.store-trigger:not(.disabled) {
  cursor: pointer;
}

.store-selected-card {
  @include theme.picker-selected-card;
}

.store-selected-info {
  flex: 1;
  min-width: 0;
}

.store-selected-name {
  font-size: 14px;
  color: #1d2129;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.store-selected-sub {
  font-size: 12px;
  color: #86909c;
  margin-top: 2px;
}

.store-clear-btn {
  @include theme.picker-clear-btn;
}

.store-trigger-placeholder {
  @include theme.picker-trigger-placeholder;
}

.dark {
  .store-selected-card {
    @include theme.picker-selected-card-dark-props;
  }

  .store-selected-name {
    @include theme.picker-text-primary-dark;
  }

  .store-selected-sub {
    @include theme.picker-text-secondary-dark;
  }

  .store-clear-btn {
    @include theme.picker-clear-dark-props;
  }

  .store-trigger-placeholder {
    @include theme.picker-placeholder-dark-props;
  }
}
</style>

<style lang="scss">
@use './picker-card-theme.scss' as theme;

.store-picker-popover {
  .ant-popover-inner {
    padding: 12px;
  }

  .store-panel {
    width: 540px;
    max-width: 86vw;
  }

  .store-search {
    margin-bottom: 10px;
  }

  .store-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
    gap: 8px;
    max-height: 300px;
    overflow-y: auto;
    padding: 2px;
  }

  .store-card {
    @include theme.picker-card-base;
  }

  .store-card-name {
    @include theme.picker-card-name;
  }

  .store-card-sub {
    @include theme.picker-card-sub;
  }

  .store-empty {
    margin: 16px 0;
  }
}

.dark .store-picker-popover {
  .store-card {
    @include theme.picker-card-dark-props;
  }

  .store-card-name {
    @include theme.picker-text-primary-dark;
  }

  .store-card-sub {
    @include theme.picker-text-secondary-dark;
  }
}
</style>
