import CustomDataTable from "../../../../assets/js/app/CustomDataTable.js?v=1.0.0";
import {
  mostrarMensajes,
  mostrarToastify,
  obtenerHTMLBotonesDropdown,
  descargarArchivo,
  obtenerNombreModulo,
  str_pad,
} from "../../../../assets/js/app/funcionesGenerales.js?v=1.0.0";
import metodosFormularios from "../../../../assets/js/app/metodosFormularios.js?v=1.0.0";
import PlanillaUnica from "../models/planillaUnicaModel.js?v=1.0.0";
import TipoPlanilla from "../models/tipoPlanillaModel.js?v=1.0.0";
import InstitucionPlanillaUnica from "../models/institucionPlanillaUnicaModel.js?v=1.0.0";
import DocumentoPlanillaUnica from "../models/documentoPlanillaUnicaModel.js?v=1.0.0";
import CodigoObservacionPlanillaUnica from "../models/codigoObservacionPlanillaUnicaModel.js?v=1.0.0";

!(function () {
  document.getElementById("busqueda-form").addEventListener("submit", (e) => {
    e.preventDefault();
    configBusqueda.buscar();
  });

  document.getElementById("empleado-form").addEventListener("submit", (e) => {
    e.preventDefault();
    configBusqueda.guardar();
  });

  document.getElementById("btn-excel").addEventListener("click", () => {
    configBusqueda.exportar({
      type: "excel",
    });
  });

  document.getElementById("btn-csv").addEventListener("click", () => {
    configBusqueda.exportar({
      type: "csv",
    });
  });

  document.getElementById("btn-agregar-extra").addEventListener("click", () => {
    configBusqueda.editar();
  });

  document
    .getElementById("btn-buscar-empleado")
    .addEventListener("click", () => {
      configBusqueda.buscarEmpleado();
    });

  document.addEventListener("click", function (e) {
    const target = e.target;
    if (target.classList.contains("editar-empleado"))
      configBusqueda.editar(target.dataset.id);

    if (target.classList.contains("eliminar-empleado"))
      configBusqueda.eliminar(target.dataset.id);
  });
})();

window.onload = () => {
  Promise.all([inicializarTablas(), configBusqueda.inicializar()]).then(() => {
    document.querySelector(".loader") &&
      document.querySelector(".loader").classList.add("d-none");

    document
      .querySelectorAll(`input[type="search"]:not(.form-control-sm)`)
      .forEach((input) => input.classList.add("form-control-sm"));
  });
};

function inicializarTablas() {
  return new Promise((resolve, reject) => {
    try {
      // V3
      configBusqueda.tabla = new CustomDataTable({
        id: "empleados-tbl",
        alineadoIzquierda: [4, 5, 6, 7, 8],
        noOrdenable: [23],
        responsive: false,
        filaSeleccionable: false,
        adicional: {
          scrollY: "60vh",
          scrollX: true,
          scrollCollapse: true,
          paging: false,
          fixedColumns: {
            left: 4,
            right: 1,
          },
        },
      });

      $("#empleados-tbl tbody").on("click dblclick", "td", function () {
        if ($(this).closest("tr").attr("id") && $(this).index() != 23) {
          if ($(this).closest("tr").hasClass("special-selected")) {
            $(this).closest("tr").removeClass("special-selected");
          } else {
            configBusqueda.tabla.tabla
              .$("tr.special-selected")
              .removeClass("special-selected");
            $(this).closest("tr").addClass("special-selected");
          }
        }
      });

      $("#empleados-tbl tbody").on("dblclick", "td", function () {
        if ($(this).closest("tr").attr("id") && $(this).index() != 23) {
          let id = $(this).closest("tr").attr("id").replace("trEmpleado", "");
          configBusqueda.editar(id);
        }
      });
      resolve();
    } catch (err) {
      reject(err);
    }
  });
}

