import { orderBy } from 'lodash';
import moment from 'moment';
import { useQuasar } from 'quasar';
import { useForceUpdate } from 'src/composables/useForceUpdate';
import { useRequestConfirmation } from 'src/composables/useRequestConfirmation';
import { notifyError } from 'src/helpers';
import { capitalize } from 'src/helpers/formatters';
import { RolUsuario } from 'src/models';
import MiCuenta from 'src/widgets/components/MiCuenta.vue';
import { UAParser } from 'ua-parser-js';
import { computed } from 'vue';
import { useRouter } from 'vue-router';
import { useStore } from 'vuex';
import { useLayoutConfig } from './useLayoutConfig';

export function useAuth() {
  const store = useStore();
  const q = useQuasar();
  const router = useRouter();
  const { requestConfirmation } = useRequestConfirmation();
  const { menuConfig: menu } = useLayoutConfig();
  const userId = computed(() => store.getters['auth/userId']);
  const userData = computed(() => store.getters['auth/state_currentUser']);
  const tokenInvitacion = computed(() => userData.value?.token_invitacion);
  const token = computed(() => store.getters['auth/token']);
  const isLogged = computed(() => !!token.value);
  const delegacionesVisibles = computed(() => store.getters['delegaciones/delegaciones_visibles_para_mi']);
  const perfil = computed<number>(() => store.getters['auth/perfil']);
  const permisos = computed<number[]>(() => store.getters['auth/permisos']);
  const isAdmin = computed(() => permisos.value.includes(RolUsuario.ADMINISTRADOR));
  const isSuperadmin = computed(() => permisos.value.includes(RolUsuario.SUPERADMIN));
  const isJefeDeEquipo = computed(() => permisos.value.includes(RolUsuario.ORGANIZADOR));
  const isPromotor = computed(() => permisos.value.includes(RolUsuario.PROMOTOR));
  const isGerente = computed(() => permisos.value.includes(RolUsuario.GERENTE));
  const isProveedor = computed(() => permisos.value.includes(RolUsuario.PROVEEDOR));
  const isCliente = computed(() => permisos.value.includes(RolUsuario.CLIENTE));
  const isCandidato = computed(() => permisos.value.includes(RolUsuario.CANDIDATO));
  const idDelegacionActiva = computed<number>(() => store.getters['auth/idDelegacionActiva']);
  const delegaciones = computed(() =>
    orderBy(delegacionesVisibles.value, 'ID_DELEGACION').map(({ ID_DELEGACION: id, V_DEL_MVX: d }) => ({
      value: id,
      label: capitalize(`${d?.COD_DEL_MVX} - ${d?.DESCRIPCION_COR}`, true),
    }))
  );
  const gerencias = computed(() => userData.value?.gerencias?.map((g) => g.ID_GERENCIA) || []);
  const props = computed(() => store.getters['auth/props']);
  const rol = computed<string | null>(() => {
    if (isAdmin.value) return 'admin';
    if (isProveedor.value) return 'proveedor';
    if (isCliente.value) return 'cliente';
    if (isJefeDeEquipo.value) return 'jefeDeEquipo';
    if (isGerente.value) return 'gerente';
    if (isPromotor.value) return 'promotor';
    if (isCandidato.value) return 'candidato';
    return null;
  });
  const rolValue = computed<RolUsuario | null>(() => {
    if (isAdmin.value) return RolUsuario.ADMINISTRADOR;
    if (isProveedor.value) return RolUsuario.ORGANIZADOR;
    if (isCliente.value) return RolUsuario.CLIENTE;
    if (isJefeDeEquipo.value) return RolUsuario.ORGANIZADOR;
    if (isGerente.value) return RolUsuario.GERENTE;
    if (isPromotor.value) return RolUsuario.PROMOTOR;
    if (isCandidato.value) return RolUsuario.CANDIDATO;
    return null;
  });

  const { screen } = useQuasar();
  const { homeConfig } = useLayoutConfig();
  const routes = computed(() => homeConfig.value?.[rolValue.value || '']);
  const defaultHomeRoute = computed(() => (screen.lt.md ? routes.value?.mobile : routes.value?.desktop));
  const homeRoute = computed(() => userData.value.ruta_inicial || defaultHomeRoute.value);

  const saveGmkSession = async () => {
    const parser = new UAParser();
    const gmk_session = await store.dispatch('auth/infoUserlogin', {
      browser: parser.getBrowser(),
      device: parser.getDevice(),
      os: parser.getOS(),
      cpu: parser.getCPU(),
      startTime: moment().format('YYYY-MM-DD HH:mm:ss'),
    });
    q.sessionStorage.set('ID_GMK_SESSIONS', gmk_session);
  };

  const actualizarSistema = async () => {
    // se supone fuerza actualizar el componente Vue
    useForceUpdate();

    // borra las sessiones
    window.localStorage.removeItem('vuex');

    if (typeof caches !== 'undefined') {
      caches.keys().then((keys) => {
        keys.forEach((key) => {
          caches.delete(key);
        });
      });
    }
  };

  const login = async ({ username, password }) => {
    // capturar el tiempo que se hizo la llamada a la api /login
    const time_init = new Date().getTime();

    const response = await store.dispatch('auth/login', { username, password });

    // login fail
    if (response === false) {
      return false;
    }

    actualizarSistema();

    // guardar en store mensaje que se muestra al hacer login
    if (response.AVISO_LOGIN) {
      store.commit('auth/setLoginMessage', response.AVISO_LOGIN);
    }

    store.commit('auth/setShowLoginMessage', true);

    // calcular y guardar cuanto duró el proceso de login
    store.dispatch('auth/performance_data', {
      request_name: 'login_ok',
      request_end: new Date().getTime(),
      request_elapsed: new Date().getTime() - time_init,
    });

    // guardar algunos datos del proceso de login
    saveGmkSession();

    // cargar delegaciones del usuario
    await store.dispatch('delegaciones/tsDelegaciones_getByUser', { ID_USUARIO: userId.value });

    return response;
  };

  const signOut = () => {
    requestConfirmation({
      title: 'Desconectar usuario',
      message: '¿Seguro que deseas cerrar la sesión?',
      action: async () => {
        await store.dispatch('auth/infoUserlogin', {
          finishTime: moment().format('YYYY-MM-DD HH:mm:ss'),
          ID_SESSION: (q.sessionStorage.getItem('ID_GMK_SESSIONS') as any)?.ID_GMK_SESSIONS,
        });
        store.commit('auth/setLoginMessage', '');
        store.dispatch('tsc/tscStateDefaultAll');
        q.sessionStorage.remove('filtrosCaptacionTable');
        window.sessionStorage.removeItem('vuex');
        store.commit('auth/clearToken');
        router.push('/login');
      },
    });
  };

  const goToProfile = () => {
    const gamaId = userData.value.id_gama;
    if (!gamaId) {
      notifyError(null, 'Usuario no tiene gama definida...');
    } else {
      router.push(`/usuarios/${userData.value.id_usuario}?gamaId=${gamaId}`);
    }
  };

  const ca = (permisoId) => {
    const p = userData.value.permisos;
    if (p) {
      if (Array.isArray(permisoId)) {
        let toreturn = false;
        for (const item of p) {
          toreturn = permisoId.includes(item);
          if (toreturn) return toreturn;
        }
        return toreturn;
      } else {
        return p.includes(permisoId);
      }
    } else return false;
  };
  const { dialog } = useQuasar();
  const showUserData = () => {
    dialog({
      component: MiCuenta,
    });
  };

  return {
    showUserData,
    login,
    signOut,
    ca,
    menu,
    isCandidato,
    isPromotor,
    isAdmin,
    isSuperadmin,
    isJefeDeEquipo,
    isGerente,
    isProveedor,
    isCliente,
    userData,
    perfil,
    idDelegacionActiva,
    delegaciones,
    userId,
    rol,
    rolValue,
    permisos,
    goToProfile,
    isLogged,
    homeRoute,
    props,
    tokenInvitacion,
    gerencias,
  };
}
