<script lang="ts" setup>
/**
 * 药品搜索选择组件（自定义实现）
 *
 * @description 自定义药品搜索下拉选择器，不依赖antd的Select组件
 *              - 支持中药/西药类型切换
 *              - 下拉选项展示：药品图片、名称、供应商、规格、价格
 *              - 选择时返回完整药品数据（包含默认用法字段）
 * @author 系统
 * @date 2024
 */
import { ref, watch, onMounted, onUnmounted } from 'vue';

import { SearchOutlined, LoadingOutlined } from '@ant-design/icons-vue';
import { Input, Spin } from 'ant-design-vue';
import { debounce } from 'lodash-es';

import { getProductListDoctorReception } from '#/views/doctor/doctor-reception/api';

/** 中药无图时与仓库列表一致的占位图 */
const TCM_PLACEHOLDER_IMAGE =
  'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk_upload_20250510/cd470ebf97e31c4048ba502ba71b66a3.jpg';

// ==================== Props 定义 ====================

interface Props {
  /**
   * 药品类型
   * 1-中药，2-西药
   */
  type?: number;
  /**
   * 占位提示文本
   */
  placeholder?: string;
  /**
   * 诊所ID
   */
  storeId?: number;
  /**
   * 挂号ID（用于取价门店与毛利率权限）
   */
  registerId?: number;
  /**
   * 是否禁用
   */
  disabled?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  type: 1,
  placeholder: '输入药品名称搜索',
  storeId: 2,
  registerId: undefined,
  disabled: false,
});

// ==================== Emits 定义 ====================

const emit = defineEmits<{
  /**
   * 选中药品时触发
   * @param drug 完整的药品数据
   */
  (e: 'select', drug: any): void;
}>();

// ==================== 响应式数据 ====================

/**
 * 搜索关键词
 */
const searchKeyword = ref('');

/**
 * 是否正在搜索
 */
const isSearching = ref(false);

/**
 * 搜索结果列表
 */
const searchResults = ref<any[]>([]);

/**
 * 是否显示下拉列表
 */
const showDropdown = ref(false);

/**
 * 组件容器引用
 */
const containerRef = ref<HTMLElement | null>(null);

/**
 * 当前高亮的选项索引（用于键盘导航）
 */
const highlightIndex = ref(-1);

function resolveDropdownImage(item: any): string {
  if (item._image) return item._image;
  if (props.type === 1) return TCM_PLACEHOLDER_IMAGE;
  return '';
}

// ==================== 方法定义 ====================

/**
 * 搜索药品
 * @param keyword 搜索关键词
 * @description 调用后端API搜索药品，支持按名称和拼音搜索
 */
const searchDrugs = debounce(async (keyword: string) => {
  if (!keyword || keyword.length < 1) {
    searchResults.value = [];
    showDropdown.value = false;
    return;
  }

  isSearching.value = true;
  showDropdown.value = true;

  try {
    const res = await getProductListDoctorReception({
      name: keyword,
      type: props.type,
      store_id: props.storeId,
      ...(props.registerId ? { register_id: props.registerId } : {}),
    });

    // 处理返回数据
    if (Array.isArray(res)) {
      searchResults.value = res.map((item: any) => ({
        // 保留原始数据
        ...item,
        // 提取常用字段便于访问
        _id: item.id,
        _drugId: item.drug_id || item.drug?.id,
        _drugName: item.drug?.drug_name || item.drug_name || '',
        _image: item.drug?.image || '',
        _specification: item.drug?.specification || '',
        _supplier: item.drug?.supplier?.name || '',
        _price: item.price || 0,
        // 默认用法字段
        _timeId: item.drug?.time_id || 0,
        _typeId: item.drug?.type_id || 0,
        _frequencyId: item.drug?.frequency_id || 0,
        _unitId: item.drug?.unit_id || 0,
        _number: item.drug?.number || 1,
        // 用法名称
        _useNum: item.drug?.useNum,
        _useType: item.drug?.useType,
        _useFrequency: item.drug?.useFrequency,
      }));
    } else {
      searchResults.value = [];
    }
  } catch (error) {
    console.error('搜索药品失败:', error);
    searchResults.value = [];
  } finally {
    isSearching.value = false;
  }
}, 300);

/**
 * 处理输入变化
 * @param e 输入事件
 */
function handleInput(e: Event) {
  const target = e.target as HTMLInputElement;
  searchKeyword.value = target.value;
  highlightIndex.value = -1;
  searchDrugs(target.value);
}

/**
 * 处理输入框获得焦点
 */
function handleFocus() {
  if (searchResults.value.length > 0) {
    showDropdown.value = true;
  }
}

/**
 * 处理选中药品
 * @param drug 选中的药品数据
 */
function handleSelectDrug(drug: any) {
  emit('select', drug);

  // 清空搜索状态
  searchKeyword.value = '';
  searchResults.value = [];
  showDropdown.value = false;
  highlightIndex.value = -1;
}

/**
 * 处理键盘事件
 * @param e 键盘事件
 */
function handleKeydown(e: KeyboardEvent) {
  if (!showDropdown.value || searchResults.value.length === 0) return;

  switch (e.key) {
    case 'ArrowDown':
      e.preventDefault();
      highlightIndex.value = Math.min(
        highlightIndex.value + 1,
        searchResults.value.length - 1,
      );
      break;
    case 'ArrowUp':
      e.preventDefault();
      highlightIndex.value = Math.max(highlightIndex.value - 1, 0);
      break;
    case 'Enter':
      e.preventDefault();
      if (highlightIndex.value >= 0) {
        handleSelectDrug(searchResults.value[highlightIndex.value]);
      }
      break;
    case 'Escape':
      showDropdown.value = false;
      highlightIndex.value = -1;
      break;
  }
}

