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

import { useUserStore } from '@vben/stores';

import { DeleteTwoTone } from '@ant-design/icons-vue';
import {
  Button,
  Card,
  Col,
  FormItem,
  InputNumber,
  message,
  Row,
  Select,
  SelectOption,
} from 'ant-design-vue';

import { ChineseDrugNameBubble } from '#/components/chinese-drug-name-bubble';
import { getDrugUseList } from '#/views/doctor/doctor-reception/api';

import PrescriptionDiagnosisOrderCards from './PrescriptionDiagnosisOrderCards.vue';

export interface ChineseDrugItem {
  _key?: number;
  id: number;
  drug_id: number;
  drug_name: string;
  number: number;
  price: number;
  buy_price?: number;
  way_id: number;
  unit_id?: number;
  unit?: { id: number; name: string } | null;
}

const props = withDefaults(
  defineProps<{
    modelValue?: ChineseDrugItem[];
    dosage?: number;
    dayDosage?: number;
    /** 固定价/SKU方案下允许编辑单价 */
    priceEditable?: boolean;
    /** 价格配置弹窗：药名/克数/用法只读，仅价格可改 */
    structureReadonly?: boolean;
    /** 预选诊断（导入特色方时带入） */
    clinicalDiagnose?: string;
    /** 预选医嘱 */
    doctorOrder?: string;
    /** 是否展示诊断/医嘱气泡卡（价格配置等场景可关闭） */
    showDiagnosisOrder?: boolean;
    /** SKU 贴数：大于 1 时展示套餐合计 */
    packageDoseCount?: number;
    /** 固定价占位模式：药味单价展示/保存恒为 0 */
    fixedZeroPrice?: boolean;
  }>(),
  {
    modelValue: () => [],
    dosage: 7,
    dayDosage: 2,
    priceEditable: false,
    structureReadonly: false,
    clinicalDiagnose: '',
    doctorOrder: '',
    showDiagnosisOrder: true,
    packageDoseCount: 1,
    fixedZeroPrice: false,
  },
);

const emit = defineEmits<{
  'update:modelValue': [value: ChineseDrugItem[]];
  'update:dosage': [value: number];
  'update:dayDosage': [value: number];
  'update:clinicalDiagnose': [value: string];
  'update:doctorOrder': [value: string];
}>();

const userStore = useUserStore();
const drugList = ref<ChineseDrugItem[]>([]);
const dosageLocal = ref(props.dosage);
const dayDosageLocal = ref(props.dayDosage);
const diagnosisOrderCardsRef = ref<InstanceType<typeof PrescriptionDiagnosisOrderCards>>();

/** 价格配置只读模式下不展示诊断/医嘱区 */
const showDiagnosisOrderPanel = computed(
  () => props.showDiagnosisOrder && !props.structureReadonly,
);

/** 一贴销售价合计（价格配置均分核对用） */
const doseSaleTotal = computed(() => {
  const sum = drugList.value.reduce(
    (acc, drug) => acc + Number(drug.price || 0) * Number(drug.number || 1),
    0,
  );
  return sum.toFixed(2);
});

/** 套餐销售价合计 = 一贴合计 × 贴数 */
const packageSaleTotal = computed(() => {
  const dose = Math.max(1, Number(props.packageDoseCount || 1));
  return (Number(doseSaleTotal.value) * dose).toFixed(2);
});

/** 预选诊断双向绑定 */
const clinicalDiagnoseModel = computed({
  get: () => props.clinicalDiagnose ?? '',
  set: (val: string) => emit('update:clinicalDiagnose', val),
});

/** 预选医嘱双向绑定 */
const doctorOrderModel = computed({
  get: () => props.doctorOrder ?? '',
  set: (val: string) => emit('update:doctorOrder', val),
});

const drugUseWay = ref<any[]>([]);
const newDrugInfo = ref<{
  id?: number;
  name?: string;
  number?: number;
  price?: number;
  way_id?: number;
  unit_id?: number;
  unit?: { id: number; name: string } | null;
}>({});

