<script lang="ts" setup>
/**
 * 简单产品选择模态框组件
 * 
 * @description 用于保健食品、产品服务包、非药品、医疗器械等简单产品的选择
 *              这些类型不需要用法用量等复杂字段，只需要选择产品和数量
 * @author 系统
 * @date 2024
 */
import { computed, ref } from 'vue';

import { Page, useVbenModal } from '@vben/common-ui';
import { useUserStore } from '@vben/stores';

import {
  ContainerOutlined,
  MinusOutlined,
  PlusOutlined,
} from '@ant-design/icons-vue';
import {
  Badge,
  Button,
  Card,
  CardMeta,
  Col,
  Image,
  InputNumber,
  InputSearch,
  message,
  Popover,
  Row,
} from 'ant-design-vue';
import { debounce } from 'lodash-es';

import {
  getProductListDoctorReception,
} from '#/views/doctor/doctor-reception/api';
import { usePrescriptionStore } from '#/store/prescription'

// 使用 Pinia store
const prescriptionStore = usePrescriptionStore();
const { currentDrugs, initializeForModal, updateCurrentDrugs } = prescriptionStore;

// 获取用户信息
const userStore = useUserStore();

// 搜索关键词
const searchKey = ref('');
// 药品类型：3-保健食品，5-产品服务包，6-非药品，7-医疗器械
const type = ref(3);
// 当前药品回调函数
const currentDrugsCallback = ref();
// 是否为聊天模式
const isChatMode = ref(false);
// 当前患者ID
const activePatientId = ref(0);
// 药品列表
const drugList = ref([]);
// 已选择的药品列表
const selectList = ref([]);
// 缓存前缀（用于区分接诊和在线复诊）
const storagePrefix = ref('');
// 预览图片URL
const previewImage = ref('');

// 图片预览控制
const visible = ref(false);
// 设置图片预览状态
const setVisible = (value: boolean, instruction = '') => {
  visible.value = value;
  previewImage.value = instruction;
};

// 本地存储键名：与 prescription store 一致（prefix 已含尾部 `-`，勿再拼 `-`）
const storageKey = computed(() => {
  return `${storagePrefix.value}prescriptionData_${type.value}_${activePatientId.value}`;
});

/**
 * 同步已选药品到 selectList
 * chat 模式以 Pinia currentDrugs 为准，避免双横线孤儿缓存回填
 */
const getCurrentDrugs = () => {
  try {
    if (isChatMode.value) {
      const drugs = prescriptionStore.currentDrugs;
      selectList.value = Array.isArray(drugs) ? [...drugs] : [];
      return;
    }
    const storedData = localStorage.getItem(storageKey.value);
    selectList.value = storedData ? JSON.parse(storedData) : [];
  } catch (error) {
    console.error('解析处方数据失败:', error);
    selectList.value = [];
  }
};

/**
 * 获取药品列表
 * @param {string} searchText - 搜索关键词
 */
const getDrugList = debounce(async (searchText = '') => {
  if (searchText === '') {
    drugList.value = [];
    return;
  }

  getCurrentDrugs();

  try {
    const res = await getProductListDoctorReception({
      store_id: userStore.userInfo?.store_id || 0,
      type: type.value,
      name: searchText,
    });

    drugList.value = res.map((item) => {
      const matched = selectList.value.find((v) => v.index_id === item.id);
      return {
        ...item,
        select_number: matched?.select_number || 0,
        drug: {
          ...item.drug,
          number: matched?.number || 1,
        },
      };
    });
  } catch (error) {
    console.error('获取药品列表失败:', error);
    message.error('获取药品列表失败');
  }
}, 300);

/**
 * 添加商品到处方
 * @param {object} data - 商品对象
 */
