<template>
  <q-table
    v-model:fullscreen="fullscreen"
    flat
    :pagination="{ rowsPerPage }"
    :pagination-label="getPaginationLabel"
    row-key="id"
    :rows="rows"
    :rows-per-page-label="$t('common.ui.table.rows_per_page')"
    :columns="columns"
    :visible-columns="visibleColumns"
    :filter="filter"
    :grid="$q.screen.lt.sm"
    :loading="loading"
    class="softpar-table q-pa-sm"
    @row-click="onRowClick"
  >
    <template #top>
      <div
        class="flex full-width justify-between align-center q-mb-md q-pl-sm"
        style="gap: 1rem"
      >
        <q-input
          v-if="showSearchField"
          v-model="filter"
          debounce="250"
          :placeholder="$t('common.actions.search')"
          clearable
          autofocus
          class=""
          color="primary"
        >
          <template #append>
            <q-icon name="mdi-magnify" />
          </template>
        </q-input>

        <q-select
          v-if="showColumnsSelect"
          v-model="visibleColumns"
          multiple
          options-outlined
          :display-value="$q.lang.table.columns"
          emit-value
          map-options
          :options="mapColumns"
          style="width: 150px"
          options-selected-class="text-bold"
        />

        <q-space />

        <q-btn
          v-if="addItem"
          color="primary"
          padding="10px 16px"
          :outline="outlineAdd"
          :label="$t('common.actions.add')"
          @click="onAddItem"
        >
        </q-btn>
      </div>
    </template>

    <template #body-cell-actions="{ row }">
      <q-td v-if="deleteFunction">
        <q-item-section>
          <q-btn
            color="negative"
            flat
            dense
            icon="mdi-delete"
            style="width: 45px"
            class="q-ml-auto q-mr-sm"
            @click.prevent.stop="onDelete(row.id)"
          />
        </q-item-section>
      </q-td>
    </template>

    <template #loading>
      <q-inner-loading showing color="primary" />
    </template>

    <template v-if="!hideNoDataLabel" #no-data>
      <div v-if="!loading" class="q-my-md row justify-center full-width">
        <div class="q-pa-md body2">
          {{ $t("http.errors.no_records_found") }}
        </div>
      </div>
    </template>

    <template v-for="name in $slots" #[name]="data">
      <slot :name="name" v-bind="data"></slot>
    </template>
  </q-table>
</template>

<script setup>
import { ref, onMounted, toRaw, watch } from "vue";
import { useRouter } from "vue-router";

const emit = defineEmits(["onRowClick", "onAddItem", "noRows"]);

const {
  columns,
  apiCall,
  outlineAdd,
  openItem,
  openItemRoute,
  addItem,
  addItemRoute,
  rowsPerPage,
  showSearchField,
  noApiCall,
  hideNoDataLabel,
  deleteFunction,
} = defineProps({
  columns: {
    type: Array,
    required: true,
  },
  apiCall: {
    type: Function,
    required: true,
  },
  outlineAdd: {
    type: Boolean,
    default: false,
  },
  openItem: {
    type: Boolean,
    default: false,
  },
  openItemRoute: {
    type: String,
    default: "",
  },
  addItem: {
    type: Boolean,
    default: true,
  },
  addItemRoute: {
    type: String,
    default: "",
  },
  rowsPerPage: {
    type: Number,
    default: 10,
  },
  showSearchField: {
    type: Boolean,
    default: true,
  },
  showColumnsSelect: {
    type: Boolean,
    default: true,
  },
  noApiCall: {
    type: Boolean,
    default: false,
  },
  hideNoDataLabel: {
    type: Boolean,
    default: false,
  },
  deleteFunction: {
    type: Function,
    default: null,
  },
});

const router = useRouter();
const rows = ref([]);
const filter = ref("");
const loading = ref(true);
const fullscreen = ref(false);
const showInativos = ref(false);
const inativos = ref([]);

const getPaginationLabel = (from, to, last) => {
  return `${from}-${to} de ${last}`;
};

watch(showInativos, () => {
  if (showInativos.value) {
    rows.value = rows.value.concat(inativos.value);
  } else {
    inativos.value = rows.value.filter(
      (row) => row.status === false || row.ativo === false,
    );
    rows.value = rows.value.filter((row) => row.ativo);
  }
});

watch(
  () => apiCall,
  async () => {
    await onRequest();
  },
);

const mapColumns = columns.reduce((accm, column) => {
  if (!column.required) {
    accm.push({
      label: column.label,
      value: column.name,
    });
  }
  return accm;
}, []);

const visibleColumns = ref(mapColumns.map((column) => column.value));

const onRowClick = (evt, row, index) => {
  const item = toRaw(row);
  if (openItem) {
    if (openItemRoute) {
      router.push({ name: openItemRoute, params: { id: item.id } });
    } else {
      emit("onRowClick", { evt, row, index });
    }
  }
};

const onAddItem = () => {
  if (addItem) {
    if (addItemRoute) {
      router.push({ name: addItemRoute });
    } else {
      emit("onAddItem");
    }
  }
};

const onDelete = async (id) => {
  if (deleteFunction) {
    loading.value = true;
    try {
      await deleteFunction(id);
      await onRequest();
    } catch (error) {
      console.error(error);
    } finally {
      loading.value = false;
    }
  }
};

const onRequest = async () => {
  if (noApiCall) {
    loading.value = false;
    return;
  }
  loading.value = true;

  const response = await apiCall();
  rows.value.splice(0, rows.value.length, ...response);

  if (rows.value.length == 0) {
    emit("noRows");
  }
  loading.value = false;
};

onMounted(async () => {
  await onRequest({
    filter: undefined,
  });
});

defineExpose({
  refresh: onRequest,
});
</script>

<style lang="scss">
@import "src/css/table.scss";
</style>