/**
 * 处理点击外部关闭下拉
 * @param e 点击事件
 */
function handleClickOutside(e: MouseEvent) {
  if (containerRef.value && !containerRef.value.contains(e.target as Node)) {
    showDropdown.value = false;
    highlightIndex.value = -1;
  }
}

// ==================== 生命周期 ====================

onMounted(() => {
  document.addEventListener('click', handleClickOutside);
});

onUnmounted(() => {
  document.removeEventListener('click', handleClickOutside);
});

// ==================== 监听 ====================

/**
 * 监听类型变化，清空搜索结果
 */
watch(
  () => props.type,
  () => {
    searchResults.value = [];
    showDropdown.value = false;
    searchKeyword.value = '';
  },
);
</script>

<template>
  <div ref="containerRef" class="drug-search-select">
    <!-- 搜索输入框 -->
    <Input
      v-model:value="searchKeyword"
      :placeholder="placeholder"
      :disabled="disabled"
      allow-clear
      @input="handleInput"
      @focus="handleFocus"
      @keydown="handleKeydown"
    >
      <template #prefix>
        <LoadingOutlined v-if="isSearching" class="text-gray-400" />
        <SearchOutlined v-else class="text-gray-400" />
      </template>
    </Input>

    <!-- 下拉列表 -->
    <div v-if="showDropdown" class="drug-dropdown">
      <!-- 加载中 -->
      <div v-if="isSearching" class="drug-dropdown__loading">
        <Spin size="small" />
        <span>搜索中...</span>
      </div>

      <!-- 无结果 -->
      <div
        v-else-if="searchResults.length === 0"
        class="drug-dropdown__empty"
      >
        暂无匹配药品
      </div>

      <!-- 结果列表 -->
      <div v-else class="drug-dropdown__list">
        <div
          v-for="(item, index) in searchResults"
          :key="item._id"
          class="drug-item"
          :class="{ 'drug-item--active': index === highlightIndex }"
          @click="handleSelectDrug(item)"
          @mouseenter="highlightIndex = index"
        >
          <!-- 药品图片 -->
          <div class="drug-item__image">
            <img
              v-if="resolveDropdownImage(item)"
              :src="resolveDropdownImage(item)"
              alt=""
              class="drug-item__img"
              @error="(e) => (e.target as HTMLImageElement).style.display = 'none'"
            />
            <div v-else class="drug-item__img-placeholder">无图</div>
          </div>

          <!-- 药品信息 -->
          <div class="drug-item__info">
            <!-- 药品名称 -->
            <div class="drug-item__name">{{ item._drugName }}</div>
            <!-- 规格和供应商 -->
            <div class="drug-item__meta">
              <span v-if="item._specification" class="drug-item__spec">
                规格：{{ item._specification }}
              </span>
              <span v-if="item._supplier" class="drug-item__supplier">
                供应商：{{ item._supplier }}
              </span>
            </div>
          </div>

          <!-- 价格 -->
          <div class="drug-item__price">
            ¥{{ Number(item._price).toFixed(2) }}
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.drug-search-select {
  position: relative;
  width: 100%;
}

.drug-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 1050;
  margin-top: 4px;
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
  max-height: 400px;
  overflow: hidden;

  &__loading,
  &__empty {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 24px;
    color: #999;
    font-size: 14px;
  }

  &__list {
    max-height: 400px;
    overflow-y: auto;
    padding: 4px 0;

    &::-webkit-scrollbar {
      width: 6px;
    }

    &::-webkit-scrollbar-thumb {
      background: #d9d9d9;
      border-radius: 3px;
    }

    &::-webkit-scrollbar-track {
      background: transparent;
    }
  }
}

.drug-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  cursor: pointer;
  transition: background-color 0.2s;

  &:hover,
  &--active {
    background-color: #f5f7fa;
  }

  &__image {
    flex-shrink: 0;
    width: 48px;
    height: 48px;
  }

  &__img {
    width: 48px;
    height: 48px;
    object-fit: cover;
    border-radius: 6px;
    border: 1px solid #f0f0f0;
  }

  &__img-placeholder {
    width: 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #f5f5f5;
    border-radius: 6px;
    font-size: 12px;
    color: #bbb;
  }

  &__info {
    flex: 1;
    min-width: 0;
    overflow: hidden;
  }

  &__name {
    font-size: 14px;
    font-weight: 500;
    color: #333;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-bottom: 4px;
  }

  &__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    font-size: 12px;
    color: #999;
  }

  &__spec {
    color: #666;
  }

  &__supplier {
    color: #1890ff;
  }

  &__price {
    flex-shrink: 0;
    font-size: 16px;
    font-weight: 600;
    color: #ff4d4f;
  }
}

/* 暗色模式适配 */
.dark {
  .drug-dropdown {
    background: #1f2937;
    border-color: #374151;
  }

  .drug-item {
    &:hover,
    &--active {
      background-color: #374151;
    }

    &__img-placeholder {
      background: #374151;
      color: #6b7280;
    }

    &__name {
      color: #f3f4f6;
    }

    &__meta {
      color: #9ca3af;
    }

    &__spec {
      color: #d1d5db;
    }

    &__supplier {
      color: #60a5fa;
    }
  }
}
</style>
