import '@/types/Store/Shopee/Flashsale';
import groupArray from 'group-array';
import moment from 'moment';
import PromiseMap from 'p-map';
import lodash from 'lodash';
import arrayDedupe from 'array-dedupe';
import delay from 'delay';
import { shopeeSellerSearchProductList, getShopeeSellerProductId } from '@/api/shopee/seller/product/index';
import { getShopeeSellerFallbackInfo } from '@/api/shopee/seller';
import {
  imageUrl, fixPrice, productSeller, flashSaleSeller,
} from '@/adapter/shopee/render/index';
import {
  getListFlashSale,
  getTimeSlotFlashSale,
  getFlashSaleCampaignId,
  getFlashSaleId,
  createFlashSaleIdFromTime,
  updateFlashSaleSetListProduct,
  updateFlashSaleIndexListProduct,
} from '@/api/shopee/seller/flashsale';
import {
  flahsalePercentMin as defaultFlahsalePercentMin,
  tablePromotionColumn,
  tableProductColumn,
  listPriceReduceBy,
  listSetMethod,
  listSearchProductType,
  listPriceOrignalType,
  configPromotion,
  unixTime,
  roundNumber,
  labelTime,
  excelResultColumn,
} from './Data';
import { apiFlashsaleSchedulerSlot, apiFlashsaleSchedulerCreate } from '@/api/autoshopee/shopee/flashsale';
import { loggerShopee } from '@/plugins/logger';
import { defineComponent } from '@vue/composition-api';
import { useStorage, useSessionStorage } from '@vueuse/core';
import { STORAGE_KEYS } from '@/constant/storage';

/** @typedef {('priceOrginal' | 'priceDiscounted' | 'priceCampaign')} ShopeeFlashsalePriceOrginalBy */
/** @typedef {('default' | 'scheduler')} ShopeeFlashsaleSetMethod */

