import { mapActions, mapGetters } from 'vuex';
import FuseSearch from 'fuse.js';
import { defineComponent } from '@vue/composition-api';
import lodash from 'lodash';
import asyncRetry from 'async-retry';
import Promise from 'bluebird';
import configShopee from '@/config/shopee';
import { TiktokProductMirgateShopee } from '@/adapter/tiktok/product';
import * as shopeeRender from '@/adapter/shopee/render/index';
import { shopeeSetting } from '@/plugins/setting';
import { gptWriterProductDescription, gptWriterProductTitle } from '@/api/gpt';
import { zipFileBase64, getBase64Url } from '@/lib/utils/save';
import { useUsageStore } from '@/vue/pinia/usage';
import { UsageTiktok } from '@/models/usage';
import { MappingProductCategory } from '@/models/mapping';
import { getTiktokProductId } from '@/api/tiktok/client/product';
import { getShopeeCategoryTreeList } from '@/api/shopee/client/category';
import {
  getShopeeAttributeCategoryId, shopeeSellerCreateProduct, shopeeSellerSearchProductList,
} from '@/api/shopee/seller/product/index';
import moment from 'moment';
import { loggerTiktok } from '@/plugins/logger';

const configShopeeProduct = configShopee.product;
const usageStore = useUsageStore();

const colorStatus = {
  text: '#000',
  pending: '#ff9900',
  success: '#19be6b',
  error: '#ed4014',
};

const productCloneRetry = {
  retries: 3,
  maxTimeout: 30 * 1000,
  factor: 1,
};

