import lodash from 'lodash';
import moment from 'moment';
import { Message } from 'view-design';
import { defineStore } from 'pinia';
import { useUserStore } from './user';
import { getDateOnly } from '@/lib/utils/moment';
import i18n from '@/vue/i18n';
import { UsageShopee, UsageTiktok } from '@/models/usage';
import { SHOPEE_USAGE_LIMITS, SHOPEE_USAGE_TYPE } from '@/constant/shopee';
import { TIKTOK_USAGE_LIMITS, TIKTOK_USAGE_TYPE } from '@/constant/tiktok';
import { USER_PLAN_FREE, USER_PLAN_VIP, USER_PLAN_PLUS } from '@/constant/user';

/**
 *
 * @param {UsageLimitStore} usageData
 * @param {number} today
 */
const resetDailyUsage = (usageData, today) => {
  usageData.dailyTime = today;
  usageData.dailyUsed = 0;
  usageData.lastestTime = 0;
  usageData.nextTime = 0;
};

/**
 *
 * @param {UsageLimitStore} usageData
 * @param {number} dailyLimit
 * @param {number} waitFor
 */
const fetchUsageState = (usageData, dailyLimit, waitFor) => {
  usageData.dailyLimit = dailyLimit;
  usageData.waitFor = waitFor;

  if (!usageData.waitFor) {
    usageData.nextTime = 0;
  }

  usageData.errorMsg = '';
  usageData.useMsg = '';

  const payloadLog = {
    name: usageData.name,
    current: usageData.dailyUsed,
    limit: usageData.dailyLimit,
    max: usageData.totalMax,
    total: usageData.totalUsed,
    second: usageData.waitFor,
  };

  if (usageData.dailyLimit - usageData.dailyUsed < 100) {
    usageData.useMsg = i18n.t('LIMIT_USAGE_ALLOW', payloadLog);
  }

  if (usageData.dailyUsed >= usageData.dailyLimit) {
    usageData.allow = false;
    usageData.errorMsg = i18n.t('LIMIT_USAGE_DAILY', payloadLog);
  } else if (usageData.totalUsed && usageData.totalMax && usageData.totalUsed >= usageData.totalMax) {
    usageData.allow = false;
    usageData.errorMsg = i18n.t('LIMIT_USAGE_TOTAL', {
      ...payloadLog,
      second: lodash.round((usageData.nextTime - Date.now()) / 1000, 0),
    });
  } else if (usageData.nextTime && usageData.nextTime > Date.now()) {
    usageData.allow = false;
    usageData.errorMsg = i18n.t('LIMIT_USAGE_WAIT', {
      ...payloadLog,
      second: lodash.round((usageData.nextTime - Date.now()) / 1000, 0),
    });
  } else {
    usageData.allow = true;
  }
};

const resolvePlanKey = (isPaid, plan) => {
  if (!isPaid) {
    return USER_PLAN_FREE;
  }

  if (plan === USER_PLAN_PLUS) {
    return USER_PLAN_PLUS;
  }

  if (plan === USER_PLAN_VIP) {
    return USER_PLAN_VIP;
  }

  return USER_PLAN_VIP;
};

const selectUsageConfig = (configMap, planKey) => {
  if (configMap[planKey]) {
    return configMap[planKey];
  }

  return configMap[USER_PLAN_FREE];
};

const ensureDailyUsage = (usageData, today) => {
  if (usageData.dailyTime !== today) {
    resetDailyUsage(usageData, today);
  }
};

const applyTotalMax = (usageData, totalMax) => {
  if (typeof totalMax === 'number') {
    usageData.totalMax = totalMax;

    return;
  }

  usageData.totalMax = 0;
};

const updateUsageCounters = async (usageData, model, usageType, periodStart) => {
  const dayStart = moment().startOf('day');

  usageData.dailyUsed = await model.count({
    type: usageType,
    createdAt: {
      $gt: dayStart.toISOString(),
    },
  });

  usageData.totalUsed = await model.count({
    type: usageType,
    createdAt: {
      $gt: periodStart.toISOString(),
    },
  });
};

const notifyUsageMessage = (usageData) => {
  if (!usageData.useMsg) {
    return;
  }

  Message.info({
    content: usageData.useMsg,
    top: 450,
    duration: 2,
  });
};

