<!-- 编辑弹窗 -->
<template>
  <ele-modal
    :width="900"
    :visible="visible"
    :maskClosable="false"
    :maxable="maxable"
    :title="isUpdate ? '编辑商品' : '添加商品'"
    :body-style="{ paddingBottom: '28px' }"
    @update:visible="updateVisible"
    @ok="save"
  >
    <a-form
      ref="formRef"
      :model="form"
      :rules="rules"
      :label-col="styleResponsive ? { md: 3, sm: 5, xs: 24 } : { flex: '90px' }"
      :wrapper-col="
        styleResponsive ? { md: 24, sm: 24, xs: 24 } : { flex: '1' }
      "
    >
      <a-tabs type="card" v-model:active-key="active" @change="onChange">
        <a-tab-pane tab="基本信息" key="base">
          <a-form-item label="商品类型" name="type">
            <a-space>
              <a-button
                :type="form.type == 1 ? 'primary' : ''"
                @click="onType(1)"
                :ghost="form.type == 1"
                >实物商品</a-button
              >
              <a-button
                :type="form.type == 2 ? 'primary' : ''"
                @click="onType(2)"
                :ghost="form.type == 2"
                >虚拟商品</a-button
              >
            </a-space>
            <div class="ele-text-placeholder">
              {{
                form.type == 1
                  ? `支持快递邮寄、同城配送或到店自提方式发货`
                  : '电子券码等，线下到店核销，无需备货'
              }}
            </div>
          </a-form-item>
          <a-form-item
            v-if="!merchantId"
            label="选择店铺"
            name="merchantId"
          >
            <SelectMerchant
              :placeholder="`选择商户`"
              class="input-item"
              style="width: 558px"
              v-model:value="form.merchantName"
              @done="chooseMerchantId"
            />
          </a-form-item>
          <a-form-item label="商品名称" name="goodsName">
            <a-input
              allow-clear
              style="width: 558px"
              placeholder="请输入商品名称"
              v-model:value="form.goodsName"
            />
          </a-form-item>
          <a-form-item label="商品分类" name="categoryId" v-if="!merchantId">
            <SelectGoodsCategory
              :data="data"
              placeholder="请选择商品分类"
              style="width: 558px"
              v-model:value="category"
              @done="chooseGoodsCategory"
            />
          </a-form-item>
          <a-form-item label="菜品分类" name="categoryId" v-else>
            <SelectGoodsCategory
              :merchantId="merchantId"
              placeholder="请选择商品分类"
              style="width: 558px"
              v-model:value="form.categoryId"
              @done="chooseTakeawayCategory"
            />
          </a-form-item>
          <a-form-item label="商品卖点" name="comments">
            <a-input
              allow-clear
              :maxlength="60"
              style="width: 558px"
              placeholder="此款商品美观大方 性价比较高 不容错过"
              v-model:value="form.comments"
            />
          </a-form-item>
          <a-form-item label="单位名称" name="unitName">
            <a-input
              allow-clear
              style="width: 558px"
              placeholder="单位名称，如(个)"
              v-model:value="form.unitName"
            />
          </a-form-item>
          <a-form-item label="市场价" name="salePrice">
            <a-input-number
              :placeholder="`市场价`"
              style="width: 240px"
              :min="0.01"
              v-model:value="form.salePrice"
            />
            <div class="ele-text-placeholder">市场价或划线价仅用于商品页展示</div>
          </a-form-item>
          <a-form-item label="会员价" name="price">
            <a-space>
            <a-input-number
              :placeholder="`会员价`"
              style="width: 240px"
              :min="0.01"
              v-model:value="form.price"
            />
            <a-checkbox v-model:checked="form.priceGift">有赠品</a-checkbox>
            </a-space>
            <div class="ele-text-placeholder">商品的实际购买金额，最低0.01</div>
          </a-form-item>
          <a-form-item label="经销商" name="buyingPrice">
            <a-space>
              <a-input-number
                :placeholder="`经销商价格`"
                style="width: 240px"
                :min="0.01"
                v-model:value="form.dealerPrice"
              />
              <a-checkbox v-model:checked="form.dealerGift">有赠品</a-checkbox>
            </a-space>
            <div class="ele-text-placeholder">经销商价格</div>
          </a-form-item>
          <a-form-item label="进货价" name="buyingPrice">
            <a-space>
              <a-input-number
                :placeholder="`进货价`"
                :min="0.01"
                style="width: 240px"
                v-model:value="form.buyingPrice"
              />
            </a-space>
            <div class="ele-text-placeholder">进货价</div>
          </a-form-item>
          <a-form-item label="当前库存" name="stock">
            <a-input-number
              :placeholder="`商品库存`"
              style="width: 240px"
              v-model:value="form.stock"
            />
            <div class="ele-text-placeholder">划线价仅用于商品页展示</div>
          </a-form-item>
          <a-form-item label="商品图片" name="image">
            <SelectFile
              :placeholder="`请选择视频文件`"
              :limit="1"
              :data="images"
              @done="chooseImage"
              @del="onDeleteItem"
            />
            <div class="ele-text-placeholder"
              >支持上传视频（mp4格式），视频时长不超过60秒，视频大小不超过200M。</div
            >
          </a-form-item>
          <a-form-item label="轮播图" name="files">
            <SelectFile
              :placeholder="`请选择视频文件`"
              :limit="9"
              :data="files"
              @done="chooseFile"
              @del="onDeleteFile"
            />
          </a-form-item>
          <a-form-item label="状态" name="isShow">
            <a-radio-group v-model:value="form.isShow">
              <a-radio :value="1">上架</a-radio>
              <a-radio :value="0">下架</a-radio>
            </a-radio-group>
          </a-form-item>
        </a-tab-pane>
        <a-tab-pane tab="商品规格" key="spec">
          <a-form-item label="规格类型" name="specs">
            <a-radio-group v-model:value="form.specs">
              <a-radio :value="0">单规格</a-radio>
              <a-radio :value="1">多规格</a-radio>
            </a-radio-group>

          </a-form-item>
          <a-form-item name="multipleSpec" v-if="form.specs == 1">
            <div class="w-[300px] ml-10">
              <SelectSpec
                placeholder="选择规格"
                :width="130"
                v-model:value="form.specName"
                @done="onSpec"
              />
            </div>
          </a-form-item>
          <a-form-item name="specValue" v-if="form.specs == 1">
            <a-space direction="vertical" class="ml-[40px]">
              <template v-for="(item, index) in spec" :key="index">
                <div class="text-left flex items-center leading-10 text-gray-400">
                  <div class="mr-2">{{ item.value }} :</div>
                  <CloseCircleOutlined
                    class="cursor-pointer"
                    @click="onClose(index)"
                  />
                </div>
                <ele-edit-tag
                  v-model:data="item.detail"
                  size="middle"
                  shape="round"
                />
              </template>
              <a-card class="ml-[40px]" v-if="showSpecForm">
                <a-form-item name="name">
                  <a-input
                    allow-clear
                    placeholder="请输入规格"
                    v-model:value="name"
                  />
                </a-form-item>
                <a-form-item name="value">
                  <a-input
                    allow-clear
                    placeholder="请输入规格值"
                    v-model:value="value"
                  />
                </a-form-item>
                <a-space>
                  <a-button type="primary" @click="addSpecValue">确定</a-button>
                  <a-button @click="openSpecForm">取消</a-button>
                </a-space>
              </a-card>
              <a-space v-if="spec.length > 0">
                <a-button type="primary" class="mt-5" @click="openSpecForm"
                >添加新规格</a-button
                >
                <a-button type="primary" class="mt-5" @click="generateSku"
                >生成SKU</a-button
                >
              </a-space>
            </a-space>
          </a-form-item>
          <a-form-item name="oneSpec" v-if="form.specs == 1">
            <div class="w-full">
              <div class="sku-table">
                <a-table
                  :pagination="false"
                  :dataSource="skuList"
                  :columns="columns"
                  :scroll="{ y: 500 }"
                >
                  <template #bodyCell="{ record, column, index }">
                    <template v-if="column.key === 'line'">
                      {{ index + 1 }}
                    </template>
                    <template v-if="column.key === 'image'">
                      <SelectFile
                        :placeholder="`请选择商品图片`"
                        :limit="1"
                        :data="record.images || []"
                        :index="index"
                        @done="chooseSkuImage"
                        @del="onDeleteSkuItem"
                      />
                    </template>
                    <template v-if="column.key === 'price'">
                      <a-input :placeholder="`成本价`" v-model:value="skuList[index].price" />
                    </template>
                    <template v-if="column.key === 'salePrice'">
                      <a-input :placeholder="`售价`" v-model:value="record.salePrice" />
                    </template>
                    <template v-if="column.key === 'stock'">
                      <a-input :placeholder="`库存`" v-model:value="record.stock" />
                    </template>
                    <template v-if="column.key === 'skuNo'">
                      <a-input :placeholder="`编码`" v-model:value="record.skuNo" />
                    </template>
                  </template>
                </a-table>
              </div>
            </div>
          </a-form-item>
        </a-tab-pane>
        <a-tab-pane tab="商品详情" key="content">
          <a-form-item name="content">
            <!-- 编辑器 -->
            <tinymce-editor
              ref="editorRef"
              class="content"
              v-model:value="content"
              :disabled="disabled"
              :init="config"
              placeholder="图片直接粘贴自动上传"
              @paste="onPaste"
            />
          </a-form-item>
        </a-tab-pane>
        <a-tab-pane tab="营销设置" key="coupon">
          <a-form-item label="商品重量" name="goodsWeight">
            <a-input
              allow-clear
              style="width: 250px"
              placeholder="请输入商品重量"
              v-model:value="form.goodsWeight"
            />
          </a-form-item>
          <a-form-item label="销量" name="sales">
            <a-input-number
              allow-clear
              style="width: 250px"
              placeholder="请输入销量"
              v-model:value="form.sales"
            />
          </a-form-item>
          <a-form-item label="获取积分" name="gainIntegral">
            <a-input-number
              :placeholder="`消费获取的积分`"
              style="width: 250px"
              v-model:value="form.gainIntegral"
            />
          </a-form-item>
          <a-form-item label="库存计算方式" name="deductStockType">
            <a-radio-group v-model:value="form.deductStockType">
              <a-radio :value="20">付款减库存</a-radio>
              <a-radio :value="10">下单减库存</a-radio>
            </a-radio-group>
          </a-form-item>
          <a-form-item label="货架" name="position">
            <a-input
              allow-clear
              style="width: 250px"
              placeholder="请输入货架"
              v-model:value="form.position"
            />
          </a-form-item>
          <a-form-item label="排序号" name="sortNumber">
            <a-input-number
              :min="0"
              :max="9999"
              style="width: 250px"
              placeholder="请输入排序号"
              v-model:value="form.sortNumber"
            />
          </a-form-item>
        </a-tab-pane>
      </a-tabs>
    </a-form>
  </ele-modal>
