import { deserialize, EstadoCaptacion } from '@win2win/shared';
import { compact, snakeCase } from 'lodash';
import { useQuasar } from 'quasar';
import { api } from 'src/boot/axios';
import { useAuth } from 'src/composables/useAuth';
import { useCaptacionActions } from 'src/composables/useCaptacionActions';
import { useRefetch } from 'src/composables/useRefetch';
import { useRequestConfirmation } from 'src/composables/useRequestConfirmation';
import { notifyError, notifySuccess } from 'src/helpers';
import { Captacion, GlobalAction, LayoutContext, Producto, Usuario } from 'src/models';
import CaptacionDiscardRequest from 'src/pages/captaciones/CaptacionDiscardRequest.vue';
import CaptacionDocumentRequest from 'src/pages/captaciones/CaptacionDocumentRequest.vue';
import widgetIndex from 'src/widgets/index';
import MeetDialog from 'src/widgets/meets/MeetDialog.vue';
import { useLayout } from 'src/widgets/useLayout';
import { StoreLiteModule, useStoreLite } from 'src/widgets/useStoreLite';
import PerfilUsuarioDialog from 'src/widgets/usuario/PerfilUsuarioDialog.vue';
import { computed, ref } from 'vue';
import { useRouter } from 'vue-router';
import IncidenciaDialog from '../dialogs/IncidenciaDialog.vue';
import { ContextActionCode } from './consts';