onMounted(async () => {
  drugList.value = [...(props.modelValue || [])];
  try {
    const res = await getDrugUseList();
    drugUseWay.value = res.drug_use_way || [];
  } catch (error) {
    console.error('加载药品用法失败:', error);
  }
});

function getWayName(wayId: number) {
  if (!wayId) return '煎服';
  const item = drugUseWay.value.find((w) => Number(w.id) === Number(wayId));
  return item?.name || '煎服';
}

function syncToParent() {
  emit('update:modelValue', [...drugList.value]);
  emit('update:dosage', dosageLocal.value);
  emit('update:dayDosage', dayDosageLocal.value);
}

/**
 * 中药气泡：选中新增行
 * @param selectedItem 商品检索完整行
 */
function selectNewDrug(selectedItem: any) {
  const drugId = Number(selectedItem?.drug?.id || selectedItem?.drug_id || 0);
  if (!drugId) return;
  const exists = drugList.value.some(
    (item) => item.id === drugId || item.drug_id === drugId,
  );
  if (exists) {
    message.warning('该药品已在列表中');
    newDrugInfo.value.id = undefined;
    newDrugInfo.value.name = '';
    return;
  }
  newDrugInfo.value.id = drugId;
  newDrugInfo.value.name = selectedItem.drug?.drug_name || '';
  newDrugInfo.value.price = selectedItem.price || 0;
  newDrugInfo.value.way_id = 0;
  newDrugInfo.value.unit =
    selectedItem.drug?.unit || selectedItem.unit || null;
  newDrugInfo.value.unit_id =
    selectedItem.drug?.unit_id || selectedItem.unit_id || 0;
  nextTick(() => {
    const numberInput = document.querySelector(
      '.new-chinese-number input',
    ) as HTMLInputElement;
    numberInput?.focus();
  });
}

function addChineseDrug() {
  if (!newDrugInfo.value.id) {
    message.warning('请先选择药品');
    return;
  }
  if (!newDrugInfo.value.number || newDrugInfo.value.number <= 0) {
    message.warning('请输入正确的克数');
    return;
  }
  drugList.value.push({
    _key: Date.now(),
    id: newDrugInfo.value.id,
    drug_id: newDrugInfo.value.id,
    drug_name: newDrugInfo.value.name || '',
    number: newDrugInfo.value.number,
    price: newDrugInfo.value.price || 0,
    way_id: newDrugInfo.value.way_id || 0,
    unit_id: newDrugInfo.value.unit_id || 0,
    unit: newDrugInfo.value.unit || null,
  });
  newDrugInfo.value = {};
  syncToParent();
  message.success('已添加药品');
  nextTick(() => {
    const nameInput = document.querySelector(
      '.new-chinese-name input',
    ) as HTMLInputElement;
    nameInput?.focus();
  });
}

function handleChineseKeydown(event: KeyboardEvent, isNew: boolean) {
  if (event.key === 'Enter') {
    event.preventDefault();
    if (isNew) {
      addChineseDrug();
    }
  }
}

/**
 * 中药气泡：替换已有行
 * @param index 行下标
 * @param selectedItem 商品检索完整行
 */
function changeChineseDrug(index: number, selectedItem: any) {
  const drugId = Number(selectedItem?.drug?.id || selectedItem?.drug_id || 0);
  if (!drugId) return;
  const exists = drugList.value.some(
    (item, i) => i !== index && (item.id === drugId || item.drug_id === drugId),
  );
  if (exists) {
    message.warning('该药品已在列表中');
    return;
  }
  const drug = drugList.value[index];
  if (drug) {
    drug.id = drugId;
    drug.drug_id = drugId;
    drug.drug_name = selectedItem.drug?.drug_name || '';
    drug.price = selectedItem.price || 0;
    drug.unit = selectedItem.drug?.unit || selectedItem.unit || null;
    drug.unit_id = selectedItem.drug?.unit_id || selectedItem.unit_id || 0;
    syncToParent();
    nextTick(() => {
      const numberInput = document.querySelector(
        `.chinese-number-${index} input`,
      ) as HTMLInputElement;
      numberInput?.focus();
    });
  }
}