function addProducts(data: any) {
  // 查找是否已存在于选择列表中
  const existItem = selectList.value.find(
    (item) => item.index_id === data.id,
  );

  if (existItem) {
    // 已存在，增加数量
    const newNumber = existItem.select_number + 1;

    // 验证数量上限
    if (newNumber > 100) {
      message.error(`${existItem.drug_name}数量不能大于100！`);
      return;
    }

    // 更新选中列表中的数量
    selectList.value = selectList.value.map((item) =>
      item.index_id === data.id ? { ...item, select_number: newNumber } : item,
    );

    // 同步更新药品列表中的数量
    syncDrugList(data.id, newNumber);

    // 更新本地存储
    updateSelectStorage();

    // 提示成功
    message.success(`${existItem.drug_name}数量已增加至${newNumber}！`);
  } else {
    // 创建新的商品对象
    const newProduct = {
      index_id: data.id,
      id: data.drug.id,
      drug_name: data.drug.drug_name,
      number: 1,
      price: data.price,
      image: data.drug.image,
      // 规格（选仓弹窗等处展示）
      specification: data.drug.specification || data.specification || '',
      instruction: data.drug.instruction,
      type: data.drug.type,
      select_number: 1,
    };

    // 添加到选中列表
    selectList.value.push(newProduct);

    // 同步更新药品列表
    syncDrugList(newProduct.index_id, 1);

    // 更新本地存储
    updateSelectStorage();

    // 提示成功
    message.success(`已将${newProduct.drug_name}添加到清单中！`);
  }
}

/**
 * 减少商品数量
 * @param {object} data - 商品对象
 */
function propProducts(data: any) {
  // 查找是否存在于选择列表中
  const existItem = selectList.value.find((item) => item.index_id === data.id);

  // 如果不存在，提示错误并返回
  if (!existItem) {
    message.error(`${data.drug.drug_name}不在清单中！`);
    return;
  }

  // 计算新的数量
  const newNumber = existItem.select_number - 1;

  // 验证数量下限
  if (newNumber < 0) {
    message.error(`${data.drug.drug_name}数量不能小于0！`);
    return;
  }

  if (newNumber === 0) {
    // 数量为0，从清单中移除
    selectList.value = selectList.value.filter(
      (item) => item.index_id !== data.id,
    );

    // 同步更新药品列表
    syncDrugList(data.id, 0);

    // 更新本地存储
    updateSelectStorage();

    // 提示成功
    message.success(`${data.drug.drug_name}已从清单移出！`);
  } else {
    // 更新数量
    selectList.value = selectList.value.map((item) =>
      item.index_id === data.id ? { ...item, select_number: newNumber } : item,
    );

    // 同步更新药品列表
    syncDrugList(data.id, newNumber);

    // 更新本地存储
    updateSelectStorage();

    // 提示成功
    message.success(`${data.drug.drug_name}数量已减少至${newNumber}！`);
  }
}

/**
 * 更新本地存储中的选择列表
 */
function updateSelectStorage() {
  try {
    localStorage.setItem(storageKey.value, JSON.stringify(selectList.value));
    if (isChatMode.value) {
      // 使用 Pinia store 的方法更新 currentDrugs
      updateCurrentDrugs(selectList.value);
    }
  } catch (error) {
    console.error('保存处方数据失败:', error);
    message.error('保存处方数据失败');
  }
}

/**
 * 同步更新药品列表中的数量
 * @param {number} productId - 药品ID
 * @param {number} number - 新的数量
 */
function syncDrugList(productId: number, number: number) {
  // 使用map创建新数组，避免直接修改原数组
  drugList.value = drugList.value.map((item) =>
    item.id === productId ? { ...item, select_number: number } : item,
  );
}

/**
 * 更新药品数量
 * @param {number} id - 药品ID
 * @param {number} number - 新的数量
 */
function updateProductNumber(id: number, number: number) {
  // 验证数量范围
  if (number > 100 || number <= 0) {
    message.error('数量不能大于100或小于1');
    return;
  }

  // 更新选择列表中的数量
  selectList.value = selectList.value.map((item) =>
    item.index_id === id
      ? {
          ...item,
          select_number: number,
          number: number,
        }
      : item,
  );

  // 更新本地存储
  updateSelectStorage();
}

