import type { GetUserInfoModel, UserInfo } from '@vben/types';

import type { AuthApi } from '#/api';

import { h, ref } from 'vue';
import { useRouter } from 'vue-router';

import { useMessage } from '@jnpf/hooks';
import { encryptByMd5, formatToDateTime } from '@jnpf/utils';

import { LOGIN_PATH } from '@vben/constants';
import { preferences, updatePreferences } from '@vben/preferences';
import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';

import { notification } from 'ant-design-vue';
import { cloneDeep } from 'lodash-es';
import { defineStore } from 'pinia';

import { getUserInfoApi, loginApi, logoutApi, unlockApi } from '#/api';
import { getRoleSelector } from '#/api/permission/role';
import { getMySystem } from '#/api/system/homeData';
import { getPermissionSwitches } from '#/api/system/sysConfig';
import { $t, initLocale } from '#/locales';
import { APP_PREFIX, defaultPreferencesConfig } from '#/utils/constants';
import { getRealJnpfAppEnCode } from '#/utils/jnpf';
import { filterPermissionMenus, normalizePermissionSwitches } from '#/utils/permissionSwitch';

import { useBaseStore } from './base';

export const useAuthStore = defineStore('auth', () => {
  const accessStore = useAccessStore();
  const userStore = useUserStore();
  const baseStore = useBaseStore();
  const router = useRouter();

  const loginLoading = ref(false);

  /**
   * 异步处理登录操作
   * Asynchronously handle the login process
   * @param params 登录表单数据
   */
  async function authLogin(params: AuthApi.LoginParams) {
    const loginRequestParams: AuthApi.LoginParams = { ...params };
    // 异步处理用户登录操作并获取 accessToken
    let userInfo: null | UserInfo = null;
    try {
      loginLoading.value = true;
      const res = await loginApi(loginRequestParams);
      const { token: accessToken, saasList = [] } = res.data;
      if (saasList?.length > 1) return { saasList, accessToken };

      // 如果成功获取到 accessToken
      if (accessToken) {
        accessStore.setAccessToken(accessToken);

        userInfo = await fetchUserInfo();
        if (!userInfo) return;
        userStore.setUserInfo(userInfo);

        if (accessStore.loginExpired) {
          accessStore.setLoginExpired(false);
        }

        if (userInfo?.prevLogin === 1) {
          notification?.destroy();
          notification.open({
            message: $t('sys.login.lastLoginInfo'),
            description: () =>
              h('div', { class: 'pt-[10px]' }, [
                h('p', null, `时间： ${formatToDateTime(userInfo?.prevLoginTime)}`),
                h('p', null, `地点： ${userInfo?.prevLoginIPAddressName || ''}`),
                h('p', null, `IP： ${userInfo?.prevLoginIPAddress || ''}`),
              ]),
            placement: 'bottomRight',
            style: { width: '300px' },
          });
        }
      }
    } finally {
      loginLoading.value = false;
    }

    return userInfo;
  }

  async function redirectAfterLogin(redirect?: string) {
    if (redirect) {
      await router.replace(redirect);
      return;
    }

    const userInfo = userStore.getUserInfo || (await fetchUserInfo());
    if (userInfo?.isAdministrator) {
      await router.replace(preferences.app.defaultHomePath);
      return;
    }

    try {
      const { data: systems = [] } = await getMySystem();
      const system = systems.find((item) => item?.enCode);
      if (system?.enCode) {
        window.location.replace(`${window.location.origin}/${APP_PREFIX}${system.enCode}`);
        return;
      }
    } catch {
      // No accessible application: preserve the existing home-page fallback.
    }

    await router.replace(preferences.app.defaultHomePath);
  }

  async function logout(redirect: boolean = true) {
    try {
      if (accessStore.accessToken) {
        const res = await logoutApi();
        // 单点登录退出登录
        if (res?.data?.ssoLogoutApiUrl) {
          const iframe: any = document.createElement('IFRAME');
          iframe.setAttribute('style', 'position:absolute;width:0px;height:0px;left:-500px;top:-500px;');
          iframe.src = res?.data.ssoLogoutApiUrl;
          iframe.addEventListener('load', () => {
            iframe.remove();
          });
          document.body.append(iframe);
        }
      }
    } catch {
      // 不做任何处理
    }

    resetAllStores();
    accessStore.setLoginExpired(false);
    if (router.currentRoute.value.path === LOGIN_PATH) return;

    // 回登陆页带上当前路由地址
    await router.replace({
      path: LOGIN_PATH,
      query: redirect
        ? {
            redirect: encodeURIComponent(router.currentRoute.value.fullPath),
          }
        : {},
    });
  }

  async function fetchUserInfo() {
    const res = await getUserInfoApi();
    if (!res) return null;
    const { userInfo, sysConfigInfo, menuList = [], permissionList = [] } = res.data as GetUserInfoModel;
    await fillRoleEnCode(userInfo);
    initLocale(preferences.app.locale);
    handleUpdatePreferences(userInfo);

    let permissionSwitches = normalizePermissionSwitches(sysConfigInfo);
    try {
      const switchRes = await getPermissionSwitches();
      permissionSwitches = normalizePermissionSwitches(switchRes?.data || {}, permissionSwitches);
    } catch {
      // 兼容前后端滚动发布：接口不可用时保留身份配置，新增入口默认关闭。
    }
    baseStore.setSysConfig({ ...sysConfigInfo, ...permissionSwitches });
    userStore.setUserInfo(userInfo);
    accessStore.setBackMenus(filterPermissionMenus(menuList, permissionSwitches));
    accessStore.setPermissionList(permissionList);
    return userInfo;
  }

  async function fillRoleEnCode(userInfo) {
    const roleList = Array.isArray(userInfo?.roleList) ? userInfo.roleList : [];
    if (!roleList.length || roleList.every((o) => o.enCode)) return;
    try {
      const res = await getRoleSelector();
      const allRoleList = Array.isArray(res?.data?.list) ? res.data.list : Array.isArray(res?.data) ? res.data : [];
      const roleMap = new Map(allRoleList.map((o) => [o.id, o]));
      userInfo.roleList = roleList.map((role) => {
        const sourceRole: any = roleMap.get(role.id) || {};
        return { ...role, enCode: role.enCode || sourceRole.enCode || '' };
      });
    } catch {}
  }

  // 更新偏好配置
  function handleUpdatePreferences(userInfo) {
    const appEnCode = getRealJnpfAppEnCode();
    let preferenceJson: any = cloneDeep(defaultPreferencesConfig);
    try {
      if (userInfo.preferenceJson) preferenceJson = JSON.parse(userInfo.preferenceJson);
    } catch {
      preferenceJson = cloneDeep(defaultPreferencesConfig);
    }
    if (!appEnCode) preferenceJson.app.layout = 'mixed-nav';
    if (appEnCode && ['teamwork', 'workFlow'].includes(appEnCode)) preferenceJson.app.layout = 'sidebar-nav';
    updatePreferences(preferenceJson);
  }

  function confirmLoginOut() {
    const { createConfirm } = useMessage();
    createConfirm({
      iconType: 'warning',
      title: () => h('span', $t('sys.app.logoutTip')),
      content: () => h('span', $t('sys.app.logoutMessage')),
      onOk: async () => {
        await logout(false);
      },
    });
  }
  // 锁屏解锁
  async function unLock(password) {
    const userStore = useUserStore();
    try {
      const account = userStore.getUserInfo?.userAccount;
      const res = await unlockApi({
        account,
        password: encryptByMd5(password),
      });
      return res;
    } catch {
      return false;
    }
  }
  function goForbidden() {
    router.replace('/forbidden');
  }

  function $reset() {
    loginLoading.value = false;
  }

  return {
    $reset,
    authLogin,
    fetchUserInfo,
    loginLoading,
    logout,
    redirectAfterLogin,
    confirmLoginOut,
    unLock,
    goForbidden,
  };
});
