import type { Language } from 'element-plus/es/locale';

import type { App } from 'vue';

import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales';

import { ref } from 'vue';

import {
  $t,
  i18n,
  loadLocalesMapFromDir,
  setupI18n as coreSetup,
} from '@vben/locales';

import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import defaultLocale from 'element-plus/es/locale/lang/zh-cn';

const APP_LOCALE: SupportedLanguagesType = 'zh-CN';
const elementLocale = ref<Language>(defaultLocale);

const baseModules = import.meta.glob([
  './langs/zh-CN/about.json',
  './langs/zh-CN/authentication.json',
  './langs/zh-CN/common.json',
  './langs/zh-CN/menu-title.json',
  './langs/zh-CN/page.json',
  './langs/zh-CN/ui.json',
]);

const businessModules = import.meta.glob([
  './langs/zh-CN/ai-platform.json',
  './langs/zh-CN/announcement.json',
  './langs/zh-CN/dashboard-design.json',
  './langs/zh-CN/menu.json',
  './langs/zh-CN/message.json',
  './langs/zh-CN/permission.json',
  './langs/zh-CN/role.json',
  './langs/zh-CN/system-config.json',
  './langs/zh-CN/system.json',
  './langs/zh-CN/ui-config.json',
  './langs/zh-CN/user.json',
]);

const baseLocalesMap = loadLocalesMapFromDir(
  /\.\/langs\/([^/]+)\/(.*)\.json$/,
  baseModules,
);

const businessLocalesMap = loadLocalesMapFromDir(
  /\.\/langs\/([^/]+)\/(.*)\.json$/,
  businessModules,
);

const loadedBusinessLocales = new Set<SupportedLanguagesType>();

async function loadMessages(lang: SupportedLanguagesType) {
  const [appLocaleMessages] = await Promise.all([
    baseLocalesMap[lang]?.(),
    loadThirdPartyMessage(lang),
  ]);
  return appLocaleMessages?.default || {};
}

function getActualLocale(): SupportedLanguagesType {
  return APP_LOCALE;
}

async function loadBusinessMessages(lang = getActualLocale()) {
  if (loadedBusinessLocales.has(lang)) {
    return;
  }

  const businessLocaleMessages = await businessLocalesMap[lang]?.();
  if (businessLocaleMessages?.default) {
    i18n.global.mergeLocaleMessage(lang, businessLocaleMessages.default);
  }
  loadedBusinessLocales.add(lang);
}

async function loadThirdPartyMessage(lang: SupportedLanguagesType) {
  await Promise.all([loadElementLocale(lang), loadDayjsLocale(lang)]);
}

async function loadDayjsLocale(lang: SupportedLanguagesType) {
  if (lang === APP_LOCALE) {
    dayjs.locale('zh-cn');
  }
}

async function loadElementLocale(lang: SupportedLanguagesType) {
  if (lang === APP_LOCALE) {
    elementLocale.value = defaultLocale;
  }
}

async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
  await coreSetup(app, {
    defaultLocale: getActualLocale(),
    loadMessages,
    missingWarn: !import.meta.env.PROD,
    ...options,
  });
}

export { $t, elementLocale, loadBusinessMessages, setupI18n };