function removeDrug(index: number) {
  drugList.value.splice(index, 1);
  syncToParent();
}

function onDrugNumberChange() {
  syncToParent();
}

function onDosageChange() {
  syncToParent();
}

function loadDrugs(recipes: any[], dosage?: number, dayDosage?: number, drugPrices?: any[]) {
  const priceMap = new Map<number, { buy_price: number; sell_price: number }>();
  (drugPrices || []).forEach((item) => {
    priceMap.set(Number(item.drug_id), {
      buy_price: Number(item.buy_price || 0),
      sell_price: Number(item.sell_price || item.price || 0),
    });
  });
  drugList.value = (recipes || []).map((recipe) => {
    const drugId = recipe.drug_id || recipe.id;
    const configured = priceMap.get(Number(drugId));
    const zeroPrice = props.fixedZeroPrice;
    return {
      _key: Date.now() + Math.random(),
      id: drugId,
      drug_id: drugId,
      drug_name: recipe.drug_name || recipe.name || '',
      number: recipe.number || 1,
      price: zeroPrice ? 0 : (configured?.sell_price ?? recipe.price ?? 0),
      buy_price: zeroPrice ? 0 : (configured?.buy_price ?? recipe.buy_price ?? 0),
      way_id: recipe.way_id || 0,
      unit_id: recipe.unit_id || 0,
      unit: recipe.unit || null,
    };
  });
  if (dosage !== undefined) dosageLocal.value = dosage;
  if (dayDosage !== undefined) dayDosageLocal.value = dayDosage;
  syncToParent();
}

function applyDistributedPrices(items: Array<{ drug_id: number; buy_price: number | string; sell_price: number | string }>) {
  const priceMap = new Map<number, { buy_price: number; sell_price: number }>();
  items.forEach((item) => {
    priceMap.set(Number(item.drug_id), {
      buy_price: Number(item.buy_price || 0),
      sell_price: Number(item.sell_price || 0),
    });
  });
  drugList.value.forEach((drug) => {
    const configured = priceMap.get(Number(drug.drug_id || drug.id));
    if (configured) {
      drug.price = configured.sell_price;
      drug.buy_price = configured.buy_price;
    }
  });
  syncToParent();
}

function getDrugPricesPayload() {
  return drugList.value.map((drug) => ({
    drug_id: drug.drug_id || drug.id,
    buy_price: drug.buy_price ?? 0,
    sell_price: drug.price ?? 0,
  }));
}

function getDrugsForDistribute() {
  return drugList.value.map((drug) => ({
    drug_id: drug.drug_id || drug.id,
    number: drug.number || 1,
  }));
}

function getDrugsPayload() {
  return drugList.value.map((drug) => ({
    drug_id: drug.drug_id || drug.id,
    drug_name: drug.drug_name,
    number: drug.number || 1,
    price: drug.price || 0,
    way_id: drug.way_id || 0,
  }));
}

defineExpose({
  getDrugsPayload,
  getDrugPricesPayload,
  getDrugsForDistribute,
  applyDistributedPrices,
  loadDrugs,
  drugList,
  getDiagnosisOrderPayload: () =>
    diagnosisOrderCardsRef.value?.getDiagnosisOrderPayload?.() ?? {
      clinical_diagnose: props.clinicalDiagnose || '',
      doctor_order: props.doctorOrder || '',
    },
});
</script>