export default defineComponent({
  name: 'ShopeeFlashsale',
  data() {
    /** @type {ShopeeFlashsalePriceOrginalBy} */
    const priceOrginalBy = useStorage(STORAGE_KEYS.LOCAL_STORAGE.SHOPEE_FLASHSALE_PRICE_BASE_ORGINAL_BY, 'priceOrginal');

    /** @type {ShopeeFlashsaleSetMethod} */
    const setMethod = useStorage(STORAGE_KEYS.LOCAL_STORAGE.SHOPEE_FLASHSALE_SET_METHOD, 'default');

    /** @type {number} */
    const timeBeforeSchedulerSet = useStorage(STORAGE_KEYS.LOCAL_STORAGE.SHOPEE_FLASHSALE_BEFORE_HOUR_SET, 48);

    /** @type {number} */
    const delayCreateFlashSale = useStorage(STORAGE_KEYS.LOCAL_STORAGE.SHOPEE_FLASHSALE_DELAY_TIME, 5);

    /** @type {{number: number, text: string}} */
    const flahsalePercentMin = useStorage(STORAGE_KEYS.LOCAL_STORAGE.SHOPEE_FLASHSALE_PERCENT_MIN, defaultFlahsalePercentMin);

    /** @type {FlashSaleScheduler[]} */
    const listFsSchedulerSlot = useSessionStorage(STORAGE_KEYS.SESSION_STORAGE.SHOPEE_FLASHSALE_SCHEDULER_SLOT, []) || [];

    /** @type {TimeSlot[]} */
    const listTimeSlot = useSessionStorage(STORAGE_KEYS.SESSION_STORAGE.SHOPEE_FLASHSALE_TIME_SLOT, []) || [];

    const exportExcel = {
      file: `shopee-flashsale-(${this.$d(new Date())}).xls`,
      sheet: 'ShopeeFlashSale',
      column: excelResultColumn,
      data: [],
    };

    const errorLog = {
      table: [
        {
          title: this.$t('FLASHSALE_TALE_ERROR_PRODUCT'),
          key: 'product',
          render: (h, params) => {
            return h('a', {
              attrs: {
                href: params.row.productUrl,
                target: '_blank',
              },
            }, params.row.product);
          },
        },
        {
          title: this.$t('FLASHSALE_TALE_ERROR_MESSAGE'),
          key: 'log',
          render: (h, params) => {
            return h('span', {
            }, params.row.log);
          },
        },
      ],
      data: [],
      show: false,
    };
    return {
      shopWarningConnectShop: false,
      flashSaleData: {
        id: 0,
        title: '',
      },
      exportExcel,
      errorLog,
      step: {
        loading: false,
        current: 0,
      },
      loading: false,
      btnLoading: false,
      shopData: {
        id: 0,
        name: '',
        image: '',
      },
      excuteProcess: {
        isStarted: false,
        loading: false,
        current: 0,
        total: 0,
        log: [],
      },
      selected: {
        listTimeId: [],
        priceOrginalBy,
        setMethod,
      },
      formPromotion: {
        isLoading: false,
        pricePercent: 50,
        stockLimit: -1,
        purchaseLimit: 0,
        status: true,
      },
      options: {
        listTimeSlot,
        listPriceOrignalType,
        listSearchProductType,
        listPriceReduceBy,
        listSetMethod,
      },
      listFsScheduler: listFsSchedulerSlot,
      searchProduct: {
        finalPage: false,
        loading: false,
        cursor: '',
        total: 0,
        by: 'name',
        keyword: '',
        limit: 40,
        page: 1,
        product: 0,
      },
      tableProduct: {
        loading: false,
        column: tableProductColumn,
        data: [],
        pagging: {
          limit: 100,
          current: 1,
          total: 0,
        },
      },
      tablePromotion: {
        loading: false,
        column: tablePromotionColumn,
        /** @type {FlashSaleProduct[]} */
        data: [],
        pagging: {
          limit: 100,
          current: 1,
          total: 0,
        },
      },
      isValidNext: true,
      schedulerConfig: {
        timeBefore: timeBeforeSchedulerSet,
      },
      flahsalePercentMin,
      delayCreateFlashSale,
    };
  },
  methods: {
    /**
      @param {FlashSaleProduct} product
      @returns {number}
     */
    renderPercent(product) {
      if (!product.pricePromotion) {
        return 0;
      }

      return roundNumber((1 - product.pricePromotion / product.priceBase) * 100);
    },
    /**
     *
     * @param {FlashSaleProduct} row
     * @returns {stỉng}
     */
    rowClassPromotion(row) {
      if (row.stockLimit > row.stockMax) {
        return 'flashsale-danger-row';
      }

      if (row.stockLimit && row.stockLimit < row.stockMax) {
        return 'flashsale-success-row';
      }

      return '';
    },
    async nextStep() {
      if (this.stepCurrent === this.stepTotal - 1) {
        return false;
      }

      this.step.loading = true;
      try {
        if (this.stepKey === 'step-select-time' && !this.countTimeSelected) {
          this.step.loading = false;
          this.$Message.error(this.$t('FLASHSALE_ERROR.EMPTY_SELECT_TIME'));
          return false;
        }

        if (this.isCloneFlashSale) {
          if (this.stepKey === 'step-select-time') {
            await this.reUpdatePromotion();
          }
        }

        if (this.isCreateFlashSale) {
          if (this.stepKey === 'step-select-product' && !this.countProduct) {
            this.step.loading = false;
            this.$Message.error(this.$t('FLASHSALE_ERROR.EMPTY_SELECT_PRODUCT'));
            return false;
          }

          if (this.stepKey === 'step-change-promotion' && !this.countPromotion) {
            this.step.loading = false;
            this.$Message.error(this.$t('FLASHSALE_ERROR.EMPTY_SELECT_PROMOTION'));
            return false;
          }
        }
      } catch (error) {
        this.step.loading = false;
        this.$Message.error(this.$t('FLASHSALE_ERROR.UNKNOWN_ERROR'));
      }

      setTimeout(() => {
        this.step.current++;
        this.step.loading = false;
      }, 500);
    },
    prevStep() {
      if (this.stepCurrent === 0) {
        return false;
      }

      this.step.loading = true;

      setTimeout(() => {
        this.step.current--;
        this.step.loading = false;
      }, 500);
    },
    timeSlotCheck(isCheckAll = true) {
      if (isCheckAll) {
        this.selected.listTimeId = this.options.listTimeSlot.filter((item) => !item.disabled).map((item) => item.value);
      } else {
        this.selected.listTimeId = [];
      }
    },
    timeSlotDate(date) {
      const listMatchDate = this.options.listTimeSlot.filter((item) => item.date === date && !item.disabled);

      listMatchDate.forEach((item) => {
        const timeIdSelect = item.value;

        const isCheck = this.selected.listTimeId.some((timeId) => timeIdSelect === timeId);

        if (!isCheck) {
          this.selected.listTimeId.push(timeIdSelect);
        } else if (false) {
          this.selected.listTimeId = this.selected.listTimeId.filter((timeId) => timeIdSelect !== timeId);
        }
      });
    },
    onPromotionMass() {
      this.formPromotion.isLoading = true;
      this.tablePromotion.loading = true;

      let percentNumber = 0;
      if (this.formPromotion.stockLimit) {
        this.formPromotion.stockLimit = Number(this.formPromotion.stockLimit);
      }

      if (this.formPromotion.stockLimit) {
        this.formPromotion.purchaseLimit = Number(this.formPromotion.purchaseLimit);
      }

      if (this.formPromotion.pricePercent) {
        this.formPromotion.pricePercent = Number(this.formPromotion.pricePercent);
        percentNumber = 1 - this.formPromotion.pricePercent / 100;
      }

      this.tablePromotion.data.forEach((/** @type {FlashSaleProduct} */ item) => {
        item.status = this.formPromotion.status;

        if (this.formPromotion.stockLimit) {
          if (this.formPromotion.stockLimit < 0) {
            item.stockLimit = item.stockMax;
          } else {
            item.stockLimit = this.formPromotion.stockLimit;
          }
        }

        if (this.formPromotion.stockLimit) {
          item.purchaseLimit = this.formPromotion.purchaseLimit;
        }

        if (this.formPromotion.pricePercent && percentNumber) {
          item.pricePromotion = roundNumber(item.priceBase * percentNumber);
        }

        this.onChangeRow(item);
      });

      this.formPromotion.isLoading = false;
      this.tablePromotion.loading = false;

      return this.formPromotion;
    },
    onChangeFlahsalePercentMin(value) {
      if (value === null || value === undefined) {
        return;
      }

      const numberValue = Number(value) / 100;
      this.flahsalePercentMin = {
        number: numberValue,
        text: `${value}%`,
      };
    },
    onChangePricePercent() {
      if (Number(this.formPromotion.pricePercent) < this.flahsalePercentMin.number * 100) {
        this.$Message.error(this.$t('SHOPEE_FLASHSALE_PROMOTION_PERCENT_MIN', { percent: this.flahsalePercentMin.text }));
        this.formPromotion.pricePercent = this.flahsalePercentMin.number * 100;
      }
    },
    /**
      @param {FlashSaleProduct} product
     */
    onChangeRow(product) {
      const productUpdated = this.onChangeItem(product);

      /** @type {FlashSaleProduct} */
      const productMatch = this.tablePromotion.data.find((item) => item.itemId === product.itemId && item.modelId === product.modelId);

      productMatch.status = productUpdated.status;
      productMatch.stockLimit = productUpdated.stockLimit;
      productMatch.purchaseLimit = productUpdated.purchaseLimit;

      productMatch.pricePromotion = productUpdated.pricePromotion;

      this.onChangeItem(productMatch);
      return true;
    },
    /**
      @param {FlashSaleProduct} productFlashsale
     * @param {boolean} foreChange
     * @returns {FlashSaleProduct}
     */
    onChangeItem(productFlashsale, foreChange = false) {
      productFlashsale.pricePromotion = Number(productFlashsale.pricePromotion) || 0;
      productFlashsale.purchaseLimit = Number(productFlashsale.purchaseLimit) || 0;
      productFlashsale.stockLimit = Number(productFlashsale.stockLimit) || 0;

      if (foreChange) {
        if (productFlashsale.pricePromotion < productFlashsale.maxPromotion) {
          productFlashsale.pricePromotion = productFlashsale.maxPromotion;
        }

        if (productFlashsale.stockLimit > productFlashsale.stockMax) {
          productFlashsale.stockLimit = productFlashsale.stockMax;
        } else if (productFlashsale.stockLimit > productFlashsale.stock) {
          productFlashsale.stockLimit = productFlashsale.stock;
        }

        if (productFlashsale.purchaseLimit > productFlashsale.purchaseMax) {
          productFlashsale.purchaseLimit = productFlashsale.purchaseMax;
        }
      }

      if (productFlashsale.pricePromotion < configPromotion.getPriceMinPromotion(productFlashsale.pricePromotion)) {
        productFlashsale.pricePromotion = configPromotion.getPriceMinPromotion(productFlashsale.pricePromotion);
      }

      return productFlashsale;
    },
    removeProductPromotion(product) {
      product.added = false;
      this.tablePromotion.data = this.tablePromotion.data.filter((item) => item.itemId !== product.id);
    },
    checkProductWasAdded(itemId) {
      return this.tablePromotion.data.some((item) => item.itemId === itemId);
    },
    addProductPromotion(product) {
      if (this.checkProductWasAdded(product.id)) {
        return false;
      }

      if (this.countProduct >= configPromotion.limitProduct) {
        this.$Message.error(this.$t('FLASHSALE_LIMIT_PRODUCT', { product: configPromotion.limitProduct }));
        return false;
      }

      if (product.stockNumber <= this.countTimeSelected) {
        this.$Message.error(this.$t('PRODUCT_STATUS_BY.NOT_ENOUGH_STOCK'));
      }

      product.added = true;
      this.pushProductPromotion(product.payload);
    },
    /**
     *
     * @param {ShopeeSellerProductSearchItem} productData
     */
    async pushProductPromotion(productData) {
      const productId = productData.id;
      const productImage = imageUrl(productData.cover_image, true);

      const totalStart = this.tablePromotion.data.length;

      const getProductData = await getShopeeSellerProductId(productId);

      const listPromotionModel = lodash.get(productData, 'promotion.ongoing_campaigns', []);

      const listModel = getProductData.model_list;

      productData.model_list.forEach((modelData, index) => {
        try {
          const modelId = modelData.id || 0;
          const modelMatch = listModel.find((each) => each.id === modelId);
          const productModel = modelMatch || modelData;

          const modelImage = imageUrl(productData.cover_image, true);

          const priceOrginal = fixPrice(lodash.get(productModel, 'price_info.input_normal_price', 0));

          let priceDiscounted = fixPrice(lodash.get(productModel, 'price_info.input_promotion_price', 0));

          const matchPromotionModel = listPromotionModel.find((each) => each.model_id === modelId && each.campaign_type === 8);

          const priceCampaign = matchPromotionModel ? fixPrice(matchPromotionModel.input_price || matchPromotionModel.price) : 0;

          if (priceCampaign && this.selected.priceOrginalBy === 'priceCampaign') {
            priceDiscounted = priceCampaign;
          }

          const stockTotal = lodash.get(productModel, 'stock_detail.total_seller_stock', 0);
          const stockreserved = lodash.get(productModel, 'stock_detail.total_reserved_stock', 0);
          const stockCurrent = stockTotal - stockreserved;

          const stockMax = roundNumber(stockCurrent / this.stockSplit) - configPromotion.stockDuration;

          const purchaseMax = stockMax;

          if (stockMax < 1) {
            return false;
          }

          /** @type {FlashSaleProduct} */
          const payloadAdd = {
            ...configPromotion.defaultPromotion,
            isFirstModel: !index,
            index: totalStart + index + 1,
            itemId: productData.id,
            name: productData.name,
            sku: modelData.sku || productModel.sku,
            modelName: modelData.name || this.$t('PRODUCT_MODEL_DEFAULT'),
            modelId,
            image: modelImage || productImage,
            purchaseMax,
            priceBase: 0,
            maxPromotion: 0,
            minPromotion: 0,
            priceOrginal,
            priceCampaign,
            priceDiscounted,
            stock: stockCurrent,
            stockMax,
            stockTotal,
            stockreserved,
            stockCurrent,
            url: productSeller(productData.id),
          };

          payloadAdd.priceBase = payloadAdd[this.selected.priceOrginalBy] || payloadAdd.priceOrginal;

          payloadAdd.maxPromotion = roundNumber(payloadAdd.priceBase * configPromotion.percentMax);
          payloadAdd.minPromotion = roundNumber(payloadAdd.priceBase * configPromotion.percentMin);

          if (!(stockCurrent && stockCurrent > this.countTimeSelected + configPromotion.stockDuration)) {
            return false;
          }

          this.tablePromotion.data.push(payloadAdd);
        } catch (error) {
          loggerShopee.error({
            msg: 'ADD_PRODUCT_FLASHSALE_ERROR',
            model: modelData,
            error,
          });
        }
      });
    },
    async loadSearchProduct() {
      this.searchProduct.loading = true;

      while (true) {
        this.searchProduct.page++;
        await this.fetchListProduct(this.searchProduct.page);

        if (this.searchProduct.finalPage) {
          break;
        }
      }

      this.searchProduct.loading = false;
    },
    async handlerSearchProduct() {
      this.searchProduct.finalPage = false;
      this.searchProduct.loading = true;
      this.searchProduct.total = 0;
      this.searchProduct.product = 0;
      this.searchProduct.page = 1;
      this.searchProduct.cursor = '';
      this.tableProduct.data = [];
      await this.fetchListProduct(this.searchProduct.page).catch(() => {});
      this.searchProduct.loading = false;
    },
    async fetchListProduct(page = 1) {
      this.tableProduct.loading = true;

      try {
        const {
          listProduct, cursor, total, count,
        } = await shopeeSellerSearchProductList(this.searchProduct.keyword, page, this.searchProduct.limit, this.searchProduct.by, this.searchProduct.cursor);

        this.searchProduct.cursor = cursor;

        this.searchProduct.total = total;

        if (!count) {
          this.searchProduct.finalPage = true;
        } else if (!cursor && page) {
          this.searchProduct.finalPage = true;
        } else if (this.tableProduct.data >= this.searchProduct.total) {
          this.searchProduct.finalPage = true;
        } else {
          const totalSearch = this.searchProduct.page * this.searchProduct.limit;
          this.searchProduct.finalPage = !!(totalSearch > this.searchProduct.total);
        }

        const totalStart = this.tableProduct.data.length;

        listProduct.forEach((/** @type {ShopeeSellerProductSearchItem} */ product, index) => {
          const isExist = this.tableProduct.data.some((item) => item.id === product.id);

          if (isExist) {
            return false;
          }

          let active = true;
          let status = this.$t('PRODUCT_STATUS_BY.ACITVE');

          try {
            const firstModel = product.model_list[0];
            const productStock = lodash.get(firstModel, 'stock_detail.total_seller_stock', 0);
            const priceOrginal = fixPrice(lodash.get(firstModel, 'price_info.input_normal_price', 0));
            const priceDiscounted = fixPrice(lodash.get(firstModel, 'price_info.input_promotion_price', 0));

            if (false) {
              if (!productStock) {
                status = this.$t('PRODUCT_STATUS_BY.OUT_OF_STOCK');
                active = false;
              } else if (productStock <= this.countTimeSelected) {
                status = this.$t('PRODUCT_STATUS_BY.NOT_ENOUGH_STOCK');
                active = false;
              }
            }

            if (product.status === 4) {
              status = this.$t('PRODUCT_STATUS_BY.WAS_LOCK');
              active = false;
            } else if (product.status === 8) {
              status = this.$t('PRODUCT_STATUS_BY.WAS_HIDE');
              active = false;
            } else if (product.pre_order) {
              status = this.$t('PRODUCT_STATUS_BY.PRE_ORDER');
              active = false;
            }

            this.tableProduct.data.push({
              index: totalStart + index + 1,
              id: product.id,
              active,
              name: product.name,
              status,
              sku: product.parent_sku || '',
              timeCreate: this.$d(unixTime(product.create_time)),
              soldCount: this.$n(lodash.get(product, 'statistics.sold_count', 0)),
              viewCount: this.$n(lodash.get(product, 'statistics.view_count', 0)),
              likeCount: this.$n(lodash.get(product, 'statistics.liked_count', 0)),
              stock: this.$n(productStock),
              image: imageUrl(product.cover_image, true),
              modelCount: product.model_list.length,
              priceOrginal: this.$n(priceOrginal),
              pricePromotion: this.$n(priceDiscounted),
              stockNumber: productStock,
              added: this.checkProductWasAdded(product.id),
              url: productSeller(product.id),
              payload: product,
            });
          } catch (error) {
            loggerShopee.error({
              msg: 'LIST_PRODUCT_FLASHSALE_ERROR',
              error,
              product,
            });
          }
        });
      } catch (error) {
        loggerShopee.error({
          msg: 'LIST_PRODUCT_FLASHSALE_ERROR',
          error,
        });
      }

      this.searchProduct.product = this.tableProduct.data.length;
      this.tableProduct.loading = false;
    },
    async fetchSeller() {
      const sellerFallback = await getShopeeSellerFallbackInfo();
      this.shopData.id = sellerFallback.shopId;
      this.shopData.name = sellerFallback.username;
    },
    async fetchFlashSaleMeta() {
      const query = {
        offset: 0,
        status: 'next',
        limit: 100,
      };

      const listTimeNew = (await getTimeSlotFlashSale()).map((item) => {
        const startTime = unixTime(item.start_time);
        const endTime = unixTime(item.end_time);

        const timeLabel = labelTime(startTime, endTime);

        return {
          label: this.$t('FLASHSALE_TIME_LABEL_NEW', {
            time: timeLabel,
          }),
          labelTime: timeLabel,
          date: moment(startTime).format('YYYY/MM/DD').toString(),
          startTime,
          endTime,
          value: item.timeslot_id,
          timeId: item.timeslot_id,
          flashSaleId: 0,
          productCount: 0,
          isParent: false,
        };
      });

      const listTimeExist = (await getListFlashSale(query.offset, query.status, query.limit)).map((item) => {
        const startTime = unixTime(item.start_time);
        const endTime = unixTime(item.end_time);

        const timeLabel = labelTime(startTime, endTime);

        const productCount = item.item_count;

        const disabled = item.timeslot_id === this.flashSaleData.timeId || productCount >= configPromotion.limitProduct;

        return {
          label: this.$t('FLASHSALE_TIME_LABEL_EXIST', {
            time: timeLabel,
            product: productCount,
          }),
          labelTime: timeLabel,
          startTime,
          endTime,
          date: moment(startTime).format('YYYY/MM/DD').toString(),
          value: item.timeslot_id,
          timeId: item.timeslot_id,
          flashSaleId: item.flash_sale_id,
          productCount,
          disabled,
          isParent: false,
        };
      });

      this.options.listTimeSlot = [...listTimeNew, ...listTimeExist].sort((a, b) => a.startTime - b.startTime);
    },
    async fetchFlashSaleClone() {
      await getFlashSaleCampaignId(this.flashSaleId).catch(() => {
        this.isValidNext = false;
      });

      if (!this.isValidNext) {
        const errorMsg = this.$t('FLASHSALE_CLONE_NOT_VALID_AUTH');
        this.$Message.error(errorMsg);

        setInterval(() => {
          this.$Message.error(errorMsg);
        }, 2000);
        return false;
      }

      this.tablePromotion.loading = true;

      const flashSaleMeta = await getFlashSaleCampaignId(this.flashSaleId);
      const flashSaleData = await getFlashSaleId(this.flashSaleId);

      const startTime = unixTime(flashSaleMeta.start_time);
      const endTime = unixTime(flashSaleMeta.end_time);

      this.flashSaleData.timeId = flashSaleMeta.timeslot_id;
      this.flashSaleData.title = this.$t('FLASHSALE_CLONE_FROM_TITLE', {
        time: labelTime(startTime, endTime),
        product: flashSaleMeta.item_count,
      });

      /** @type {FlashSaleProduct[]} */
      let lastestProductId = 0;
      this.tablePromotion.data = flashSaleData.items
        .map((promotion, index) => {
          try {
            const productId = promotion.item_id;
            const modelId = promotion.model_id;
            const productData = flashSaleData.item_info.find((info) => info.itemid === productId);

            const modelData = flashSaleData.model_info[productId].find((each) => each.modelid === modelId);
            const modelSku = flashSaleData.price_stock_info.find((info) => info.item_id === productId).sku_stock_price_list.find((each) => each.model_id === modelId);

            const listImage = productData.images.split(',');
            const productImage = imageUrl(listImage[0], true);

            modelData.stock = lodash.get(modelSku, 'seller_stock_info.normal_stock', 0);
            modelData.price = lodash.get(modelSku, 'price_info.input_normal_price', 0);

            /** @type {FlashSaleProduct} */
            const payloadAdd = {
              ...configPromotion.defaultPromotion,
              isFirstModel: lastestProductId !== productId,
              index: index + 1,
              itemId: promotion.item_id,
              modelId: promotion.model_id,
              name: productData.name,
              modelName: modelData.name || this.$t('PRODUCT_MODEL_DEFAULT'),
              image: productImage,
              priceOrginal: modelData.price,
              priceDiscounted: modelData.price,
              stockMax: 0,
              purchaseMax: 0,
              maxPromotion: 0,
              minPromotion: 0,
              priceBase: 0,
              stock: modelData.stock,
              pricePromotion: promotion.input_promotion_price,
              stockLimit: promotion.stock,
              purchaseLimit: promotion.purchase_limit,
              status: !!promotion.status,
              url: productSeller(promotion.item_id),
            };

            payloadAdd.priceBase = payloadAdd[this.selected.priceOrginalBy] || payloadAdd.priceOrginal;
            payloadAdd.maxPromotion = roundNumber(payloadAdd.priceBase * configPromotion.percentMax);
            payloadAdd.minPromotion = roundNumber(payloadAdd.priceBase * configPromotion.percentMin);
            lastestProductId = productId;
            return payloadAdd;
          } catch (error) {
            loggerShopee.error({
              msg: 'CLONE_PROMOTION_ITEM_ERROR',
              error,
              promotion,
            });
            return null;
          }
        })
        .filter((item) => item);

      this.tablePromotion.loading = false;
    },
    async reUpdatePromotion() {
      this.tablePromotion.data = this.tablePromotion.data.map((/** @type {FlashSaleProduct} */ payloadAdd) => {
        try {
          payloadAdd.priceBase = payloadAdd[this.selected.priceOrginalBy] || payloadAdd.priceOrginal;

          payloadAdd.maxPromotion = roundNumber(payloadAdd.priceBase * configPromotion.percentMax);
          payloadAdd.minPromotion = roundNumber(payloadAdd.priceBase * configPromotion.percentMin);

          if (payloadAdd.stock && this.countTimeSelected && payloadAdd.stock > this.countTimeSelected) {
            payloadAdd.stockMax = roundNumber(payloadAdd.stock / this.stockSplit) - configPromotion.stockDuration;
            payloadAdd.purchaseMax = payloadAdd.stockMax;
          } else {
            payloadAdd.stockMax = payloadAdd.stock;
            payloadAdd.purchaseMax = payloadAdd.stockMax;
          }

          return payloadAdd;
        } catch (error) {
          loggerShopee.error({
            msg: 'RE_UPDATE_PROMOTION_ERROR',
            error,
            payloadAdd,
          });
          return null;
        }
      }).filter((item) => item);
    },
    async fetchInit() {
      this.fetchSeller().catch((error) => {
        loggerShopee.error({
          msg: 'FETCH_SELLER_ERROR',
          error,
        });
      });

      if (this.isCloneFlashSale) {
        await this.fetchFlashSaleClone().catch((error) => {
          loggerShopee.error({
            msg: 'FETCH_FLASH_SALE_CLONE_ERROR',
            error,
          });
        });
      } else {
        this.fetchListProduct();
      }

      this.fetchFlashSaleMeta();
    },
    /**
      @param {number} timeId
     */
    async createFlashSaleId(timeId) {
      const timeSlot = this.getTimeSlot(timeId);

      if (!timeSlot) {
        return null;
      }

      let flashSaleId = timeSlot.flashSaleId;

      /**
       * @type {FlashSaleProduct[]}
       */
      const listPromotion = this.listPromotionValid;
      const listProduct = arrayDedupe(this.listPromotionValid, ['itemId']);

      /**
          @type {ShopeeFsSetListItem[]}
       */
      const listSet = listPromotion
        .filter((item) => item.status)
        .map((product) => {
          return {
            item_id: product.itemId,
            status: product.status ? 1 : 0,
            model_id: product.modelId,
            input_promo_price: Number(product.pricePromotion),
            stock: Number(product.stockLimit),
            purchase_limit: Number(product.purchaseLimit),
          };
        });

      /**
          @type {ShopeeFsIndexListItem[]}
       */
      const listIndex = listProduct.map((product, index) => {
        return {
          item_id: product.itemId,
          display_sequence: index + 1,
        };
      });

      if (this.isSchedulerFlashSale) {
        const shopRef = this.getShopeeShopRef.toString();
        const shopId = this.getShopeeShopId.toString();
        const shopName = this.getShopeeShopName;

        const timeBefore = Number(this.schedulerConfig.timeBefore) || 1;

        /** @type {FlashSaleScheduler} */
        const payloadCreate = {
          timeSlot,
          productCount: listProduct.length,
          timeId,
          listSet,
          listIndex,
          shopId,
          shopName,
          timeBefore,
        };

        if (shopRef) {
          payloadCreate.shopRef = shopRef;
        }

        const createScheduler = await apiFlashsaleSchedulerCreate(payloadCreate);
        return createScheduler;
      }

      if (!flashSaleId) {
        const createFs = await createFlashSaleIdFromTime(timeId);

        flashSaleId = createFs.flash_sale_id;
      }

      if (!flashSaleId) {
        throw 'CREATE_FLASHSALEID_ERROR';
      }

      /** @type {ShopeeFsSetResult} */
      const resultSet = await updateFlashSaleSetListProduct(flashSaleId, listSet);

      await updateFlashSaleIndexListProduct(flashSaleId, listIndex).catch(() => {});

      const listFailed = arrayDedupe(resultSet.failed_items, ['item_id']);

      listPromotion.forEach((/** @type {FlashSaleProduct} */ flashsaleProduct) => {
        const matchError = resultSet.failed_items.find((item) => item.item_id === flashsaleProduct.itemId && item.model_id === flashsaleProduct.modelId);

        if (!matchError) {
          return null;
        }

        const excelRow = {
          id: flashSaleId,
          status: this.$t('ERROR_STATUS'),
          time: timeSlot.labelTime,
          product: flashsaleProduct.name,
          productId: flashsaleProduct.itemId,
          productUrl: flashsaleProduct.url,
          modelName: flashsaleProduct.modelName,
          stock: flashsaleProduct.stock,
          priceOrginal: flashsaleProduct.priceOrginal,
          pricePromotion: flashsaleProduct.pricePromotion,
          percentPromotion: `${this.renderPercent(flashsaleProduct)}%`,
          stockLimit: `${flashsaleProduct.stockLimit} (MAX=${flashsaleProduct.stockMax})`,
          purchaseLimit: `${flashsaleProduct.purchaseLimit} (MAX=${flashsaleProduct.purchaseMax})`,
          url: flashSaleSeller(flashSaleId),
          log: matchError.err_msg,
        };

        this.exportExcel.data.push(excelRow);
      });

      return {
        flashSaleId,
        totalProduct: listProduct.length,
        totalSuccess: listProduct.length - listFailed.length,
        totalError: listFailed.length,
      };
    },
    showErrorLog() {
      this.errorLog.show = true;
      this.errorLog.data = [];
      const groupFlashsaleId = groupArray(this.exportExcel.data, 'time');

      Object.entries(groupFlashsaleId).forEach(([, listLogFlashsale]) => {
        const groupFlashsaleProduct = groupArray(listLogFlashsale, 'productId', 'log');

        const listLogData = {
          fashsaleName: '',
          fashsaleId: '',
          fashsaleUrl: '',
          list: [],
          total: 10,
        };

        Object.entries(groupFlashsaleProduct).forEach(([, listLogProduct]) => {
          Object.entries(listLogProduct).forEach(([errorMessage, listLogError]) => {
            if (!listLogData.url) {
              listLogData.fashsaleId = listLogError[0].id;
              listLogData.fashsaleUrl = listLogError[0].url;
              listLogData.fashsaleName = listLogError[0].time;
            }

            let errorMsg = errorMessage;

            if (errorMessage.includes('IN_PLATFORM_FLASH_SALE')) {
              errorMsg = this.$t('FLASHSALE_ERROR_LOG.EXIST_IN_OTHER_FLASHSALE');
            } if (errorMessage.includes('355310007')) {
              errorMsg = this.$t('FLASHSALE_ERROR_LOG.LIMIT_FLASHSALE_PRODUCT');
            }

            listLogData.list.push({
              product: listLogError[0].product,
              productId: listLogError[0].productId,
              productUrl: listLogError[0].productUrl,
              url: '',
              log: errorMsg,
              count: listLogError.length,
            });
          });
        });

        this.errorLog.data.push(listLogData);
      });
    },
    getTimeSlot(timeId) {
      return this.options.listTimeSlot.find((item) => item.value === timeId);
    },
    async applyPromotion() {
      this.excuteProcess.isStarted = true;
      this.excuteProcess.loading = true;

      if (this.isCreateFlashSale) {
        this.tablePromotion.data.forEach((product) => {
          this.onChangeItem(product, true);
        });
      }

      this.excuteProcess.current = 0;
      this.excuteProcess.total = this.selected.listTimeId.length;

      await PromiseMap(
        this.selected.listTimeId,
        async (timeId) => {
          const timeSlot = this.getTimeSlot(timeId);

          this.excuteProcess.log.push(
            this.$t('FLASHSALE_RUN.START', {
              time: timeSlot.labelTime,
            }),
          );

          await this.createFlashSaleId(timeId)
            .then((flashsaleResult) => {
              if (this.isSchedulerFlashSale) {
                /** @type {FlashSaleScheduler} */
                const flahsaleScheduler = flashsaleResult;

                this.excuteProcess.log.push(this.$t('FLASHSALE_RUN.AUTO', {
                  id: flahsaleScheduler._id,
                  time: flahsaleScheduler.timeSlot.labelTime,
                }));
              } else {
                const flahsaleCreated = flashsaleResult;

                this.excuteProcess.log.push(
                  this.$t('FLASHSALE_RUN.RESULT', {
                    id: flahsaleCreated.flashSaleId,
                    total: flahsaleCreated.totalProduct,
                    success: flahsaleCreated.totalSuccess,
                    error: flahsaleCreated.totalError,
                    url: flashSaleSeller(flahsaleCreated.flashSaleId),
                  }),
                );
              }
            })
            .catch((error) => {
              this.excuteProcess.log.push(this.$t('FLASHSALE_RUN.ERROR'));
              loggerShopee.error({
                msg: 'CREATE_FLASHSALE_HANDLE_ERROR',
                timeSlot,
                error,
              });
            });

          this.excuteProcess.current++;

          if (!this.isSchedulerFlashSale && this.excuteProcess.current < this.excuteProcess.total) {
            const delaySeconds = Number(this.delayCreateFlashSale) || 10;
            this.excuteProcess.log.push(this.$t('FLASHSALE_RUN.WAIT', { seconds: delaySeconds }));
            await delay(delaySeconds * 1000);
          }
        },
        {
          concurrency: 1,
        },
      );

      this.excuteProcess.loading = false;
    },
    async fetchScheduler() {
      this.listFsScheduler = await apiFlashsaleSchedulerSlot(this.getShopeeShopId);
    },
  },
  created() {
    this.fetchInit().catch((error) => {
      loggerShopee.error({
        msg: 'FLASHSALE_FETCH_INIT_ERROR',
        error,
      });
    });

    this.fetchScheduler().catch((error) => {
      loggerShopee.error({
        msg: 'FLASHSALE_SHOP_INIT_ERROR',
        error,
      });
    });
  },
  computed: {
    flahsalePercentMinText() {
      return this.$t('SHOPEE_FLASHSALE_PROMOTION_PERCENT_MIN', { percent: this.flahsalePercentMin.text });
    },
    flahsalePercentMinNumber: {
      get() {
        return this.flahsalePercentMin.number * 100;
      },
      set(value) {
        const numberValue = Number(value) / 100;
        this.flahsalePercentMin = {
          number: numberValue,
          text: `${value}%`,
        };
      },
    },
    isCloneFlashSale() {
      return !!this.flashSaleId;
    },
    isCreateFlashSale() {
      return !this.flashSaleId;
    },
    isSchedulerFlashSale() {
      return this.selected.setMethod === 'scheduler';
    },
    countTimeTotal() {
      return this.options.listTimeSlot.length;
    },
    countTimeSelected() {
      return this.selected.listTimeId.length;
    },
    countPromotion() {
      return arrayDedupe(this.listPromotionValid, ['itemId']).length;
    },
    countProduct() {
      return arrayDedupe(this.tablePromotion.data, ['itemId']).length;
    },
    listPromotionValid() {
      return this.tablePromotion.data.filter((item) => Number(item.pricePromotion) && item.status && item.stockLimit);
    },
    stepList() {
      return [
        {
          label: this.$t('FLASHSALE_STEP.STEP_01.NAME'),
          key: 'step-tutorial',
          isShow: true,
        },
        {
          label: this.$t('FLASHSALE_STEP.STEP_02.NAME', { total: this.countTimeSelected }),
          key: 'step-select-time',
          isShow: true,
        },
        {
          label: this.$t('FLASHSALE_STEP.STEP_03.NAME', { total: this.countProduct }),
          key: 'step-select-product',
          isShow: this.isCreateFlashSale,
        },
        {
          label: this.$t('FLASHSALE_STEP.STEP_04.NAME', { total: this.countPromotion }),
          key: 'step-change-promotion',
          isShow: true,
        },
        {
          label: this.$t('FLASHSALE_STEP.STEP_05.NAME'),
          key: 'step-final',
          isShow: true,
        },
      ].filter((item) => item.isShow);
    },
    processLogger() {
      return this.excuteProcess.log.join('\n');
    },
    stepKey() {
      return this.stepList[this.stepCurrent].key;
    },
    stepTotal() {
      return this.stepList.length;
    },
    stepCurrent() {
      return this.step.current;
    },
    isNextStep() {
      return !!(this.stepCurrent < this.stepTotal - 1);
    },
    isPrevStep() {
      return !!(this.stepCurrent > 0);
    },
    isProcessDone() {
      return this.excuteProcess.isStarted;
    },
    stockSplit() {
      return this.isSchedulerFlashSale ? configPromotion.stockSplitDefault : this.countTimeSelected;
    },
    listSlotTime() {
      const listSlot = [];
      Object.entries(groupArray(this.options.listTimeSlot, 'date')).forEach(([date, listTime]) => {
        listSlot.push({
          text: date,
          value: date,
          disabled: false,
          isParent: true,
        });

        listTime.forEach((fsSlot) => {
          fsSlot.text = fsSlot.label;

          if (this.listFsScheduler && this.listFsScheduler.length) {
            const timeId = fsSlot.timeId.toString();

            const fsScheduler = this.listFsScheduler.find((flashsale) => !flashsale.isDone && flashsale.timeId.toString() === timeId);

            if (fsScheduler) {
              fsSlot.text = `${fsSlot.label} - ${this.$t('FLASHSALE_TIME_LABEL_SCHEDULER', { product: fsScheduler.productCount })}`;
            }
          }

          listSlot.push(fsSlot);
        });
      });

      return listSlot;
    },
  },
});