export function useContextActions(context: LayoutContext) {
  const { requestConfirmation } = useRequestConfirmation();
  const { data, idGama } = useStoreLite<Producto | Captacion | Usuario>(context as StoreLiteModule);
  const estado = computed(() => Number(data.value?.['ESTADO']) ?? 0);
  const { globalActions: rawGlobalActions, layoutParams } = useLayout(context, 'detalle');
  const { dialog } = useQuasar();
  const loading = ref<string | null>(null);
  const { isAdmin, isCliente } = useAuth();
  const router = useRouter();

  const id = computed(
    () =>
      ({
        producto: data.value?.['ID_PRODUCTO'],
        captacion: data.value?.['ID_CAPTACION'],
        usuario: data.value?.['ID_USUARIO'],
      }[context] ?? null)
  );

  const refetch = useRefetch({ type: 'all' });

  // refactorizar para que sea generico esto
  const { showActionDialog } = useCaptacionActions();

  function getDialogComponent(component: string) {
    let name = snakeCase(component);
    if (name.startsWith('widget_')) {
      name = name.replace('widget_', '');
      return widgetIndex[name]?.component ?? null;
    }

    return {
      perfil_usuario_dialog: PerfilUsuarioDialog,
    }[name];
  }

  const changeState = (action: GlobalAction) => {
    const {
      params: { confirmationText, value, dynamic = false },
      code,
    } = action;
    const message = confirmationText || `¿Estás seguro que confirmas esta acción?`;
    const endpointRoot =
      {
        usuario: 'usuarios',
      }[context] || context;

    requestConfirmation({
      message,
      action: () => {
        const key = dynamic ? (value.length === 36 ? 'id_estado' : 'code') : 'estado';
        loading.value = code;
        api
          .put(`/${endpointRoot}/${id.value}/estado`, { [key]: value })
          .then(() => {
            notifySuccess('Información actualizada correctamente');
            if (refetch) {
              refetch();
            }
          })
          .catch((err) => {
            notifyError(err, 'Ha ocurrido un error al actualizar la información');
          })
          .finally(() => (loading.value = null));
      },
    });
  };

  const deleteItem = (action: GlobalAction) => {
    const {
      params: { confirmationText },
      code,
    } = action;
    const endpointRoot =
      {
        producto: 'productos',
      }[context] || context;
    const message = confirmationText || `¿Estás seguro que quieres eliminar este registro?`;
    requestConfirmation({
      message,
      action: () => {
        loading.value = code;
        api
          .delete(`/${endpointRoot}/${id.value}`)
          .then(() => {
            notifySuccess('Registro eliminado correctamente');
            router.push('/productos?gamaId=' + idGama.value);
            if (refetch) {
              refetch();
            }
          })
          .catch((err) => {
            notifyError(err, 'Ha ocurrido un error al eliminar el registro');
          })
          .finally(() => (loading.value = null));
      },
    });
  };

  const commonActionsParams = (action: GlobalAction) => ({
    [ContextActionCode.STATE_UPDATER]: {
      icon: action.icon || action.mobileIcon,
      visible: true,
      action: () => changeState(action),
    },
    [ContextActionCode.DELETE]: {
      icon: action.icon || action.mobileIcon,
      visible: true,
      action: () => deleteItem(action),
    },
  });

  function getActionParams(context: LayoutContext, action: GlobalAction) {
    const contextActions = {
      usuario: {
        [ContextActionCode.STATE_UPDATER]: {
          icon: action.icon || action.mobileIcon,
          visible: true,
          action: () => changeState(action),
        },
        [ContextActionCode.OPEN_DIALOG]: {
          icon: action.icon || action.mobileIcon || 'sym_o_plagiarism',
          visible: true,
          action: () => {
            dialog({
              component: getDialogComponent(action.params.component),
              componentProps: {
                ...action.params.props,
              },
            });
          },
        },
      },

      captacion: {
        // default customer actions
        [ContextActionCode.CONFIRM]: {
          icon: action.icon || action.mobileIcon,
          visible: isCliente.value && estado.value >= Number(EstadoCaptacion.NEGOCIACION_FINALIZADA),
          action: () => showActionDialog('confirmar'),
        },

        // default admin actions
        [ContextActionCode.PREAPPROVE]: {
          icon: action.icon || action.mobileIcon,
          visible: isAdmin.value && estado.value === Number(EstadoCaptacion.EN_ESTUDIO),
          action: () => showActionDialog('preaprobar', action.label),
        },
        [ContextActionCode.APPROVE]: {
          icon: action.icon || action.mobileIcon,
          visible: isAdmin.value && estado.value === Number(EstadoCaptacion.PRE_APROBADA),
          action: () => showActionDialog('aprobar', action.label),
        },
        [ContextActionCode.DISCARD]: {
          icon: action.icon || action.mobileIcon,
          visible: isAdmin.value && estado.value !== Number(EstadoCaptacion.CANCELADA) && estado.value !== Number(EstadoCaptacion.FINALIZADA),
          action: () =>
            dialog({
              component: CaptacionDiscardRequest,
              componentProps: {
                motivos: action.params?.motivos?.concat('Otro') || [],
              },
            }),
        },
        [ContextActionCode.NEW_MEET]: {
          icon: action.icon || action.mobileIcon,
          visible: isAdmin.value && ![Number(EstadoCaptacion.CANCELADA), Number(EstadoCaptacion.FINALIZADA)].includes(estado.value),
          action: () =>
            dialog({
              component: MeetDialog,
              componentProps: {
                now: false,
              },
            }),
        },
        [ContextActionCode.RESET]: {
          icon: action.icon || action.mobileIcon,
          visible: isAdmin.value && estado.value === Number(EstadoCaptacion.CANCELADA),
          action: () => showActionDialog('restablecer', action.label),
        },
        [ContextActionCode.REQUEST_DOCUMENTATION]: {
          icon: action.icon || action.mobileIcon,
          visible: isAdmin.value,
          action: () =>
            dialog({
              component: CaptacionDocumentRequest,
            }),
        },
        [ContextActionCode.GENERATE_INCIDENT]: {
          icon: action.icon || action.mobileIcon,
          visible: isAdmin && ![Number(EstadoCaptacion.CANCELADA), Number(EstadoCaptacion.FINALIZADA)].includes(estado.value),
          action: () => {
            dialog({
              component: IncidenciaDialog,
              componentProps: {
                context: { TIPO: 1, ID_CONTACTO: data.value?.['ID_CONTACTO'], ID_PRODUCTO: data.value?.['ID_PRODUCTO'], ID_CAPTACION: data.value?.['ID_CAPTACION'] },
                options: {
                  reasons: [
                    { label: 'Información incorrecta', value: 'Información incorrecta' },
                    { label: 'Información faltante', value: 'Información faltante' },
                  ],
                },
                notify: true,
              },
            });
          },
        },
        [ContextActionCode.COMPLETE]: {
          icon: action.icon || action.mobileIcon,
          visible: isAdmin.value,
          action: () => showActionDialog('finalizar', action.label),
        },
        [ContextActionCode.DELETE]: {
          icon: action.icon || action.mobileIcon,
          visible: isAdmin.value && estado.value == Number(EstadoCaptacion.CANCELADA),
          action: () => showActionDialog('eliminar', action.label),
        },
        [ContextActionCode.OPEN_DIALOG]: {
          icon: action.icon || action.mobileIcon || 'sym_o_plagiarism',
          visible: true,
          action: () => {
            // De momento esto esta hardcodeado, pero deberia ser dinamico. Funciona bien para el caso de uso actual.
            const htmlNode = document.getElementById('captacion_estado');
            dialog({
              component: getDialogComponent(action.params.component),
              componentProps: {
                ...action.params.props,
                htmlNodes: [
                  {
                    index: 3, // TODO: resolver como pasar este parametro dinamicamente
                    element: htmlNode,
                  },
                ],
                context: {
                  ...(action.params.props?.context || {}),
                  idCaptacion: data.value?.['ID_CAPTACION'],
                  idContacto: data.value?.['ID_CONTACTO'],
                  idPedido: data.value?.['ID_PEDIDO'],
                },
              },
            });
          },
        },
      },

      producto: {},
    }[context];

    const actions = { ...commonActionsParams(action), ...contextActions }[action.code];
    return actions;
  }

  const globalActions = computed(() =>
    compact(
      (rawGlobalActions.value || []).map((action) => {
        if (action.code === 'back') return null;
        if (action.params && typeof action.params == 'string') {
          action.params = JSON.parse(action.params);
        }
        let visible = true;
        if (action.visibilityFn) {
          visible = deserialize(action.visibilityFn, { context: layoutParams.value, run: true });
        }
        const params = getActionParams(context, action);
        return {
          ...params,
          visible: visible ?? params.visible,
          label: action.label || action.code,
          disable: false,
          code: action.code,
          position: action.position || 0,
          params: action.params || {},
          icon: action['icon'] || action.mobileIcon,
        };
      })
    )
  );

  return {
    data,
    id,
    refetch,
    globalActions,
    loading,
  };
}