<template>
  <div class="chinese-drug-editor">
    <Row v-if="!structureReadonly" :gutter="16" class="mb-4">
      <Col :span="12">
        <FormItem label="剂量（天/剂）">
          <InputNumber
            v-model:value="dosageLocal"
            :min="1"
            :max="100"
            style="width: 100%"
            @change="onDosageChange"
          />
        </FormItem>
      </Col>
      <Col :span="12">
        <FormItem label="频次（次/天）">
          <InputNumber
            v-model:value="dayDosageLocal"
            :min="1"
            :max="10"
            style="width: 100%"
            @change="onDosageChange"
          />
        </FormItem>
      </Col>
    </Row>
    <div v-else-if="dosageLocal || dayDosageLocal" class="readonly-meta mb-3 text-gray-500">
      剂量 {{ dosageLocal }} 天/剂 · 频次 {{ dayDosageLocal }} 次/天
    </div>

    <FormItem :label="structureReadonly ? '' : '药品列表'" :required="!structureReadonly">
      <PrescriptionDiagnosisOrderCards
        v-if="showDiagnosisOrderPanel"
        ref="diagnosisOrderCardsRef"
        v-model:clinical-diagnose="clinicalDiagnoseModel"
        v-model:doctor-order="doctorOrderModel"
      />
      <Row :gutter="[12, 12]">
        <Col
          v-for="(drug, index) in drugList"
          :key="drug._key"
          :xs="24"
          :sm="12"
          :md="8"
          :lg="8"
        >
          <Card size="small" class="chinese-drug-card">
            <div class="chinese-drug-content">
              <span class="chinese-drug-index">{{ index + 1 }}、</span>
              <div v-if="structureReadonly" class="chinese-drug-readonly">
                <span class="chinese-drug-name-text">{{ drug.drug_name }}</span>
                <span class="chinese-drug-comma">，</span>
                <span>{{ drug.number }}{{ drug.unit?.name || 'g' }}</span>
                <span class="chinese-drug-comma">，</span>
                <span>{{ getWayName(drug.way_id) }}</span>
              </div>
              <div v-else class="chinese-drug-form">
                <ChineseDrugNameBubble
                  :display-name="drug.drug_name"
                  :store-id="userStore.userInfo?.store_id || 0"
                  :type="1"
                  compact
                  input-class="chinese-drug-name"
                  placeholder="药名"
                  @select="(item) => changeChineseDrug(index, item)"
                />
                <span class="chinese-drug-comma">，</span>
                <InputNumber
                  v-model:value="drug.number"
                  :class="`chinese-number-${index}`"
                  :controls="false"
                  :min="1"
                  style="width: 60px"
                  @change="onDrugNumberChange"
                />
                <span class="chinese-drug-unit">{{ drug.unit?.name || 'g' }}</span>
                <span class="chinese-drug-comma">，</span>
                <Select
                  v-model:value="drug.way_id"
                  placeholder="用法"
                  style="width: 70px"
                  @change="onDrugNumberChange"
                >
                  <SelectOption :value="0">煎服</SelectOption>
                  <SelectOption
                    v-for="item in drugUseWay"
                    :key="item.id"
                    :value="item.id"
                  >
                    {{ item.name }}
                  </SelectOption>
                </Select>
              </div>
              <div class="chinese-drug-price">
                <template v-if="priceEditable && !fixedZeroPrice">
                  <div class="price-edit-row">
                    <span>售</span>
                    <InputNumber
                      v-model:value="drug.price"
                      :min="0.01"
                      :precision="2"
                      :controls="false"
                      size="small"
                      style="width: 72px"
                      @change="onDrugNumberChange"
                    />
                    <span>供</span>
                    <InputNumber
                      v-model:value="drug.buy_price"
                      :min="0.01"
                      :precision="2"
                      :controls="false"
                      size="small"
                      style="width: 72px"
                      @change="onDrugNumberChange"
                    />
                  </div>
                  <div class="price-line-total">
                    小计 ￥{{ ((drug.price || 0) * (drug.number || 1)).toFixed(2) }}
                  </div>
                </template>
                <template v-else-if="fixedZeroPrice">
                  单价 ¥0.00
                </template>
                <template v-else>
                  ￥{{ ((drug.price || 0) * (drug.number || 1)).toFixed(2) }}
                </template>
              </div>
              <Button
                v-if="!structureReadonly"
                type="link"
                class="chinese-drug-delete"
                @click="removeDrug(index)"
              >
                <DeleteTwoTone two-tone-color="#ff4d4f" />
              </Button>
            </div>
          </Card>
        </Col>

        <Col v-if="!structureReadonly" :xs="24" :sm="12" :md="8" :lg="8">
          <Card size="small" class="chinese-drug-card chinese-drug-card-new">
            <div class="chinese-drug-content">
              <span class="chinese-drug-index">{{ drugList.length + 1 }}、</span>
              <div class="chinese-drug-form">
                <ChineseDrugNameBubble
                  :display-name="newDrugInfo.name || ''"
                  :store-id="userStore.userInfo?.store_id || 0"
                  :type="1"
                  compact
                  input-class="chinese-drug-name new-chinese-name"
                  placeholder="药名"
                  @select="selectNewDrug"
                />
                <span class="chinese-drug-comma">，</span>
                <InputNumber
                  v-model:value="newDrugInfo.number"
                  class="new-chinese-number"
                  :controls="false"
                  :min="1"
                  style="width: 60px"
                  @keydown="(e) => handleChineseKeydown(e, true)"
                />
                <span class="chinese-drug-unit">{{ newDrugInfo.unit?.name || 'g' }}</span>
                <span class="chinese-drug-comma">，</span>
                <Select
                  v-model:value="newDrugInfo.way_id"
                  placeholder="用法"
                  style="width: 70px"
                  @keydown="(e) => handleChineseKeydown(e, true)"
                >
                  <SelectOption :value="0">煎服</SelectOption>
                  <SelectOption v-for="item in drugUseWay" :key="item.id" :value="item.id">
                    {{ item.name }}
                  </SelectOption>
                </Select>
              </div>
              <div class="chinese-drug-price">
                ￥{{ ((newDrugInfo.price || 0) * (newDrugInfo.number || 1)).toFixed(2) }}
              </div>
            </div>
          </Card>
        </Col>
      </Row>
      <div v-if="priceEditable && !fixedZeroPrice" class="price-allocation-summary">
        <span>一贴合计：￥{{ doseSaleTotal }}</span>
        <span v-if="packageDoseCount > 1" class="ml-4">套餐合计：￥{{ packageSaleTotal }}</span>
      </div>
    </FormItem>
  </div>
