import { Dialog, QSelect, Notify, QNotifyCreateOptions } from 'quasar';
import GlobalDialog from 'components/GlobalDialog.vue';
import { ComposerTranslation, useI18n } from 'vue-i18n';
import { defineStore } from 'pinia';
import { Ref, ref } from 'vue';
import { getRole } from 'src/services/keycloak';

export const baseUrl = import.meta.env.VITE_API_BASE_URL;

export function dialog(opts: {
  title: string;
  message: string;
  color?: string;
  icon?: string;
  persistent?: boolean;
  actionText?: string;
  cancelText?: string;
  enablei18n?: boolean;
  action?: (...args: unknown[]) => unknown;
  cancel?: (...args: unknown[]) => unknown;
}) {
  Dialog.create({
    component: GlobalDialog,
    componentProps: opts,
  });
}

export function dialogWarningClose(
  t: ComposerTranslation,
  opts: {
    action?: (...args: unknown[]) => unknown;
    cancel?: (...args: unknown[]) => unknown;
  },
) {
  dialog({
    color: 'warning',
    icon: 'mdi-alert',
    title: t('warning'),
    actionText: t('ok'),
    message: t('warningClose'),
    action: async () => {
      if (opts.action) opts.action();
    },
    cancel: () => {
      if (opts.cancel) opts.cancel();
    },
  });
}

export function notify(
  type: 'create',
  message?: string,
  opts?: QNotifyCreateOptions | string,
) {
  if (type === 'create') {
    Notify.create({
      icon: 'mdi-check-circle',
      iconColor: 'white',
      iconSize: '42px',
      color: 'positive',
      message: message,
      position: 'bottom',
      timeout: 1000,
      group: false,
      actions: [
        {
          icon: 'mdi-close',
          color: 'white',
          round: true,
          handler: () => {},
        },
      ],
    });
  }
  if (opts) {
    Notify.create(opts);
  }
}

export function moveItemUp(items: unknown[], index: number) {
  if (index > 0) {
    const temp = items[index];
    items[index] = items[index - 1];
    items[index - 1] = temp;
  }
}

export function moveItemDown(items: unknown[], index: number) {
  if (index < items.length - 1) {
    const temp = items[index];
    items[index] = items[index + 1];
    items[index + 1] = temp;
  }
}

export function deleteItem(items: unknown[], index: number) {
  if (!items) return;
  if (index >= 0 && index < items.length) {
    items.splice(index, 1);
  }
}

export function formatNumberDecimal(num: number, point: number): string {
  return num.toLocaleString('eng', {
    minimumFractionDigits: point,
    maximumFractionDigits: point,
  });
}

export function selectFilterOptionRefMod(
  source: Ref<Record<string, unknown>[]>,
  destination: Ref<Record<string, unknown>[]>,
  filterField?: string,
) {
  destination.value = source.value;

  const filter = ((value, update) => {
    if (value === '') update(() => (destination.value = source.value));
    else
      update(
        () => {
          destination.value = source.value.filter((v) => {
            const label = v[filterField || 'label'];

            if (typeof label !== 'string') {
              throw new Error('Label must be of type string.');
            }

            return (
              label.toLocaleLowerCase().indexOf(value.toLocaleLowerCase()) > -1
            );
          });
        },
        (ref) => {
          if (value !== '' && destination.value.length > 0) {
            ref.setOptionIndex(-1);
            ref.moveOptionSelection(1, true);
          }
        },
      );
  }) satisfies QSelect['onFilter'];

  return filter;
}

export function selectOptionFilter(
  list: Record<string, unknown>[],
  filterField?: string,
  prepare?: (
    ...args: unknown[]
  ) => Record<string, unknown>[] | Promise<Record<string, unknown>[]>,
) {
  const options = ref<typeof list>([]);

  (async () => {
    const data = await prepare?.();
    if (data) options.value = list = data;
  })();

  const filter = ((value, update) => {
    if (value === '') update(() => (options.value = list));
    else
      update(() => {
        options.value = list.filter((v) => {
          const label = v[filterField || 'label'];

          if (typeof label !== 'string') {
            throw new Error('Label must be of type string.');
          }

          return (
            label.toLocaleLowerCase().indexOf(value.toLocaleLowerCase()) > -1
          );
        });
      });
  }) satisfies QSelect['onFilter'];

  return { options, filter };
}

export function checkTabBeforeAdd(data: unknown[], except?: string[]) {
  if (!data) return;
  const lastData = data[data.length - 1];

  if (typeof lastData !== 'object') return false;

  let canAdd = false;
  for (const [key, val] of Object.entries(
    lastData as Record<string, unknown>,
  )) {
    if (except?.includes(key)) continue;
    canAdd = val !== '' && val !== null;
    if (canAdd) break;
  }
  return canAdd;
}

const useUtilsStore = defineStore('utilsStore', () => {
  const currentTitle = ref<{
    title: string;
    path: {
      text: string;
      i18n?: boolean;
      argsi18n?: Record<string, string>;
      handler?: () => unknown;
    }[];
  }>({
    title: '',
    path: [
      {
        text: '',
        handler: () => {},
      },
    ],
  });

  return {
    currentTitle,
  };
});

export function isRoleInclude(role2check: string[]): boolean {
  const roles = getRole() ?? [];
  const isIncluded = role2check.some((r) => roles.includes(r));

  return isIncluded;
}

export default useUtilsStore;