// 使用modal组件
const [Modal, modalApi] = useVbenModal({
  fullscreenButton: false,
  draggable: true,
  onCancel() {
    // 关闭时也更新本地存储
    updateSelectStorage();
    modalApi.close();
  },
  onConfirm: async () => {
    // 更新本地存储
    updateSelectStorage();
    // 调用回调函数
    if (typeof currentDrugsCallback.value === 'function') {
      currentDrugsCallback.value();
    }
    // 关闭modal
    modalApi.close();
    // 提示成功
    message.success('保存成功');
  },
  onOpenChange: async (isOpen: boolean) => {
    if (isOpen) {
      // 获取回调函数
      const data = modalApi.getData();
      currentDrugsCallback.value = data?.getCurrentDrugs;

      // 获取参数
      const { values, activePatient_id, isChat, storagePrefix: prefix } = data || {};

      if (values) {
        // 设置缓存前缀
        storagePrefix.value = prefix || '';
        // 设置药品类型
        type.value = values;
        // 设置患者ID
        activePatientId.value = activePatient_id;
        if (isChat === 'chat') {
          isChatMode.value = true;
          await initializeForModal(
            activePatient_id,
            prefix || 'onlineConsultation-',
          );
          // 弹窗类型与 store tab 对齐，避免读到其它分类的已选
          prescriptionStore.activeCategory = type.value;
          prescriptionStore.loadFromLocalStorage();
          const drugs = prescriptionStore.currentDrugs;
          selectList.value = Array.isArray(drugs) ? [...drugs] : [];
        } else {
          isChatMode.value = false;
        }
        // 获取药品列表
        getDrugList();
      }
    }
  },
});

// 获取类型标签
const getTypeLabel = computed(() => {
  const typeMap: Record<number, string> = {
    3: '保健食品',
    5: '产品服务包',
    6: '非药品',
    7: '医疗器械',
  };
  return typeMap[type.value] || '商品';
});
</script>

<template>
  <Modal :class="'w-[60%]'" :title="`${getTypeLabel}列表`">
    <!-- 图片预览组件 -->
    <Image
      :preview="{
        visible,
        onVisibleChange: setVisible,
      }"
      :src="previewImage"
      :style="{ display: 'none' }"
      :width="200"
    />
    <Page>
      <Row :gutter="12">
        <!-- 搜索框 -->
        <Col :span="24">
          <InputSearch
            v-model:value="searchKey"
            enter-button
            :placeholder="`请输入${getTypeLabel}名称或拼音首拼`"
            @input="(e) => getDrugList(e.target.value)"
            @search="getDrugList"
          />
        </Col>
        <!-- 商品列表 -->
        <Col v-for="item in drugList" :key="item.id" :span="6">
          <Badge :count="item.select_number" class="mt-5">
            <Card hoverable>
              <template #cover>
                <Image :height="200" :src="item.drug?.image" />
              </template>
              <template #actions>
                <MinusOutlined key="prop" @click="propProducts(item)" />
                <ContainerOutlined
                  v-if="item.drug.instruction"
                  @click="setVisible(true, item.drug.instruction)"
                />
                <PlusOutlined key="add" @click="addProducts(item)" />
              </template>
              <CardMeta
                :description="item.drug?.function || item.drug?.specification"
                :title="`${item.drug?.drug_name}${item.drug?.pinyin_simple ? `(${item.drug?.pinyin_simple})` : ''}`"
              >
                <template #avatar>
                  <a-avatar src="https://joeschmoe.io/api/v1/random" />
                </template>
              </CardMeta>
              <div class="card-box mt-5" style="padding: 10px 5px">
                <Popover v-if="item.drug?.function || item.drug?.usage">
                  <template #content>
                    <p v-if="item.drug?.function">功效：{{ item.drug?.function }}</p>
                    <p v-if="item.drug?.usage">用法：{{ item.drug?.usage }}</p>
                  </template>
                </Popover>
                <p class="text-source mt-5">{{ item.drug?.source }}</p>
                <p class="mt-3">单价：￥{{ item.price }}</p>
                <!-- 数量输入框 -->
                <div class="mt-3">
                  <InputNumber
                    v-model:value="item.select_number"
                    :min="0"
                    :max="100"
                    class="w-full"
                    @change="updateProductNumber(item.id, item.select_number)"
                  >
                    <template #addonBefore>
                      <MinusOutlined
                        key="prop"
                        @click="
                          updateProductNumber(
                            item.id,
                            item.select_number > 0 ? item.select_number - 1 : 0,
                          )
                        "
                      />
                    </template>
                    <template #addonAfter>
                      <PlusOutlined
                        key="add"
                        @click="
                          updateProductNumber(
                            item.id,
                            item.select_number < 100
                              ? item.select_number + 1
                              : 100,
                          )
                        "
                      />
                    </template>
                  </InputNumber>
                </div>
              </div>
            </Card>
          </Badge>
        </Col>
      </Row>
    </Page>
  </Modal>
</template>

<style scoped>
.card-box {
  min-height: 100px;
}

.text-source {
  font-size: 12px;
  color: #999;
}
</style>
