import PromiseMap from 'p-map';
import delay from 'delay';
import { imageUrl } from '@/adapter/shopee/render/index';
import { getShopeeProductListReview } from '@/api/shopee/client/product';
import { zipFileBase64, getBase64Url, saveAs } from '@/lib/utils/save';
import { v4 as uuid } from 'uuid';
import { loggerShopee } from '@/plugins/logger';

import { tableColumn, excelColumn, listFilter } from './Data';

import { defineComponent } from '@vue/composition-api';

export default defineComponent({
  data() {
    return {
      listFilter,
      productId: this.$route.query.productId,
      shopId: this.$route.query.shopId,
      listReview: [],
      exportExcel: {
        file: `shopee-review-(${this.$d(new Date())}).xls`,
        sheet: 'ShopeeReview',
        column: excelColumn,
        data: [],
      },
      filterSelect: ['media'],
      fetchReview: {
        loading: false,
        started: false,
        process: '',
      },
      downloader: {
        loading: false,
        current: 0,
        total: 0,
      },
      pagging: {
        current: 1,
        total: 100,
        limit: 50,
        size: [10, 20, 50, 100, 500, 1000],
      },
      tableColumn,
    };
  },
  methods: {
    /**
     *
     * @param {ShopeeReviewItem[]} listReview
     */
    renderReview(listReview = []) {
      this.listReview = listReview
        .map((item, index) => {
          try {
            const listImage = (item.image_data || []).map((image) => imageUrl(image.image_id));

            const listProduct = (item.product_items || []).map((product) => ({
              name: product.name,
              model: product.model_name,
              image: imageUrl(product.image),
            }));

            const listVideo = (item.videos || []).map((video) => {
              return {
                id: video.id,
                image: video.cover,
                url: video.url,
              };
            });

            return {
              index: index + 1,
              orderId: item.orderid,
              cmtId: item.cmtid,
              timeCreate: this.$d(new Date(item.ctime * 1000)),
              productId: item.itemid,
              shopId: item.shopid,
              userId: item.userid,
              authorId: item.author_shopid,
              authorName: item.author_username,
              authorImage: imageUrl(item.author_portrait),
              comment: item.comment,
              reply: item.ItemRatingReply ? item.ItemRatingReply.comment : '',
              star: item.rating_star,
              productName: listProduct[0].name,
              productModel: listProduct[0].model,
              productImage: listProduct[0].image,
              listImage,
              listVideo,
              listProduct,
              listTag: item.template_tags,
              isVideo: !!listVideo.length,
              isComment: !!listImage.length,
            };
          } catch (error) {
            loggerShopee.error({
              msg: 'RENDER_REVIEW_ERROR',
              error,
            });
            return null;
          }
        })
        .filter((review) => review);

      this.exportExcel.file = `Review-${this.productName}-(${this.$d(new Date())}).xls`;

      this.exportExcel.data = this.listReview.map((product) => {
        return {
          ...product,
          videoUrl: product.listVideo.map((video) => video.url).join('\n'),
          imageUrl: product.listImage.map((image) => image).join('\n'),
        };
      });

      this.pagging.current = 1;
      this.pagging.total = this.listReview.length;
    },
    async fetchReviewHandler() {
      this.fetchReview.loading = true;
      const listReview = [];
      const listFilterSelected = listFilter.filter((item) => this.filterSelect.includes(item.key));
      const limit = 20;
      const pageMax = 1000;

      await PromiseMap(
        listFilterSelected,
        async (filterSelected) => {
          await delay(500);
          let totalReview = 0;

          for (let page = 0; page < pageMax; page++) {
            this.fetchReview.process = this.$t('REVIEW_FETCH_PROCESS', {
              type: filterSelected.label,
              current: page * limit,
              total: totalReview,
            });

            try {
              const fetchReview = await getShopeeProductListReview(this.productId, this.shopId, limit, page, filterSelected.filter, filterSelected.type);

              if (!(fetchReview && fetchReview.ratings && fetchReview.ratings.length)) {
                break;
              }

              listReview.push(...fetchReview.ratings);
              totalReview = fetchReview.item_rating_summary.rating_total;
            } catch (error) {
              loggerShopee.error({
                msg: 'FETCH_REVIEW_ERROR',
                page,
                filterSelected,
                error,
              });
            }
          }
        },
        {
          concurrency: 1,
        },
      );

      this.renderReview(listReview);
      this.fetchReview.loading = false;
      this.fetchReview.started = true;
    },
    saveAsUrl(url, type) {
      return saveAs(url, `${uuid()}${type}`);
    },
    async downloadHandler() {
      const listReviewDownload = this.$refs.TableReview.getSelection();
      if (!(listReviewDownload && listReviewDownload.length)) {
        this.$Message.error(this.$t('REVIEW_DOWNLOAD_NO_SELECTED'));
        return false;
      }

      this.downloader.loading = true;

      const listDownloader = {
        fileName: `review-${this.productName}.zip`,
        input: [],
        data: [],
      };

      listReviewDownload.forEach((review, reviewIndex) => {
        listDownloader.input.push(
          ...review.listImage.map((image, imageIndex) => ({
            type: 'image',
            fileName: `image/${reviewIndex + 1}-${imageIndex + 1}-${review.cmtId}.jpg`,
            url: image,
          })),
        );

        listDownloader.input.push(
          ...review.listVideo.map((video, indexVideo) => ({
            type: 'video',
            fileName: `video/${reviewIndex + 1}-${indexVideo + 1}-${review.cmtId}.mp4`,
            fileImage: `thumbnail/${reviewIndex + 1}-${indexVideo + 1}-${review.cmtId}.jpg`,
            url: video.url,
            image: video.image,
          })),
        );
      });

      this.downloader.current = 0;
      this.downloader.total = listDownloader.input.length;

      await PromiseMap(
        listDownloader.input,
        async ({ url, fileName }) => {
          try {
            const base64 = await getBase64Url(url);

            listDownloader.data.push({
              fileName,
              base64,
            });
          } catch (error) {
            loggerShopee.error({
              msg: 'REVIEW_DOWNLOAD_IMAGE_ERROR',
              error,
              url,
              fileName,
            });
          }

          this.downloader.current++;
        },
        {
          concurrency: 4,
        },
      );

      await zipFileBase64(listDownloader.data, listDownloader.fileName);

      this.downloader.loading = false;
    },
    imageZip(url) {
      return `${url}_tn`;
    },
    onPaggingChange(page) {
      this.pagging.current = page;
    },
    onPaggingSize(limit) {
      this.pagging.limit = limit;
    },
  },
  computed: {
    productName() {
      return this.listReview && this.listReview[0] ? this.listReview[0].productName : '';
    },
    listReviewShow() {
      const { limit, current } = this.pagging;

      const start = current ? (current - 1) * limit : 0;
      const end = current ? current * limit : limit;

      return this.listReview.slice(start, end);
    },
    downloadProcess() {
      const text = [this.downloader.current, this.downloader.total].join('/');

      return this.downloader.loading ? `(${text})` : '';
    },
  },
});