</template>

<script lang="ts" setup>
  import { CloseCircleOutlined } from '@ant-design/icons-vue';
  import { ref, reactive, watch } from 'vue';
  import { Form, message } from 'ant-design-vue';
  import { assignObject, uuid } from 'ele-admin-pro';
  import { addGoods, updateGoods } from "@/api/shop/goods";
  import { Goods } from '@/api/shop/goods/model';
  import { useThemeStore } from '@/store/modules/theme';
  import { storeToRefs } from 'pinia';
  import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
  import { FormInstance, RuleObject } from 'ant-design-vue/es/form';
  import { FileRecord } from '@/api/system/file/model';
  import { Merchant } from '@/api/shop/merchant/model';
  import TinymceEditor from '@/components/TinymceEditor/index.vue';
  import { uploadFile, uploadOss } from "@/api/system/file";
  import { SpecValue } from "@/api/shop/specValue/model";
  import { Spec } from "@/api/shop/spec/model";
  import { GoodsSku } from "@/api/shop/goodsSku/model";
  import { GoodsSpec } from "@/api/shop/goodsSpec/model";
  import { generateGoodsSku, listGoodsSku } from "@/api/shop/goodsSku";
  import { listGoodsSpec } from "@/api/shop/goodsSpec";
  import { GoodsCategory } from "@/api/shop/goodsCategory/model";
  import { listGoodsCategory } from "@/api/shop/goodsCategory";
  import { getMerchantId } from "@/utils/merchant";

  // 是否是修改
  const isUpdate = ref(false);
  const useForm = Form.useForm;
  // 是否开启响应式布局
  const themeStore = useThemeStore();
  const { styleResponsive } = storeToRefs(themeStore);

  const props = defineProps<{
    // 弹窗是否打开
    visible: boolean;
    // 修改回显的数据
    data?: Goods | null;
  }>();

  const emit = defineEmits<{
    (e: 'done'): void;
    (e: 'update:visible', visible: boolean): void;
  }>();

  // 提交状态
  const loading = ref(false);
  // 是否显示最大化切换按钮
  const maxable = ref(true);
  // 表格选中数据
  const formRef = ref<FormInstance | null>(null);
  const images = ref<ItemType[]>([]);
  const content = ref('');
  const disabled = ref(false);
  // 当前选项卡
  const active = ref('base');

  const spec = ref<SpecValue[]>([]);
  const showSpecForm = ref(false);
  const name = ref();
  const value = ref();
  const skuList = ref<GoodsSku[]>([]);
  const files = ref<ItemType[]>([]);
  const goodsSpec = ref<GoodsSpec>();
  const category = ref<string[]>([]);
  const takeaway = ref<GoodsCategory[]>([]);
  const merchantId = getMerchantId();

  const columns = [
    {
      title: '图片',
      dataIndex: 'image',
      key: 'image',
      align: 'center'
    },
    {
      title: '售价',
      dataIndex: 'salePrice',
      key: 'salePrice',
      align: 'center',
    },
    {
      title: '成本价',
      dataIndex: 'price',
      key: 'price',
      align: 'center',
    },
    {
      title: '库存',
      dataIndex: 'stock',
      key: 'stock',
      align: 'center',
    },
    {
      title: '商品编号',
      dataIndex: 'skuNo',
      key: 'skuNo',
      align: 'center',
    },
  ];

  // 用户信息
  const form = reactive<Goods>({
    goodsId: undefined,
    type: 1,
    code: undefined,
    goodsName: undefined,
    image: undefined,
    content: undefined,
    unitName: '',
    categoryId: undefined,
    parentName: undefined,
    categoryName: undefined,
    specs: 0,
    position: undefined,
    price: undefined,
    salePrice: undefined,
    buyingPrice: undefined,
    dealerPrice: undefined,
    priceGift: undefined,
    dealerGift: undefined,
    files: undefined,
    sales: 0,
    gainIntegral: 0,
    goodsWeight: undefined,
    recommend: undefined,
    merchantId: undefined,
    merchantName: undefined,
    stock: 1000,
    deductStockType: 20,
    isShow: 1,
    status: 0,
    comments: '',
    sortNumber: 100,
    specName: ''
  });

  /* 更新visible */
  const updateVisible = (value: boolean) => {
    emit('update:visible', value);
  };

  // 表单验证规则
  const rules = reactive({
    type: [
      {
        required: true,
        message: '请选择商品类型',
        type: 'number',
        trigger: 'blur'
      }
    ],
    image: [
      {
        required: true,
        message: '请上传图片',
        type: 'string',
        trigger: 'blur'
      }
    ],
    files: [
      {
        required: true,
        message: '请上传轮播图',
        type: 'string',
        trigger: 'blur',
        validator: async (_rule: RuleObject, value: string) => {
          if (form.files?.length == 0) {
            return Promise.reject('选择上传轮播图');
          }
          return Promise.resolve();
        }
      }
    ],
    specs: [
      {
        required: true,
        message: '请选择规格类型',
        type: 'number',
        trigger: 'blur'
      }
    ],
    price: [
      {
        required: true,
        message: '请填写会员价',
        type: 'number',
        trigger: 'blur'
      }
    ],
    salePrice: [
      {
        required: true,
        message: '请填写市场价',
        type: 'number',
        trigger: 'blur'
      }
    ],
    buyingPrice: [
      {
        required: true,
        message: '请填写进货价',
        type: 'number',
        trigger: 'blur'
      }
    ],
    stock: [
      {
        required: true,
        message: '请填写商品库存',
        type: 'number',
        trigger: 'blur'
      }
    ],
    merchantId: [
      {
        required: true,
        message: '请选择店铺',
        type: 'number',
        trigger: 'blur'
      }
    ],
    categoryId: [
      {
        required: true,
        type: 'string',
        message: '选择商品分类',
        trigger: 'blur',
        validator: async (_rule: RuleObject, value: string) => {
          if (!form.categoryId) {
            return Promise.reject('选择商品分类');
          }
          return Promise.resolve();
        }
      }
    ],
    goodsName: [
      {
        required: true,
        message: '请选择商品名称',
        type: 'string',
        trigger: 'blur'
      }
    ],
    sortNumber: [
      {
        required: true,
        message: '请输入排序号',
        type: 'number',
        trigger: 'blur'
      }
    ]
  });

  const onType = (index: number) => {
    form.type = index;
  };

  /* 搜索 */
  const chooseMerchantId = (item: Merchant) => {
    form.merchantName = item.merchantName;
    form.merchantId = item.merchantId;
  };

  const chooseGoodsCategory = (item: GoodsCategory,value: any) => {
    form.categoryId = value[1].value;
    form.parentName = value[0].label;
    form.categoryName = value[1].label;
  }
  const chooseTakeawayCategory = (item: GoodsCategory, value: any) => {
    form.categoryParent = '店铺分类';
    form.categoryChildren = value[0].label;
    form.categoryId = item[0];
  }

  const chooseImage = (data: FileRecord) => {
    images.value.push({
      uid: data.id,
      url: data.path,
      status: 'done'
    });
    form.image = data.path;
  };

  const chooseSkuImage = (data: FileRecord) => {
    const index = data?.index;
    skuList.value[index].images?.push({
      uid: uuid(),
      url: data.path,
      status: 'done'
    });
    skuList.value[index].image = data.path;
  }

  const onDeleteSkuItem = (index: number) => {
    images.value.splice(index, 1);
  };

  const onChange = (text: string) => {
    // 加载商品多规格
    if(text == 'spec'){
      const goodsId = props.data?.goodsId;
      if(goodsId){
        listGoodsSpec({goodsId}).then(data => {

          const specValue = data[0].specValue;
          if(specValue){
            spec.value = JSON.parse(specValue).map( d => {
              console.log(d);
              return {
                value: d.value,
                detail: d.detail
              };
            })
          }
          console.log(spec.value);
        })
        listGoodsSku({goodsId}).then(data => {
          skuList.value = data;
        })
      }
    }
  };

  const onDeleteItem = (index: number) => {
    images.value.splice(index, 1);
    form.image = '';
  };

  const onClose = (index) => {
    spec.value.splice(index, 1);
  };

  const openSpecForm = () => {
    showSpecForm.value = !showSpecForm.value;
  };

  const onSpec = (row: Spec) => {
    form.specName = row.specName;
    goodsSpec.value = row;
    if(row.specValue){
      spec.value = JSON.parse(row?.specValue);
    }
  }

  // 新增规格
  const addSpecValue = () => {
    if (!name.value || !value.value) {
      message.error(`请输入规格和规格值`);
      return false;
    }
    const findIndex = spec.value.findIndex((d) => d.value == name.value);
    if (findIndex == 0) {
      message.error(`${name.value}已存在)`);
      return false;
    }
    spec.value.push({
      value: name.value,
      detail: [value.value]
    });
    name.value = '';
    value.value = '';
    openSpecForm();
  };

  const chooseFile = (data: FileRecord) => {
    files.value.push({
      uid: data.id,
      url: data.path,
      status: 'done'
    });
  };

  const onDeleteFile = (index: number) => {
    files.value.splice(index, 1);
  };

  /**
   * 生成商品SKU列表
   */
  const generateSku = () => {
    generateGoodsSku(spec.value).then(data => {
      if(data){
        skuList.value = data;
      }
    })
  }

  const editorRef = ref<InstanceType<typeof TinymceEditor> | null>(null);
  const config = ref({
    height: 500,
    images_upload_handler: (blobInfo, success, error) => {
      const file = blobInfo.blob();
      const formData = new FormData();
      formData.append('file', file, file.name);
      uploadOss(file).then(res => {
        success(res.path)
      }).catch((msg) => {
        error(msg);
      })
    },
    // 自定义文件上传(这里使用把选择的文件转成 blob 演示)
    file_picker_callback: (callback: any, _value: any, meta: any) => {
      const input = document.createElement('input');
      input.setAttribute('type', 'file');
      // 设定文件可选类型
      if (meta.filetype === 'image') {
        input.setAttribute('accept', 'image/*');
      } else if (meta.filetype === 'media') {
        input.setAttribute('accept', 'video/*,.pdf');
      }
      input.onchange = () => {
        const file = input.files?.[0];
        if (!file) {
          return;
        }
        if (meta.filetype === 'media') {
          if (file.size / 1024 / 1024 > 200) {
            editorRef.value?.alert({ content: '大小不能超过 200MB' });
            return;
          }
          if(file.type.startsWith('application/pdf')){
            uploadOss(file).then(res => {
              const addPath = `<a href="${res.downloadUrl}" target="_blank">${res.name}</a>`;
              content.value = content.value + addPath
            })
            return;
          }
          if (!file.type.startsWith('video/')) {
            editorRef.value?.alert({ content: '只能选择视频文件' });
            return;
          }
          uploadOss(file).then(res => {
            callback(res.path)
          });
        }
      };
      input.click();
    }
  });

  /* 粘贴图片上传服务器并插入编辑器 */
  const onPaste = (e) => {
    const items = (e.clipboardData || e.originalEvent.clipboardData).items;
    let hasFile = false;
    for (let i = 0; i < items.length; i++) {
      if (items[i].type.indexOf('image') !== -1) {
        let file = items[i].getAsFile();
        const item: ItemType = {
          file,
          uid: (file as any).lastModified,
          name: file.name
        };
        uploadFile(<File>item.file)
          .then((result) => {
            const addPath = `<p><img class="content-img" src="${result.url}"></p>`;
            content.value = content.value + addPath
          })
          .catch((e) => {
            message.error(e.message);
          });
        hasFile = true;
      }
    }
    if (hasFile) {
      e.preventDefault();
    }
  }

  const { resetFields } = useForm(form, rules);

  /* 保存编辑 */
  const save = () => {
    if (!formRef.value) {
      return;
    }
    formRef.value
      .validate()
      .then(() => {
        loading.value = true;
        const formData = {
          ...form,
          content: content.value,
          category: JSON.stringify(category.value),
          files: JSON.stringify(files.value),
          goodsSpec: goodsSpec.value,
          goodsSkus: skuList.value,
          merchantId: getMerchantId(),
          type: getMerchantId() ? 1 : 0
        };
        const saveOrUpdate = isUpdate.value ? updateGoods : addGoods;
        saveOrUpdate(formData)
          .then((msg) => {
            loading.value = false;
            message.success(msg);
            updateVisible(false);
            emit('done');
          })
          .catch((e) => {
            loading.value = false;
            message.error(e.message);
          });
      })
      .catch(() => {});
  };

  watch(
    () => props.visible,
    (visible) => {
      if (visible) {
        images.value = [];
        category.value = [];
        files.value = [];
        if (props.data) {
          assignObject(form, props.data);
          if (props.data.image) {
            images.value.push({
              uid: uuid(),
              url: props.data.image,
              status: 'done'
            });
          }
          if(props.data.files){
            files.value = JSON.parse(props.data.files);
          }
          if(props.data.goodsSpecs){
            goodsSpec.value = props.data.goodsSpecs[0];
            if(props.data.specs == 1){
              form.specName = props.data.goodsSpecs[0].specName;
            }
          }
          if(props.data.goodsSkus){
            skuList.value = props.data.goodsSkus.map(d => {
              d.images = [];
              d.images.push({
                uid: uuid(),
                url: d.image,
                status: 'done'
              })
              return d;
            });
          }
          // 商品分类
          if(props.data.parentName){
            category.value.push(props.data.parentName);
          }
          if(props.data.category){
            category.value = JSON.parse(props.data.category);
          }
          if (props.data.content){
            content.value = props.data.content;
          }
          // 外卖商品分类
          listGoodsCategory({merchantId: props.merchantId}).then(list => {
            takeaway.value = list
          })

          isUpdate.value = true;
        } else {
          spec.value = [];
          goodsSpec.value = undefined;
          skuList.value = [];
          isUpdate.value = false;
        }
      } else {
        resetFields();
      }
    },
    { immediate: true }
  );
</script>