const configBusqueda = {
  id: 0,
  idEncabezado: 0,
  cnt: 0,
  data: {},
  tabla: null,
  form: "busqueda-form",
  campos: {
    tipoPlanilla: document.getElementById("cbo-tipoPlanilla"),
    periodo: document.getElementById("txt-periodo"),
    codempleado: document.getElementById("txt-codempleado"),
    configuracion: document.getElementById("cbo-configuracion"),
  },
  camposModal: {
    tipoDocumento: document.getElementById("cbo-tipoDocumento"),
    institucionPrevisional: document.getElementById(
      "cbo-institucionPrevisional"
    ),
    codigoObservacion1: document.getElementById("cbo-codigoObservacion1"),
    codigoObservacion2: document.getElementById("cbo-codigoObservacion2"),
    numeroDocumento: document.getElementById("txt-numeroDocumento"),
    numeroPatronal: document.getElementById("txt-numeroPatronal"),
    primerNombre: document.getElementById("txt-primerNombre"),
    segundoNombre: document.getElementById("txt-segundoNombre"),
    primerApellido: document.getElementById("txt-primerApellido"),
    segundoApellido: document.getElementById("txt-segundoApellido"),
    apellidoCasada: document.getElementById("txt-apellidoCasada"),
    salario: document.getElementById("num-salario"),
    pagoAdicional: document.getElementById("num-pagoAdicional"),
    montoVacacion: document.getElementById("num-montoVacacion"),
    dias: document.getElementById("num-dias"),
    horas: document.getElementById("num-horas"),
    diasVacacion: document.getElementById("num-diasVacacion"),
  },
  modal: {
    id: "modal-empleado",
    mostrar: () => $(`#${configBusqueda.modal.id}`).modal("show"),
    ocultar: () => $(`#${configBusqueda.modal.id}`).modal("hide"),
  },
  ultimaBusqueda: null,
  inicializar: function () {
    return new Promise(async (resolve, reject) => {
      try {
        let { data: tiposPlanilla } = await TipoPlanilla.obtenerPorUsuario();

        tiposPlanilla = tiposPlanilla || [];

        let opciones = tiposPlanilla.map(
          (tipo) =>
            `<option value="${tipo.codtipoplanilla}">${tipo.tipoPlanilla}</option>`
        );

        opciones.length > 0 &&
          opciones.unshift(
            `<option selected disabled value="">Seleccione</option>`
          );

        this.campos.tipoPlanilla.innerHTML = opciones.join("");

        $(`#${this.campos.tipoPlanilla.id}`)
          .selectpicker("destroy")
          .selectpicker();

        let { data: documentos } = await DocumentoPlanillaUnica.obtenerTodos();
        let { data: instituciones } =
          await InstitucionPlanillaUnica.obtenerTodos();
        let { data: codigosObservacion } =
          await CodigoObservacionPlanillaUnica.obtenerTodos();

        documentos = documentos || [];
        instituciones = instituciones || [];
        codigosObservacion = codigosObservacion || [];

        let opcionesDocumentos = [
            `<option selected disabled value="">Seleccione</option>`,
            ...documentos.map(
              (doc) =>
                `<option value="${doc.codigo}">${doc.codigo} - ${doc.tipoDocumento}</option>`
            ),
          ],
          opcionesInstituciones = [
            `<option selected disabled value="">Seleccione</option>`,
            ...instituciones.map(
              (inst) =>
                `<option value="${inst.codigo.length > 0 ? inst.codigo : 0}">${
                  inst.codigo
                } - ${inst.nombreInstitucion}</option>`
            ),
          ],
          opcionesCodigos = [
            `<option selected disabled value="">Seleccione</option>`,
            ...codigosObservacion.map(
              (cod) =>
                `<option value="${cod.codigo}">${cod.codigo} - ${cod.concepto}</option>`
            ),
          ];

        this.camposModal.tipoDocumento.innerHTML = opcionesDocumentos.join("");
        this.camposModal.institucionPrevisional.innerHTML =
          opcionesInstituciones.join("");
        this.camposModal.codigoObservacion1.innerHTML =
          opcionesCodigos.join("");
        this.camposModal.codigoObservacion2.innerHTML =
          opcionesCodigos.join("");

        $(`#${this.camposModal.codigoObservacion1.id}`)
          .selectpicker("destroy")
          .selectpicker();
        $(`#${this.camposModal.codigoObservacion2.id}`)
          .selectpicker("destroy")
          .selectpicker();

        resolve();
      } catch (err) {
        reject(err);
      }
    });
  },
  evaluarCantidadRegistros: function () {
    const cantidadRegistros = Object.values(this.data).length;

    document.getElementById(
      "lbl-info-cantidad"
    ).innerHTML = `( ${cantidadRegistros} registros )`;

    document.getElementById("btn-excel").disabled = cantidadRegistros == 0;
    document.getElementById("btn-csv").disabled = cantidadRegistros == 0;
    document.getElementById("btn-agregar-extra").disabled =
      cantidadRegistros == 0;
  },
  buscar: async function () {
    if (!metodosFormularios.validar({ id: this.form })) return;

    try {
      const periodo = moment(
        this.campos.periodo._flatpickr.selectedDates[0]
      ).format("MMyyyy");

      this.tabla.limpiar().redibujar();
      this.data = {};
      this.id = 0;
      this.idEncabezado = 0;

      document.getElementById(
        "lbl-info"
      ).innerHTML = `Tipo de planilla: <strong>${
        this.campos.tipoPlanilla.options[
          this.campos.tipoPlanilla.options.selectedIndex
        ].text
      }</strong>. Período: <strong>${this.campos.periodo.value}</strong>.`;

      let { data: empleados } = await PlanillaUnica.buscar({
        tipoPlanilla: this.campos.tipoPlanilla.value,
        periodo,
        datosNuevos: this.campos.configuracion.value,
      });

      this.ultimaBusqueda = {
        codtipoplanilla: this.campos.tipoPlanilla.value,
        tipoPlanilla:
          this.campos.tipoPlanilla.options[
            this.campos.tipoPlanilla.options.selectedIndex
          ].text,
        periodo,
        labelPeriodo: this.campos.periodo.value,
      };

      empleados = empleados || [];

      empleados.forEach((empleado) => {
        this.cnt++;
        this.data[this.cnt] = empleado;

        const fila = this.prepararParaFila({
          datos: empleado,
          id: this.cnt,
        });

        this.tabla.agregarFila({
          datos: fila,
          idFila: `trEmpleado${this.cnt}`,
        });
      });

      if (empleados.length == 0)
        mostrarToastify({
          type: "info",
          message: "No se encontraron registros",
        });

      this.tabla.redibujar();
      this.evaluarCantidadRegistros();

      //Aquí hay que agregar la parte de los detalles de la búsqueda
    } catch (err) {
      mostrarMensajes.error(err);
    }
  },
  buscarEmpleado: async function () {
    if (!metodosFormularios.validar({ id: "empleado-form" })) return;

    try {
      const resultado = await PlanillaUnica.buscarEmpleado({
        codempleado: this.campos.codempleado.value,
      });

      if (resultado.data.length == 0) {
        mostrarToastify({
          type: "info",
          message: "No se encontraron registros",
        });
        return;
      }

      const empleado = resultado.data[0];

      this.desbloquearCampos();
      this.cargarCampos(empleado);
    } catch (err) {
      mostrarMensajes.error(err);
    }
  },
  prepararParaFila: function ({ datos, id }) {
    return {
      0: id,
      1: datos.codempleado,
      2: "DUI",
      3: datos.numeroDocumento,
      4: datos.primerNombre,
      5: datos.segundoNombre,
      6: datos.primerApellido,
      7: datos.segundoApellido,
      8: datos.apellidoCasada,
      9: datos.documentoEmpleador,
      10: datos.numeroPatronalEmpleador,
      11: datos.periodo,
      12: datos.correlativoTrabajo,
      13: datos.numeroPatronalEmpleado,
      14: datos.institucionPrevisional,
      15: `$${parseFloat(datos.salario).toLocaleString("en-US")}`,
      16: `$${parseFloat(datos.pagoAdicional).toLocaleString("en-US")}`,
      17: `$${parseFloat(datos.montoVacaciones).toLocaleString("en-US")}`,
      18: datos.dias,
      19: datos.horas,
      20: datos.diasVacacion,
      21: str_pad({
        input: datos.codigo1,
        padLength: 2,
        padString: "0",
        padType: "STR_PAD_LEFT",
      }),
      22: str_pad({
        input: datos.codigo2,
        padLength: 2,
        padString: "0",
        padType: "STR_PAD_LEFT",
      }),
      23: obtenerHTMLBotonesDropdown([
        {
          tipo: "edit",
          texto: "Editar",
          selectorClase: "editar-empleado",
          selectorId: id,
        },
        {
          tipo: "delete",
          texto: "Eliminar",
          selectorClase: "eliminar-empleado",
          selectorId: id,
        },
      ]),
    };
  },
  exportar: async function ({ type = "excel" }) {
    if (!!!this.ultimaBusqueda) return;

    try {
      let complementoMensaje = `<br> Se generará un archivo <strong>.xlsx</strong>, no olvide eliminar el encabezado antes de exportar a <strong>.csv</strong>.`;

      if (type == "csv") {
        complementoMensaje = `<br> Se generará un archivo <strong>.csv</strong>, se recomienda no modificarlo para evitar errores en la carga.`;
      }

      const confirmacion = await mostrarMensajes.confirm({
        title: "¡Atención!",
        message: `Se generará un archivo con los datos de la planilla <strong>${this.ultimaBusqueda.tipoPlanilla}</strong> para el período <strong>${this.ultimaBusqueda.labelPeriodo}</strong>.${complementoMensaje}`,
      });

      if (!confirmacion) return;

      let planillaUnica = new PlanillaUnica({
        id: this.idEncabezado || 0,
        tipoPlanilla: this.ultimaBusqueda.codtipoplanilla,
        periodo: this.ultimaBusqueda.periodo,
        empleados: Object.values(this.data) || [],
        fechaRegistro: null,
        usuario: null,
      });

      const respuesta = await planillaUnica.generar({
        tipoArchivo: type,
      });

      switch (respuesta.message) {
        case "success":
          const ruta = `main/${obtenerNombreModulo()}/docs/planillaUnica/${type}/${
            respuesta.nombreArchivo
          }`;

          this.idEncabezado = respuesta.id;

          descargarArchivo({
            nombreArchivo: respuesta.nombreArchivo,
            blobURL: ruta,
          });

          mostrarToastify({
            type: "success",
            message: "Archivo generado con éxito",
          });
          break;
        default:
          mostrarMensajes.error(respuesta);
          break;
      }
    } catch (err) {
      if (!!err) mostrarMensajes.error(err);
    }
  },
  editar: async function (id = 0) {
    await metodosFormularios.limpiar({ id: "empleado-form" });

    this.id = id;

    const empleado = this.data[id] || null;

    if (!!empleado) this.cargarCampos(empleado);

    if (this.id == 0) {
      this.bloquearCampos();
    } else {
      this.desbloquearCampos();
    }

    $(`#${this.camposModal.codigoObservacion1.id}`)
      .selectpicker("destroy")
      .selectpicker();
    $(`#${this.camposModal.codigoObservacion2.id}`)
      .selectpicker("destroy")
      .selectpicker();

    this.modal.mostrar();
  },
  cargarCampos: function (empleado) {
    this.campos.codempleado.value = empleado.codempleado;
    this.camposModal.tipoDocumento.value = parseInt(empleado.tipoDocumento);
    this.camposModal.numeroDocumento.value = empleado.numeroDocumento;
    this.camposModal.numeroPatronal.value = empleado.numeroPatronalEmpleado;
    this.camposModal.institucionPrevisional.value =
      empleado.institucionPrevisional;
    this.camposModal.primerNombre.value = empleado.primerNombre;
    this.camposModal.segundoNombre.value = empleado.segundoNombre;
    this.camposModal.primerApellido.value = empleado.primerApellido;
    this.camposModal.segundoApellido.value = empleado.segundoApellido;
    this.camposModal.apellidoCasada.value = empleado.apellidoCasada;
    this.camposModal.salario.value = empleado.salario
      ? parseFloat(empleado.salario).toFixed(2)
      : "";
    this.camposModal.pagoAdicional.value = empleado.pagoAdicional
      ? parseFloat(empleado.pagoAdicional).toFixed(2)
      : "";
    this.camposModal.montoVacacion.value = empleado.montoVacaciones
      ? parseFloat(empleado.montoVacaciones).toFixed(2)
      : "";
    this.camposModal.dias.value = empleado.dias || 0;
    this.camposModal.horas.value = empleado.horas || 0;
    this.camposModal.diasVacacion.value = empleado.diasVacacion || 0;
    this.camposModal.codigoObservacion1.value = empleado.codigo1
      ? parseInt(empleado.codigo1)
      : this.camposModal.codigoObservacion1.options[0].value;
    this.camposModal.codigoObservacion2.value = empleado.codigo2
      ? parseInt(empleado.codigo2)
      : this.camposModal.codigoObservacion2.options[0].value;

    $(`#${this.camposModal.codigoObservacion1.id}`)
      .selectpicker("destroy")
      .selectpicker();
    $(`#${this.camposModal.codigoObservacion2.id}`)
      .selectpicker("destroy")
      .selectpicker();
  },
  bloquearCampos: function () {
    const campos = Object.values(this.camposModal);
    campos.forEach((campo) => {
      campo.setAttribute("disabled", true);
    });

    this.campos.codempleado.readOnly = false;
    document.getElementById("btn-buscar-empleado").classList.remove("d-none");

    document.getElementById("btn-guardar-empleado").disabled = true;
  },
  desbloquearCampos: function () {
    const campos = Object.values(this.camposModal);
    campos.forEach((campo) => {
      campo.removeAttribute("disabled");
    });

    this.campos.codempleado.readOnly = true;
    document.getElementById("btn-buscar-empleado").classList.add("d-none");

    document.getElementById("btn-guardar-empleado").disabled = false;
  },
  guardar: function () {
    if (!metodosFormularios.validar({ id: "empleado-form" })) return;

    let empleado = this.data[this.id] || null;

    if (
      this.id == 0 &&
      Object.values(this.data).filter(
        (emp) => emp.codempleado == this.campos.codempleado.value.trim()
      ).length == 2
    )
      return mostrarMensajes.warning({
        message: "No es posible agregar más de dos veces el mismo empleado",
      });

    if (!empleado) {
      const primerEmpleado = Object.values(this.data)[0] || {};
      empleado = { ...primerEmpleado };
    }

    empleado.codempleado = this.campos.codempleado.value;
    empleado.tipoDocumento = this.camposModal.tipoDocumento.value;
    empleado.numeroDocumento = this.camposModal.numeroDocumento.value;
    empleado.numeroPatronalEmpleado = this.camposModal.numeroPatronal.value;
    empleado.institucionPrevisional =
      this.camposModal.institucionPrevisional.value;
    empleado.primerNombre = this.camposModal.primerNombre.value;
    empleado.segundoNombre = this.camposModal.segundoNombre.value;
    empleado.primerApellido = this.camposModal.primerApellido.value;
    empleado.segundoApellido = this.camposModal.segundoApellido.value || "";
    empleado.apellidoCasada = this.camposModal.apellidoCasada.value || "";
    empleado.salario = this.camposModal.salario.value;
    empleado.pagoAdicional = this.camposModal.pagoAdicional.value || 0;
    empleado.montoVacaciones = this.camposModal.montoVacacion.value || 0;
    empleado.dias = this.camposModal.dias.value;
    empleado.horas = this.camposModal.horas.value;
    empleado.diasVacacion = this.camposModal.diasVacacion.value || 0;
    empleado.codigo1 = this.camposModal.codigoObservacion1.value;
    empleado.codigo2 = this.camposModal.codigoObservacion2.value;

    let fila = this.prepararParaFila({
      datos: empleado,
      id: this.id > 0 ? this.id : this.cnt + 1,
    });

    if (this.id == 0) {
      this.cnt++;
      this.id = this.cnt;
      this.tabla
        .agregarFila({ datos: fila, idFila: `trEmpleado${this.id}` })
        .redibujar();
    } else {
      this.tabla
        .actualizarFila({ datos: fila, idFila: `trEmpleado${this.id}` })
        .redibujar();
    }

    this.data[this.id] = empleado;
    this.modal.ocultar();

    mostrarToastify({
      type: "success",
      message: "Empleado actualizado con éxito",
    });
  },
  eliminar: async function (id) {
    const empleado = this.data[id];

    try {
      const confirmacion = await mostrarMensajes.confirm({
        message: `Se eliminará el registro del empleado <strong>${empleado.primerNombre} ${empleado.segundoNombre} ${empleado.primerApellido} ${empleado.segundoApellido}</strong>. ¿Desea continuar?. Esta acción no se puede deshacer`,
        confirmButtonText: "Si, eliminar",
        cancelButtonText: "No, cancelar",
      });

      if (!confirmacion) return;

      delete this.data[id];
      this.tabla.eliminarFila({ idFila: `trEmpleado${id}` }).redibujar();
      mostrarToastify({
        type: "info",
        message: "Registro eliminado con éxito",
      });
    } catch (err) {
      if (!!err) mostrarMensajes.error(err);
    }
  },
};