export const useUsageStore = defineStore('usage', {
  state() {
    return {
      /** @type {UsageLimitStore} */
      tiktokCloneProduct: {
        name: i18n.t('PRODUCT_CLONE'),
        allow: true,
        dailyTime: '',
        dailyLimit: 0,
        dailyUsed: 0,
        totalUsed: 0,
        totalMax: 0,
        lastestTime: 0,
        nextTime: 0,
        waitFor: 0,
        errorMsg: '',
        useMsg: '',
      },
      /** @type {UsageLimitStore} */
      shopeeCloneProduct: {
        name: i18n.t('PRODUCT_CLONE'),
        allow: true,
        dailyTime: '',
        dailyLimit: 0,
        dailyUsed: 0,
        totalUsed: 0,
        totalMax: 0,
        lastestTime: 0,
        nextTime: 0,
        waitFor: 0,
        errorMsg: '',
        useMsg: '',
      },
      /** @type {UsageLimitStore} */
      shopeeDownloadImage: {
        name: i18n.t('PRODUCT_DOWNLOAD_IMAGE'),
        allow: true,
        dailyTime: '',
        dailyLimit: 0,
        dailyUsed: 0,
        totalUsed: 0,
        totalMax: 0,
        lastestTime: 0,
        nextTime: 0,
        waitFor: 0,
        errorMsg: '',
        useMsg: '',
      },
      /** @type {UsageLimitStore} */
      shopeeDownloadVideo: {
        name: i18n.t('PRODUCT_DOWNLOAD_VIDEO'),
        allow: true,
        dailyTime: '',
        dailyLimit: 0,
        dailyUsed: 0,
        totalUsed: 0,
        totalMax: 0,
        lastestTime: 0,
        nextTime: 0,
        waitFor: 0,
        errorMsg: '',
        useMsg: '',
      },
    };
  },
  getters: {
    getUsageTiktokCloneProduct() {
      return this.tiktokCloneProduct;
    },
    getUsageShopeeCloneProduct() {
      return this.shopeeCloneProduct;
    },
    getUsageShopeeDownloadImage() {
      return this.shopeeDownloadImage;
    },
    getUsageShopeeDownloadVideo() {
      return this.shopeeDownloadVideo;
    },
  },
  actions: {
    resetUsage() {
      const { getUserIsPaid } = useUserStore();

      if (getUserIsPaid) {
        this.tiktokCloneProduct.waitFor = 0;
        this.shopeeCloneProduct.waitFor = 0;
        this.shopeeDownloadImage.waitFor = 0;
        this.shopeeDownloadVideo.waitFor = 0;
      }
    },
    incrementUsage(usageData) {
      usageData.dailyUsed++;
      usageData.totalUsed++;
      usageData.lastestTime = Date.now();
      usageData.nextTime = Date.now() + usageData.waitFor * 1000;
      this.fetchUsage();
    },

    incTiktokCloneProduct() {
      this.incrementUsage(this.tiktokCloneProduct);
      notifyUsageMessage(this.tiktokCloneProduct);
    },

    incShopeeCloneProduct() {
      this.incrementUsage(this.shopeeCloneProduct);
      notifyUsageMessage(this.shopeeCloneProduct);
    },

    incShopeeDownloadImage() {
      this.incrementUsage(this.shopeeDownloadImage);
      notifyUsageMessage(this.shopeeDownloadImage);
    },

    incShopeeDownloadVideo() {
      this.incrementUsage(this.shopeeDownloadVideo);
      notifyUsageMessage(this.shopeeDownloadVideo);
    },

    async fetchUsage() {
      const periodStart = moment().startOf('month');
      const today = getDateOnly(Date.now());
      const { getUserIsPaid, getUserPlan } = useUserStore();
      const planKey = resolvePlanKey(getUserIsPaid, getUserPlan);

      const shopeeDownloadImageConfig = selectUsageConfig(SHOPEE_USAGE_LIMITS.downloadImage, planKey);
      ensureDailyUsage(this.shopeeDownloadImage, today);
      fetchUsageState(this.shopeeDownloadImage, shopeeDownloadImageConfig.dailyLimit, shopeeDownloadImageConfig.waitFor);

      const shopeeDownloadVideoConfig = selectUsageConfig(SHOPEE_USAGE_LIMITS.downloadVideo, planKey);
      ensureDailyUsage(this.shopeeDownloadVideo, today);
      fetchUsageState(this.shopeeDownloadVideo, shopeeDownloadVideoConfig.dailyLimit, shopeeDownloadVideoConfig.waitFor);

      const shopeeCloneConfig = selectUsageConfig(SHOPEE_USAGE_LIMITS.productClone, planKey);
      ensureDailyUsage(this.shopeeCloneProduct, today);
      applyTotalMax(this.shopeeCloneProduct, shopeeCloneConfig.totalMax);
      await updateUsageCounters(this.shopeeCloneProduct, UsageShopee, SHOPEE_USAGE_TYPE.productClone, periodStart);
      fetchUsageState(this.shopeeCloneProduct, shopeeCloneConfig.dailyLimit, shopeeCloneConfig.waitFor);

      const tiktokCloneConfig = selectUsageConfig(TIKTOK_USAGE_LIMITS.productClone, planKey);
      ensureDailyUsage(this.tiktokCloneProduct, today);
      applyTotalMax(this.tiktokCloneProduct, tiktokCloneConfig.totalMax);
      await updateUsageCounters(this.tiktokCloneProduct, UsageTiktok, TIKTOK_USAGE_TYPE.productClone, periodStart);
      fetchUsageState(this.tiktokCloneProduct, tiktokCloneConfig.dailyLimit, tiktokCloneConfig.waitFor);

      return true;
    },
  },
  persist: {
    enabled: true,
    key: 'pinia-persist-usage',
  },
});