</template>

<style lang="scss" scoped>
.chinese-drug-card {
  position: relative;
  min-height: 80px;

  :deep(.ant-card-body) {
    padding: 12px;
  }
}

.chinese-drug-card-new {
  border-style: dashed;
}

.chinese-drug-content {
  position: relative;
}

.chinese-drug-index {
  position: absolute;
  left: 0;
  top: 0;
  font-size: 16px;
  font-weight: bold;
  @apply text-primary;
}

.chinese-drug-form {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 4px;
  padding-left: 28px;
  overflow: hidden;
}
/* 药名气泡锁宽，与克数/用法保持同一行 */
.chinese-drug-form :deep(.chinese-drug-name-bubble) {
  width: 100px !important;
  min-width: 88px !important;
  max-width: 110px !important;
  flex: 0 0 100px !important;
}

.chinese-drug-readonly {
  display: inline;
  padding-left: 24px;
  line-height: 1.6;
}

.chinese-drug-name-text {
  font-weight: 500;
}

.chinese-drug-comma {
  @apply text-muted-foreground;
}

.chinese-drug-unit {
  @apply text-muted-foreground text-xs;
}

.chinese-drug-price {
  position: absolute;
  right: 24px;
  bottom: 0;
  @apply text-destructive font-medium;
  text-align: right;
}

.price-edit-row {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
}

.price-line-total {
  font-size: 12px;
  margin-top: 2px;
}

.price-allocation-summary {
  margin-top: 12px;
  padding: 8px 12px;
  font-size: 13px;
  font-weight: 600;
  border: 1px solid hsl(var(--border));
  border-radius: 6px;
  background: hsl(var(--muted) / 0.3);
  color: hsl(var(--foreground));
}

.chinese-drug-delete {
  position: absolute;
  right: -8px;
  top: -8px;
  padding: 4px;
}
</style>