export default defineComponent({
  props: {
    productId: {
      type: String || Number,
      require: true,
    },
  },
  data() {
    /** @type {ProductCloneEditPayload} */
    const editData = {
      title: {
        prepend: '',
        append: '',
        gptWriter: false,
      },
      description: {
        prepend: '',
        append: '',
        json: false,
        gptWriter: false,
      },
      price: {
        beforeDiscount: false,
        change: '',
      },
      image: {
        spin: false,
      },
      replace: {
        phone: '',
        address: '',
      },
      weight: 10,
      expiredDay: 365,
      skipDuplicateSku: true,
      unlisted: false,
      logisticsChannels: [],
    };

    const logClone = {
      color: colorStatus.text,
      text: '',
      process: '',
      detail: {},
    };

    const shopWarehouse = {
      selected: shopeeSetting.shopeeShopWarehouse.get(),
      options: [],
    };

    /** @type {TiktokPdpProductId} */
    const tiktokProduct = {
      sku: '',
      name: '',
      description: '',
    };

    const categoryProduct = {
      originCategoryTree: '',
      originCategoryId: '',
      selected: '',
      categoryId: '',
      list: getShopeeCategoryTreeList(),
      options: getShopeeCategoryTreeList().map((item) => {
        const categoryId = item.category_id;
        const categoryTree = item.path.map((cat) => cat.category_name);
        return {
          value: categoryId,
          name: categoryTree.join(' > '),
        };
      }),
    };

    return {
      categoryProduct,
      log: logClone,
      tiktokProduct,
      editData,
      shopWarehouse,
      btnDisable: false,
      btnLoading: false,
      productLoading: false,
    };
  },
  methods: {
    ...mapActions(['ShopeeSetClonePayload', 'ShopeeSellerConfig']),
    openSellerLogin() {
      this.openExternalUrl(shopeeRender.sellerLoginUrl, false);
    },
    async openSpyProduct() {
      this.openPopupUrl('/tiktok/spy/product', {
        productId: this.tiktokProduct.item_id,
        shopId: this.tiktokProduct.shop_id,
      });
    },
    async openFetchReview() {
      this.openPopupUrl('/tiktok/product/review/get', {
        productId: this.tiktokProduct.item_id,
        shopId: this.tiktokProduct.shop_id,
      });
    },
    async openViewImage() {
      const listAllImage = this.getListImageUrl();
      this.openPopupUrl('/shopee/product/image/view', {
        source: JSON.stringify(listAllImage),
      });
    },
    getListImageUrl() {
      const productInfo = this.tiktokProduct.initialData.productInfo;

      const listUrl = productInfo.product_base.images.map((imageData, indexImage) => {
        const url = TiktokProductMirgateShopee.getTiktokImageUrl(imageData.uri);
        return {
          url,
          fileName: `main-${indexImage + 1}.jpg`,
          type: 'main',
        };
      });

      productInfo.sale_props.forEach((prop) => {
        if (prop.has_image) {
          prop.sale_prop_values.forEach((value, indexImage) => {
            if (value.image && value.image.uri) {
              const url = TiktokProductMirgateShopee.getTiktokImageUrl(value.image.uri);

              listUrl.push({
                url,
                fileName: `variation-${indexImage + 1}.jpg`,
                type: 'variation',
              });
            }
          });
        }
      });

      return listUrl;
    },
    async findCategoryMatch() {
      const categoryList = this.tiktokProduct.categoryInfo;
      this.categoryProduct.originCategoryTree = categoryList.map((cat) => cat.category_name).join(' > ');
      this.categoryProduct.originCategoryId = categoryList.at(-1).category_id;

      const whereMapping = {
        from: 'tiktok',
        to: 'shopee',
        categoryIdFrom: this.categoryProduct.originCategoryId.toString(),
      };

      const categoryMapping = await MappingProductCategory.findOne(whereMapping);

      if (categoryMapping) {
        this.categoryProduct.selected = Number(categoryMapping.categoryIdTo);

        return this.categoryProduct.selected;
      }

      let fuseSearch = new FuseSearch(this.categoryProduct.options, {
        keys: ['name'],
        threshold: 0.4,
      });

      let results = fuseSearch.search([
        categoryList.at(-2).category_name,
        categoryList.at(-1).category_name,
      ].join(' '));

      if (!(results && results.length)) {
        results = fuseSearch.search([
          categoryList.at(-3).category_name,
          categoryList.at(-2).category_name,
          categoryList.at(-1).category_name,
        ].join(' '));
      }

      if (!(results && results.length)) {
        fuseSearch = new FuseSearch(this.categoryProduct.options, {
          keys: ['name'],
          threshold: 0.5,
        });

        results = fuseSearch.search([
          categoryList.at(-3).category_name,
          categoryList.at(-2).category_name,
          categoryList.at(-1).category_name,
        ].join(' '));
      }

      if (results && results.length) {
        const categoryId = results[0].item.value;
        this.categoryProduct.selected = Number(categoryId);
      }
    },
    async  saveCategoryMatch() {
      if (!this.categoryProduct.selected) {
        return false;
      }

      const whereMapping = {
        from: 'tiktok',
        to: 'shopee',
        categoryIdFrom: this.categoryProduct.originCategoryId.toString(),
      };

      const payloadSave = {
        ...whereMapping,
        categoryIdTo: this.categoryProduct.selected.toString(),
      };

      const categoryMapping = await MappingProductCategory.findOne(whereMapping);

      if (categoryMapping) {
        return MappingProductCategory.updateId(categoryMapping._id, payloadSave);
      }

      return MappingProductCategory.insert(payloadSave);
    },
    renderProduct() {
      if (!(this.tiktokProduct && this.tiktokProduct.initialData)) {
        return null;
      }

      const tiktokProduct = this.tiktokProduct.initialData.productInfo;

      this.tiktokProduct.name = tiktokProduct.product_base.title;
      this.tiktokProduct.id = tiktokProduct.product_id.toString();
      this.tiktokProduct.sku = tiktokProduct.product_id.toString();
      this.tiktokProduct.description = JSON.parse(tiktokProduct.product_base.desc_detail)
        .map((item) => item.text)
        .filter((text) => text).join('\n')
        .trim();

      this.findCategoryMatch();
    },
    onChangeWarehouse(value) {
      shopeeSetting.shopeeShopWarehouse.set(value);
    },
    async getBase64ListImage() {
      const listImage = this.getListImageUrl();

      const listBase64 = await Promise.mapSeries(listImage, async (item) => {
        const base64 = await getBase64Url(item.url);

        return {
          ...item,
          base64,
        };
      });

      return listBase64;
    },
    async downLoadAllImageZip() {
      this.btnDisable = true;

      try {
        const saveName = `${lodash.snakeCase(this.tiktokProduct.name)}.zip`;

        const listFileBase64 = await this.getBase64ListImage();

        await zipFileBase64(listFileBase64, saveName);
      } catch (error) {}

      this.btnDisable = false;
    },
    async copyProduct() {
      if (!usageStore.getUsageTiktokCloneProduct.allow) {
        return this.$Message.error({
          content: usageStore.getUsageTiktokCloneProduct.errorMsg,
          top: 450,
          duration: 2,
        });
      }

      if (!this.categoryProduct.selected) {
        this.log.text = this.$t('COPY_PRODUCT_SELECT_CATEGORY_MAPPING');
        this.log.color = colorStatus.error;

        return false;
      }

      let isActive = true;
      this.btnDisable = true;
      this.log.color = colorStatus.pending;
      this.log.text = this.$t('PRODUCT_COPYING');

      const productCloneOption = this.editData;

      if (productCloneOption.skipDuplicateSku) {
        try {
          const searchSku = this.tiktokProduct.sku;
          const { listProduct } = await shopeeSellerSearchProductList(searchSku, 1, 20, 'sku');

          if (listProduct && listProduct.length) {
            this.log.text = this.$t('PRODUCT_CREATE_ERROR_WAS_DUPLICATE');
            this.log.color = colorStatus.error;
            isActive = false;
          }
        } catch (error) {
          this.log.text = this.$t('SHOPEE_NO_LOGIN');
          this.log.color = colorStatus.error;
          isActive = false;
        }
      }

      if (!isActive) {
        this.btnDisable = false;

        return false;
      }

      const logisticIdSelected = this.getShopeeSellerLogistic.selected;

      if (!logisticIdSelected.length) {
        this.log.text = this.$t('SHOP_LOGISTIC_NOT_ENABLE');
        this.log.color = colorStatus.error;

        this.btnDisable = false;

        return false;
      }

      const MirgateProductShopee = new TiktokProductMirgateShopee(this.tiktokProduct);

      try {
        const categoryId = Number(this.categoryProduct.selected);

        /** @type {Array} */
        const listCategory = this.categoryProduct.list.find((cat) => cat.category_id === categoryId).path.map((cat) => cat.category_id);

        const listAttribute = (await getShopeeAttributeCategoryId(categoryId)) || [];
        const listWarehouseId = this.shopWarehouse.selected.filter((warehouseId) => this.shopWarehouse.options.find((item) => item.value === warehouseId));

        const expiryDateAttribute = listAttribute.find((attr) => attr.name === 'Expiry Date' || [100061].includes(attr.attribute_id));

        MirgateProductShopee.listAttribute = [];
        MirgateProductShopee.listWarehouse = listWarehouseId;
        MirgateProductShopee.listCategory = listCategory;
        MirgateProductShopee.listLogistic = logisticIdSelected.map((id) => {
          return {
            price: '0',
            cover_shipping_fee: false,
            enabled: true,
            item_flag: '0',
            channelid: id,
            sizeid: 0,
          };
        });

        if (expiryDateAttribute) {
          const expiredDay = Number(lodash.get(productCloneOption, 'expiredDay', 0)) || 365;

          MirgateProductShopee.listAttribute.push({
            attribute_id: expiryDateAttribute.attribute_id,
            custom_value: {
              raw_value: moment().add(expiredDay, 'day').unix().toString(),
              unit: '',
            },
          });
        }

        const callbackLogImage = ({ imageUrl, imageIndex }) => {
          this.log.process = this.$t('MIRGATE_PRODUCT_IMAGE_URL', { url: imageUrl, index: imageIndex });
        };

        await MirgateProductShopee.mirgateImageList(callbackLogImage);

        this.log.process = '';

        /** @type {TiktokProductMirgateShopeePayload} */
        const mirgatePayload = {
          unListed: productCloneOption.unlisted,
          weight: productCloneOption.weight,
          beforeDiscount: productCloneOption.price.beforeDiscount,
          priceChange: productCloneOption.price.change,
          sku: this.tiktokProduct.sku,
          name: this.tiktokProduct.name,
          description: this.tiktokProduct.description,
        };

        /** @type {ShopeePayloadProductCreate} */
        const payloadProduct = MirgateProductShopee.getPayload(mirgatePayload);

        if (productCloneOption.title.gptWriter) {
          this.log.text = this.$t('PRODUCT_CLONE_LOG_GPT_WRITER_TITLE');
          payloadProduct.name = await gptWriterProductTitle(payloadProduct.name);
        }

        if (productCloneOption.description.gptWriter) {
          this.log.text = this.$t('PRODUCT_CLONE_LOG_GPT_WRITER_DESCRIPTION');
          payloadProduct.description = await gptWriterProductDescription(payloadProduct.description);
        }

        payloadProduct.name = [
          productCloneOption.title.prepend,
          payloadProduct.name,
          productCloneOption.title.append,
        ].join(' ');

        payloadProduct.description = [
          productCloneOption.description.prepend,
          payloadProduct.description,
          productCloneOption.description.append,
        ].join('\n\n');

        const cloneResult = await asyncRetry(async (stopClone) => {
          const createResult = await shopeeSellerCreateProduct(payloadProduct);

          const msgError = lodash.get(createResult, 'user_message', '').toLowerCase();

          loggerTiktok.info({
            msg: 'COPY_PRODUCT_DONE',
            result: createResult,
            payload: payloadProduct,
            msgError,
          });

          if (lodash.has(createResult, 'data.product_id')) {
            return createResult;
          }

          if (msgError.includes('listing limit')) {
            return createResult;
          }

          const matchImgInvalid = 'image is invalid: ';

          if (msgError.includes(matchImgInvalid)) {
            const listImageIdError = msgError.replace(matchImgInvalid, '').trim().split(',');
            payloadProduct.images = payloadProduct.images.filter((imageCurrent) => !listImageIdError.find((imgError) => imageCurrent.includes(imgError)));
          } else if (msgError.includes('image for product description')) {
            payloadProduct.description_json = null;
          } else if (msgError.includes('hỏa tốc')) {
            payloadProduct.logistics_channels = payloadProduct.logistics_channels.filter(({ channelid }) => channelid !== 5000);
          } else if (msgError.includes('size chart')) {
            const sizeChartUrl = configShopeeProduct.sizeChartDefault;
            const sizeChartId = shopeeRender.imageId(sizeChartUrl);

            payloadProduct.size_chart_info = {
              size_chart_id: 0,
              size_chart: sizeChartId,
            };
          } else if (msgError.includes('brand')) {
            payloadProduct.brand_id = 0;
          } else if (msgError.includes('product is duplicated')) {
            payloadProduct.name += '0';
          } else if (msgError.includes('condition.enum')) {
            payloadProduct.condition = 1;
          } else if (msgError.includes('create product')) {
            if (payloadProduct.video_list) {
              payloadProduct.video_list = [];
            } else if (payloadProduct.attributes.length) {
              payloadProduct.attributes = [];
            }
          } else if (msgError.includes('mandatory_direct')) {
            throw 'RETRY_CLONE';
          } else {
            stopClone(createResult);
          }

          throw 'RETRY_CLONE';
        }, productCloneRetry);

        if (lodash.has(cloneResult, 'data.product_id')) {
          const productId = cloneResult.data.product_id;

          const payloadUsage = {
            type: 'productClone',
            shopId: this.getShopeeShopId,
            payload: {
              from: 'shopee',
              name: this.tiktokProduct.name,
              productId: this.tiktokProduct.item_id,
              shopId: this.tiktokProduct.shop_id,
            },
            result: {
              name: payloadProduct.name,
              productId,
              shopId: this.getShopeeShopId,
            },
          };

          UsageTiktok.insert(payloadUsage).catch((error) => {
            loggerTiktok.error({
              msg: 'USAGE_PRODUCT_CLONE_ERROR',
              error,
              payloadUsage,
            });
          });

          usageStore.incTiktokCloneProduct();

          this.log.text = this.$t('PRODUCT_CREATE_SUCCESS');
          this.log.color = colorStatus.success;

          this.openExternalUrl(shopeeRender.productSeller(productId), false);

          this.btnDisable = false;

          return productId;
        }

        const errorCode = cloneResult.code.toString();
        const errorMsg = lodash.get(cloneResult, 'user_message', '') || lodash.get(cloneResult, 'message', '');

        const mapErrorCode = {
          100011445: this.$t('SHOP_IS_OFF_STATUS'),
          100010006: this.$t('SHOP_REACH_MAX_PRODUCT'),
          100021445: this.$t('SHOP_MISSING_LOGISTIC'),
          100010239: this.$t('PRODUCT_INVALID_LOGISTIC'),
          100010243: this.$t('COPY_PRODUCT_TOO_FAST'),
          100010242: this.$t('PRODUCT_CREATE_ERROR_WAS_DUPLICATE'),
        };

        const isDuplicated = errorMsg.includes('product is duplicated') || errorMsg.includes('duplicate with another product') || errorMsg.includes('The product is duplicated with another');

        if (isDuplicated) {
          this.log.text = this.$t('PRODUCT_CREATE_ERROR_WAS_DUPLICATE');
          this.log.color = colorStatus.error;
        } else if (Object.keys(mapErrorCode).includes(errorCode)) {
          this.log.text = this.$t(mapErrorCode[errorCode]);
          this.log.color = colorStatus.error;
        } else {
          this.log.text = errorMsg;
          this.log.color = colorStatus.error;
        }
      } catch (error) {
        loggerTiktok.error({
          msg: 'COPY_PRODUCT_ERROR',
          error,
        });

        this.log.text = error.user_message || error.message || this.$t('COPY_PRODUCT_ERROR');
        this.log.color = colorStatus.error;
      }

      this.btnDisable = false;
    },
  },
  async created() {
    this.productLoading = true;

    this.tiktokProduct = await getTiktokProductId(this.productId);

    this.editData = {
      ...this.editData,
      ...this.getShopeeClonePayload,
    };

    this.renderProduct();
    this.ShopeeSellerConfig();

    this.productLoading = false;

    setInterval(usageStore.fetchUsage, 1000);

    setTimeout(() => {
      if (!this.getUsageGptWriter.allow) {
        this.editData.title.gptWriter = false;
        this.editData.description.gptWriter = false;
      }
    }, 1000);

    UsageTiktok.syncRemote();
    MappingProductCategory.syncRemote();
  },
  watch: {
    editData: {
      deep: true,
      handler(data) {
        this.ShopeeSetClonePayload(data);
      },
    },
    getShopeeSellerWarehouse: {
      deep: true,
      handler(shopWarehouse) {
        if (!shopWarehouse.list.length) {
          return [];
        }

        this.shopWarehouse.options = shopWarehouse.list;

        if (!this.shopWarehouse.selected.length) {
          this.shopWarehouse.selected = shopWarehouse.selected;
          shopeeSetting.shopeeShopWarehouse.set(shopWarehouse.selected);
        }

        return this.shopWarehouse.selected;
      },
    },
  },
  computed: {
    ...mapGetters(['getShopeeClonePayload', 'getShopeeSellerLogistic', 'getShopeeSellerWarehouse']),
    warningCloneText() {
      return usageStore.getUsageTiktokCloneProduct.allow ? '' : usageStore.getUsageTiktokCloneProduct.errorMsg;
    },
    btnDisabled() {
      return this.btnDisable || !this.getShopeeSellerAuthed;
    },
    isShopWarehouse() {
      return this.shopWarehouse.options.length || this.shopWarehouse.selected.length;
    },
  },
});
