import NProgress from 'nprogress';
import moment from 'moment';
import groupArray from 'group-array';
import arrayDedupe from 'array-dedupe';
import { Input } from 'view-design';
import { mapActions, mapGetters } from 'vuex';
import { defineComponent } from '@vue/composition-api';
import { ShopeeFlashSaleSave } from '@/models/shopee/seller/flashsale';
import { apiFlashsaleSchedulerList, apiFlashsaleSchedulerRemove } from '@/api/autoshopee/shopee/flashsale';
import { getListFlashSale, removeFlashSaleId } from '@/api/shopee/seller/flashsale';
import { flashSaleSeller } from '@/adapter/shopee/render/index';
import { cloneObject } from '@/lib/utils/utils';
import { createFlashsaleFromSchedulerId } from '@/service/shopee/flashsale/scheduler';
import { loggerShopee } from '@/plugins/logger';
import lodash from 'lodash';
import { useSessionStorage } from '@vueuse/core';
import { STORAGE_KEYS } from '@/constant/storage';
import {
  mapStatusLabel, unixTime, labelTime, listStatus, flahsaleProductMax,
} from './Data';

export default defineComponent({
  data() {
    /** @type {FlashSaleCampagin[]} */
    const listSelected = [];

    /** @type {FlashSaleCampagin[]} */
    const listCampagin = [];

    /** @type {FlashSaleCampagin[]} */
    const listFsSave = useSessionStorage(STORAGE_KEYS.SESSION_STORAGE.SHOPEE_FLASHSALE_LIST_FS_SAVE, []) || [];

    /** @type {FlashSaleCampagin[]} */
    const listFsScheduler = useSessionStorage(STORAGE_KEYS.SESSION_STORAGE.SHOPEE_FLASHSALE_LIST_FS_SCHEDULER, []) || [];

    /** @type {FlashSaleCampagin[]} */
    const listFsNext = useSessionStorage(STORAGE_KEYS.SESSION_STORAGE.SHOPEE_FLASHSALE_LIST_FS_NEXT, []) || [];

    /** @type {FlashSaleCampagin[]} */
    const listFsCurrent = useSessionStorage(STORAGE_KEYS.SESSION_STORAGE.SHOPEE_FLASHSALE_LIST_FS_CURRENT, []) || [];

    /** @type {FlashSaleCampagin[]} */
    const listFsEnd = useSessionStorage(STORAGE_KEYS.SESSION_STORAGE.SHOPEE_FLASHSALE_LIST_FS_END, []) || [];

    /** @type {FlashSaleQueryStatus} */
    const tabActive = useSessionStorage(STORAGE_KEYS.SESSION_STORAGE.SHOPEE_FLASHSALE_TAB_ACTIVE, 'next');

    return {
      storeSubcribeAction: null,
      fetchInterval: null,
      popupReport: false,
      popupCampagin: false,
      enableAuto: false,
      shopId: '',
      shopRef: '',
      loading: false,
      tabActive,
      listCampagin,
      listSelected,
      listQuery: {
        listSave: listFsSave,
        listScheduler: listFsScheduler,
        listNext: listFsNext,
        listCurrent: listFsCurrent,
        listEnd: listFsEnd,
      },
      query: {
        loading: false,
        offset: 0,
        status: tabActive,
        limit: 100,
      },
      filter: {
        date: 'all',
      },
    };
  },
  methods: {

    ...mapActions(['SetShopeeFlashsaleList', 'SetShopeeFlashsaleSchedulerAuto', 'FetchShopeeFlashsaleList']),
    /**
     *
     * @param {FlashSaleCampagin} schedulerData
     */
    async createFlashSaleFromScheduler(schedulerData) {
      schedulerData.loading = true;
      const { flashSaleId: schedulerId, name: flashSaleName } = schedulerData;

      try {
        const flashSaleId = await createFlashsaleFromSchedulerId(schedulerId, true);

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

        schedulerData.urlOpen = flashSaleSeller(flashSaleId);
        this.$Message.success(flashSaleName);

        this.FetchShopeeFlashsaleList();
      } catch (error) {
        loggerShopee.error({
          msg: 'FLASHSALE_SCHEDULER_CREATE_ERROR',
          schedulerData,
          error,
        });

        this.$Message.error(error.errorMsg || this.$t('FLASHSALE_CREATE_SCHEDULER_ERROR'));
      }

      schedulerData.loading = false;

      await this.fetchSchedulerFlashsale();
      this.fetchCampgaignQuery('scheduler');
    },
    /**
     *
     * @param {FlashSaleCampagin} flashSaleData
     */
    async removeEntryFlashSale(flashSaleData) {
      const {
        flashSaleId, timeId, fromSave, fromScheduler, name: flashSaleName,
      } = flashSaleData;

      flashSaleData.loading = true;

      this.$Message.error(this.$t('FLASHSALE_REMOVE', { name: flashSaleName }));

      if (fromSave) {
        const flashsaleSave = this.listQuery.listSave.find((item) => item.flashSaleId === flashSaleId);
        await ShopeeFlashSaleSave.removeId(flashsaleSave._id);
        this.listQuery.listSave = this.listQuery.listSave.filter((item) => item.flashSaleId !== flashSaleId);
      } else if (fromScheduler) {
        this.listQuery.listScheduler = this.listQuery.listScheduler.filter((item) => item._id !== flashSaleId);
        await apiFlashsaleSchedulerRemove(flashSaleId);
      } else {
        await removeFlashSaleId(flashSaleId, timeId);
      }

      this.removeFlashSaleId(flashSaleId);
      flashSaleData.loading = false;
    },
    renderTabLabel(item) {
      return item.count ? `${item.label} [${item.count}]` : item.label;
    },
    onChangeTab() {
      const queryStatus = this.tabActive;

      this.query.status = queryStatus;

      return this.fetchCampgaignQuery(queryStatus);
    },
    selectAll(value) {
      if (value) {
        this.listSelected = this.listCampaginShow.map((item) => item.flashSaleId);
        return true;
      }

      this.listSelected = [];
    },
    removeFlashSaleId(flashSaleId) {
      this.listCampagin = this.listCampagin.filter((item) => item.flashSaleId !== flashSaleId);
    },
    getFlashSaleId(id) {
      return this.listCampagin.find((item) => item.flashSaleId === id);
    },
    onRemoveAll() {
      this.$Modal.confirm({
        title: this.$t('REMOVE_FLASHSALE_ALL_CONFIRM', { count: this.listSelected.length }),
        onOk: async () => {
          this.listSelected.forEach((id) => {
            this.removeEntryFlashSale(this.getFlashSaleId(id));
          });
        },
      });
    },
    onRemove(flashSale) {
      this.$Modal.confirm({
        content: flashSale.timeName,
        title: this.$t('REMOVE_FLASHSALE_CONFIRM'),
        onOk: async () => {
          flashSale.loading = true;
          await this.removeEntryFlashSale(flashSale);
          this.$Message.success(this.$t('REMOVE_SUCCESS'));
          flashSale.loading = false;
        },
      });
    },
    /**
     *
     * @param {FlashSaleCampagin} flashSale
     */
    onSave(flashSale) {
      const shopId = this.getShopeeShopId.toString();
      const shopName = this.getShopeeShopName;

      let saveName = '';

      this.$Modal.confirm({
        render: (h) => h(Input, {
          props: {
            autofocus: true,
            placeholder: this.$t('ENTER_FLASHSALE_NAME_SAVE'),
          },
          on: {
            input: (value) => {
              saveName = value;
            },
          },
        }),
        onOk: async () => {
          flashSale.fromSave = true;

          /** @type {FlashSaleCampagin} */
          const payloadCreate = {
            ...cloneObject(flashSale),
            shopId,
            shopName,
            flashSaleId: flashSale.flashSaleId.toString(),
            fromSave: true,
            name: saveName,
          };

          try {
            await ShopeeFlashSaleSave.insert(payloadCreate, payloadCreate.flashSaleId);

            this.$Message.success(this.$t('SAVE_SUCCESS'));

            this.pushNewFlashsaleSave(payloadCreate);
          } catch (error) {
            loggerShopee.error({
              msg: 'SAVE_FLASHSALE_ERROR',
              error,
            });
            this.$Message.error(this.$t('SAVE_ERROR'));
          }
        },
      });
    },
    /**
     *
     * @param {FlashSaleQueryStatus} queryStatus
     * @param {FlashSaleCampagin[]} listFlashsale
     */
    setListFlashsale(queryStatus, listFlashsale = []) {
      if (queryStatus === 'next') {
        this.listQuery.listNext = listFlashsale;
      }

      if (queryStatus === 'current') {
        this.listQuery.listCurrent = listFlashsale;
      }

      if (queryStatus === 'end') {
        this.listQuery.listEnd = listFlashsale;
      }

      if (queryStatus === 'save') {
        this.listQuery.listSave = listFlashsale;
      }

      if (queryStatus === 'scheduler') {
        this.listQuery.listScheduler = listFlashsale;
      }

      return true;
    },
    /**
     *
     * @param {FlashSaleQueryStatus} queryStatus
     * @returns {FlashSaleCampagin[]}
     */
    getListFlashsaleQuery(queryStatus) {
      if (queryStatus === 'next') {
        return this.listQuery.listNext;
      }

      if (queryStatus === 'current') {
        return this.listQuery.listCurrent;
      }

      if (queryStatus === 'end') {
        return this.listQuery.listEnd;
      }

      if (queryStatus === 'save') {
        return this.listQuery.listSave;
      }
      if (queryStatus === 'scheduler') {
        return this.listQuery.listScheduler;
      }
      return [];
    },
    /**
     *
     * @param {FlashSaleQueryStatus} queryStatus
     * @returns
     */
    async fetchCampgaignQuery(queryStatus = this.query.status) {
      if (false) {
        this.query.loading = true;
      }

      if (!queryStatus) {
        queryStatus = this.query.status || 'current';
      }

      NProgress.start();

      this.listSelected = [];
      this.listCampagin = [];

      let listFlashsaleReturn = [];

      const getListSave = () => {
        return this.getListFlashsaleQuery('save').map((item) => ({
          ...item,
          fromSave: true,
          fromScheduler: false,
        }));
      };

      const getListScheduler = () => {
        this.fetchSchedulerFlashsale().catch((error) => {
          loggerShopee.error({
            msg: 'FLASHSALE_FETCH_SCHEDULER_ERROR',
            error,
          });
        });

        /** @type {FlashSaleListScheduler[]} */
        const listFlashsale = this.getListFlashsaleQuery('scheduler');

        return listFlashsale
          .sort((a, b) => new Date(a.timeFlashsale) - new Date(b.timeFlashsale))
          .map((flashsaleScheduler, schedulerIndex) => {
            const { flashsaleId } = flashsaleScheduler;
            const isLateSchedule = !flashsaleId && moment(flashsaleScheduler.timeSchedule) < moment();
            const isLateTime = !flashsaleId && moment(flashsaleScheduler.timeFlashsale) < moment();

            let colorStyle = '';

            if (flashsaleId) {
              colorStyle = 'text-primary';
            } else if (isLateTime) {
              colorStyle = 'text-danger';
            } else if (isLateSchedule) {
              colorStyle = 'text-warning';
            }

            const flashsaleName = this.$t('FLASHSALE_NAME_TIME', {
              time: flashsaleScheduler.timeSlot.labelTime,
              index: schedulerIndex + 1,
              status: flashsaleScheduler.campaignName ? this.$t('FLASHSALE_SCHEDULER_CREATE_FROM_CAMPAIGN', { name: flashsaleScheduler.campaignName }).toLowerCase() : this.$t('FLASHSALE_SCHEDULER_SATUS'),
            });

            const flashsaleDescription = [
              this.$t('FLASHSALE_DESCRIPTION_TIME', {
                product: flashsaleScheduler.productCount,
                max: flahsaleProductMax,
                time: flashsaleScheduler.timeSet ? this.$d(new Date(flashsaleScheduler.timeSet), 'long') : '?',
              }),
              !flashsaleId ? this.$t('FLASHSALE_LABEL_SCHEDULER', {
                time: this.$d(new Date(flashsaleScheduler.timeSchedule), 'long'),
                hour: flashsaleScheduler.timeBefore,
                ago: moment(flashsaleScheduler.timeSchedule).fromNow(),
              }).toLowerCase() : '',
              !flashsaleId && flashsaleScheduler.error.message ? `(ERROR: ${flashsaleScheduler.error.message})` : '',
            ].filter((text) => text).join(', ');

            return {
              name: flashsaleName,
              description: flashsaleDescription,
              color: colorStyle,
              timeName: flashsaleScheduler.timeSlot.labelTime,
              flashSaleId: flashsaleScheduler._id,
              timeId: flashsaleScheduler.timeId,
              timeStart: null,
              timeEnd: null,
              timeCreate: null,
              timeUpdate: null,
              dateOnly: moment(flashsaleScheduler.timeFlashsale).format('YYYY/MM/DD'),
              productCount: flashsaleScheduler.productCount,
              productEnable: flashsaleScheduler.productCount,
              status: 'scheduler',
              urlOpen: flashsaleScheduler.flashsaleId ? flashSaleSeller(flashsaleScheduler.flashsaleId) : '',
              urlClone: '',
              fromSave: false,
              fromScheduler: true,
              loading: false,
            };
          });
      };

      const fetchListQuery = async ({ offset, status, limit }) => {
        try {
          /**
           * @type {ShopeeFSCampagin[]}
           */
          const listFetch = await getListFlashSale(offset, status, limit);

          const listFlashSaleQuery = listFetch
            .sort((flashSaleA, flashSaleB) => flashSaleA.start_time - flashSaleB.start_time)
            .map((item, index) => {
              const timeCreate = unixTime(item.ctime);
              const timeUpdate = unixTime(item.mtime);
              const timeStart = unixTime(item.start_time);
              const timeEnd = unixTime(item.end_time);
              const timeName = labelTime(timeStart, timeEnd);
              const getStatus = mapStatusLabel[item.type] || mapStatusLabel[3];

              let colorStyle = '';

              if (!item.item_count) {
                colorStyle = 'text-danger';
              } else if (item.item_count < flahsaleProductMax) {
                colorStyle = 'text-warning';
              }

              return {
                name: this.$t('FLASHSALE_NAME_TIME', {
                  time: timeName,
                  index: index + 1,
                  status: getStatus,
                }),
                description: this.$t('FLASHSALE_DESCRIPTION_TIME', {
                  product: item.item_count,
                  max: flahsaleProductMax,
                  time: this.$d(timeCreate, 'long'),
                }),
                color: colorStyle,
                timeName,
                flashSaleId: item.flash_sale_id,
                timeId: item.timeslot_id,
                timeStart,
                timeEnd,
                timeCreate,
                timeUpdate,
                dateOnly: moment(timeStart).format('YYYY/MM/DD'),
                productCount: item.item_count,
                productEnable: item.enabled_item_count,
                status: getStatus,
                urlOpen: flashSaleSeller(item.flash_sale_id),
                urlClone: this.$router.resolve(`/shopee/seller/flashsale/clone/${item.flash_sale_id}`).href,
                fromSave: this.getListFlashsaleQuery('save').some((fsale) => Number(item.flash_sale_id) === Number(fsale.flashSaleId)),
                fromScheduler: false,
                loading: false,
              };
            });

          this.setListFlashsale(queryStatus, listFlashSaleQuery);

          return listFlashSaleQuery;
        } catch (error) {
          loggerShopee.error({
            msg: 'FETCH_FLASHSALE_ERROR',
            error,
          });
          return [];
        }
      };

      try {
        if (queryStatus === 'save') {
          listFlashsaleReturn = getListSave();
        } else if (queryStatus === 'scheduler') {
          listFlashsaleReturn = getListScheduler();
        } else {
          this.listCampagin = this.getListFlashsaleQuery(queryStatus);

          const { limit, offset, status } = this.query;
          listFlashsaleReturn = await fetchListQuery({ limit, offset, status });
        }
      } catch (error) {
        loggerShopee.error({
          msg: 'FETCH_FLASHSALE_ERROR',
          query: queryStatus,
          error,
        });
      }

      this.SetShopeeFlashsaleList({
        listSet: listFlashsaleReturn,
        typeSet: queryStatus,
      });

      this.listCampagin = listFlashsaleReturn.map((flashsaleData) => ({
        ...flashsaleData,
        loading: false,
        color: flashsaleData.color || '',
      }));

      this.query.loading = false;

      NProgress.done();
      return this.listCampagin;
    },
    async fetchSaveFlashsale() {
      const shopId = this.getShopeeShopId.toString();
      const shopName = this.getShopeeShopName;

      const listAll = await ShopeeFlashSaleSave.findMany({});

      /** @type {FlashSaleCampagin[]} */
      const listSave = listAll
        .filter((flashsale) => flashsale.shopId && flashsale.flashSaleId && flashsale.shopId.toString() === shopId)
        .map((flashsale) => {
          flashsale.flashSaleId = flashsale.flashSaleId.toString();
          flashsale.shopId = flashsale.shopId.toString();

          if (!flashsale.shopName && flashsale.isOwned) {
            flashsale.shopName = shopName;
          }

          flashsale.fromSave = true;
          flashsale.fromScheduler = false;
          return flashsale;
        });

      this.listQuery.listSave = arrayDedupe(listSave, ['flashSaleId']);
    },
    async fetchSchedulerFlashsale() {
      this.listQuery.listScheduler = await apiFlashsaleSchedulerList(this.getShopeeShopId);
    },
    openFlashsaleReport() {
      this.popupReport = true;
      this.$refs.FlashsaleReport.reportFlashSale();
    },
    openFlashsaleCampaign() {
      if (!this.getIsPaidVip) {
        this.$router.push({
          name: 'UpgradePlan',
          query: {
            plan: 'Vip',
            feature: this.$t('FLASHSALE_CAMPAGIN_CREATE_BTN'),
          },
        });
        return;
      }

      this.popupCampagin = true;
      this.$refs.FlashsaleCampagin.initCampaign();
    },
    /**
     *
     * @param {FlashSaleCampagin} payloadFlashSale
     */
    pushNewFlashsaleSave(payloadFlashSale) {
      const shopId = this.getShopeeShopId.toString();
      const shopName = this.getShopeeShopName;

      this.listQuery.listSave.push({
        shopId,
        shopName,
        ...payloadFlashSale,
        fromSave: true,
      });
    },
  },
  async created() {
    this.enableAuto = this.getShopeeFlashsaleSchedulerJob.auto;

    ShopeeFlashSaleSave.syncRemote();

    const fetchFlashsaleAll = async () => {
      const queryStatus = this.query.status;

      this.fetchSaveFlashsale().catch((error) => {
        loggerShopee.error({
          msg: 'FLASHSALE_FETCH_SAVED_ERROR',
          error,
        });
      });

      this.fetchSchedulerFlashsale().catch((error) => {
        loggerShopee.error({
          msg: 'FLASHSALE_FETCH_SCHEDULER_ERROR',
          error,
        });
      });

      this.fetchCampgaignQuery(queryStatus).catch((error) => {
        loggerShopee.error({
          msg: 'FLASHSALE_FETCH_CAMPAGIN_ERROR',
          error,
        });
      });
    };

    fetchFlashsaleAll();

    const taskFlashsaleLastest = useSessionStorage(STORAGE_KEYS.SESSION_STORAGE.SHOPEE_FLASHSALE_TASK_LASTEST, 0);
    taskFlashsaleLastest.value = 0;

    this.storeSubcribeAction = this.$store.subscribeAction(async (action) => {
      if (action.type === 'FetchShopeeFlashsaleList') {
        fetchFlashsaleAll();
      }
    });

    this.fetchInterval = setInterval(() => {
      this.fetchSchedulerFlashsale().catch((error) => {
        loggerShopee.error({
          msg: 'FLASHSALE_FETCH_SCHEDULER_ERROR',
          error,
        });
      });
    }, 15000);
  },
  beforeDestroy() {
    if (this.storeSubcribeAction) {
      this.storeSubcribeAction();
    }

    if (this.fetchInterval) {
      clearInterval(this.fetchInterval);
    }
  },
  computed: {
    ...mapGetters(['getShopeeFlashsaleSchedulerJob']),
    isTabSave() {
      return this.query.status === 'save';
    },
    isTabScheduler() {
      return this.query.status === 'scheduler';
    },
    isTabQuery() {
      return ['scheduler', 'save'].includes(this.query.status);
    },
    listCampaginId() {
      return this.listCampagin.map((item) => item.flashSaleId);
    },
    listCampaginShow() {
      if (this.filter.date === 'all') {
        return this.listCampagin;
      }

      return this.listCampagin.filter((item) => !item.dateOnly || item.dateOnly === this.filter.date);
    },
    listDateFilter() {
      const listDateSelect = Object.entries(groupArray(this.listCampagin, ['dateOnly'])).map(([key, value]) => {
        return {
          value: key,
          label: `${key} (${this.$t('FLASHSALE_CREATE_COUNT', { count: value.length })})`,
        };
      });

      return [
        {
          value: 'all',
          label: this.$t('SELECT_ALL'),
        },
        ...listDateSelect,
      ];
    },
    listTab() {
      const listTab = lodash.cloneDeep(listStatus);

      listTab.find((item) => item.value === 'scheduler').count = this.getListFlashsaleQuery('scheduler').length;
      listTab.find((item) => item.value === 'save').count = this.getListFlashsaleQuery('save').length;
      listTab.find((item) => item.value === 'next').count = this.getListFlashsaleQuery('next').length;
      listTab.find((item) => item.value === 'current').count = this.getListFlashsaleQuery('current').length;

      return listTab;
    },
  },
});
