<template>
  <v-container fluid class="pa-0 ma-0">
    <v-flex class="d-flex w-100 justify-end align-center">
      <v-btn-toggle
        v-if="!xs"
        v-model="viewType"
        variant="outlined"
        divided
        rounded="xl"
      >
        <v-btn value="tableView">
          <v-icon icon="mdi-table"></v-icon>
        </v-btn>

        <v-btn value="cardView">
          <v-icon icon="mdi-card-text-outline"></v-icon>
        </v-btn>
      </v-btn-toggle>
      <v-spacer></v-spacer>
      <v-pagination
        v-model="page"
        color="#769fdb"
        style="width: 80%"
        :length="totalPages"
        @update:modelValue="load"
        rounded="circle"
        class="ms-3"
      >
        <template v-slot:item="item">
          <template v-if="item.isActive">
            <v-text-field
              density="compact"
              label="Página"
              class="w-10 pt-5"
              v-model="item.page"
              @click:append-inner="changePage('page', item.page)"
              :append-inner-icon="'mdi-arrow-right'"
            />
          </template>
          <template v-else>
            <v-btn
              v-if="item.page < 1000"
              elevation="0"
              @click="changePage('page', item.page)"
              class="rounded-circle"
              :ellipsis="true"
              icon
              color="#769fdb80"
            >
              {{ item.page }}
            </v-btn>
            <v-tooltip :text="item.page.replaceAll(',', '.')" v-else>
              <template v-slot:activator="{ props }">
                <v-btn
                  v-if="item.page != '...'"
                  elevation="0"
                  @click="changePage('page', item.page)"
                  color="#769fdb80"
                  class="rounded-circle"
                  :ellipsis="true"
                  icon
                  v-bind="props"
                >
                  {{
                    Intl.NumberFormat("pt-BR", {
                      notation: "compact",
                      maximumFractionDigits: 0
                    }).format(Number.parseFloat(item.page.replaceAll(",", "")))
                  }}
                </v-btn>
                <v-btn
                  v-else
                  elevation="0"
                  @click="changePage('page', item.page)"
                  color="#769fdb80"
                  class="rounded-circle"
                  :ellipsis="true"
                  icon
                  v-bind="props"
                >
                  {{ item.page }}
                </v-btn>
              </template>
            </v-tooltip>
          </template>
        </template>
        <template #next>
          <v-btn
            :disabled="page == totalPages"
            size="large"
            variant="outlined"
            @click="changePage('next')"
            color="#769fdb"
            class="mr-0 me-5 text-none text-subtitle-1"
            append-icon="mdi-arrow-right"
          >
            Próxima
          </v-btn>
        </template>
        <template #prev>
          <v-btn
            :disabled="page == 1"
            size="large"
            variant="outlined"
            @click="changePage('prev')"
            color="#769fdb"
            class="mr-0 text-none text-subtitle-1"
            prepend-icon="mdi-arrow-left"
          >
            Anterior
          </v-btn>
        </template>
      </v-pagination>
    </v-flex>
    <VDataTableServer
      v-if="viewType == 'tableView'"
      v-model="selected"
      class="elevation-1"
      no-data-text="Nenhum dado foi encontrado"
      v-bind="$attrs"
      :headers="innerHeaders"
      :items="list"
      :loading="loading"
      :items-length="totalItems"
      v-model:items-per-page="itemsPerPage"
      v-model:page="page"
      items-per-page-text="Itens por página"
      :page-text="`1 de ${list.length}`"
      :height="height"
      :fixed-header="true"
      :sticky="true"
      @update:options="updateOptions"
      @update:groupBy="updateGroupBy"
      @update:itemsPerPage="updateItemsPerPage"
      @update:page="updatePage"
      @update:sortBy="updateSortBy"
    >
      <template v-slot:top> </template>
      <template v-slot:bottom>
        <!-- REMOVER PAGINAÇÃO NO FOOTER -->
      </template>
      <template v-slot:[`item.actionEdit`]="{ item }">
        <v-btn
          size="x-small"
          variant="outlined"
          v-if="canEdit && !onlyVisualize"
          @click="editItem(item.raw)"
          color="success"
          class="mr-0 text-none text-subtitle-2"
          prepend-icon="mdi-pencil"
        >
          Editar
        </v-btn>
      </template>
      <template v-slot:[`item.actionVisualize`]="{ item }">
        <v-btn
          size="x-small"
          variant="outlined"
          v-if="onlyVisualize || showVisualize"
          @click="visualizeItem(item.raw)"
          color="success"
          class="mr-0"
          prepend-icon="mdi-file-find"
        >
          Visualizar
        </v-btn>
      </template>
      <template v-slot:[`item.actionDelete`]="{ item }">
        <v-btn
          size="x-small"
          variant="outlined"
          @click="deleteItem(item.raw)"
          :disabled="!enableDelete(item.raw)"
          color="error"
          prepend-icon="mdi-delete"
        >
          Excluir
        </v-btn>
      </template>
      <template v-if="canActive" v-slot:[`item.enumDataState`]="{ item }">
        <v-btn
          size="x-small"
          variant="outlined"
          :loading="actionLoading.changeDataStateItem[item.raw.id]"
          v-if="enableDataState(item.raw) && canActive"
          @click="changeDataStateItem(item.raw)"
          :color="item.raw.enumDataState == 1 ? 'warning' : 'success'"
          :prepend-icon="
            item.raw.enumDataState == 1 ? 'mdi-cancel' : 'mdi-check-bold'
          "
        >
          {{ item.raw.enumDataState == 1 ? "Desativar" : "Ativar" }}
        </v-btn>
      </template>

      <!-- Slots passados para o componente -->
      <template v-for="(_, name) in $slots" v-slot:[name]="slotProps">
        <slot v-if="slotProps" :name="name" v-bind="slotProps" />
        <slot v-else :name="name" v-bind="slotProps" />
      </template>

      <!-- Slots dinâmicos a partir do Header -->
      <template
        v-for="(header, index) in headersSlotTyped"
        v-slot:[getSlotName(header)]="slotProps"
      >
        <template v-if="header.type == 'date'">
          <span v-if="!!slotProps.item.raw[header.key]">
            {{
              slotProps.item.raw[header.key] == null
                ? (slotProps.item.raw[header.key] = "-")
                : moment(slotProps.item.raw[header.key]).isValid()
                ? moment(slotProps.item.raw[header.key])
                    .utc()
                    .format("DD/MM/YYYY")
                : (slotProps.item.raw[header.key] = "-")
            }}
          </span>
          <span v-else>
            {{ "-" }}
          </span>
        </template>
        <template v-else-if="header.type == 'datetime'">
          <span v-if="!!slotProps.item.raw[header.key]">
            {{
              slotProps.item.raw[header.key] == null
                ? (slotProps.item.raw[header.key] = "-")
                : moment(slotProps.item.raw[header.key]).isValid()
                ? moment(slotProps.item.raw[header.key])
                    .utc()
                    .format("DD/MM/YYYY HH:mm")
                : (slotProps.item.raw[header.key] = "-")
            }}
          </span>
          <span v-else>
            {{ "-" }}
          </span>
        </template>
        <template v-else-if="header.type == 'currency'">
          <span v-if="!!slotProps.item.raw[header.key]">
            {{
              (Math.round(slotProps.item.raw[header.key] * 100) / 100)
                | currency
            }}
          </span>
          <span v-else>
            {{ "-" }}
          </span>
        </template>
        <template v-else-if="header.type == 'currency_usd'">
          <span v-if="!!slotProps.item.raw[header.key]">
            {{
              (Math.round(slotProps.item.raw[header.key] * 100) / 100)
                | currency_usd
            }}
          </span>
          <span v-else>
            {{ "-" }}
          </span>
        </template>
        <template v-else-if="header.type == 'decimal'">
          <span v-if="!!slotProps.item.raw[header.key]">
            {{
              slotProps.item.raw[header.key] | decimal(getFormatConfig(header))
            }}
          </span>
          <span v-else>
            {{ "-" }}
          </span>
        </template>
        <template v-else-if="header.type == 'percentage'">
          <span v-if="!!slotProps.item.raw[header.key]">
            {{
              !!slotProps.item.raw[header.key]
                ? `${Math.round(slotProps.item.raw[header.key] * 10000) / 100}%`
                : "-"
            }}
          </span>
          <span v-else>
            {{ "-" }}
          </span>
        </template>
        <template v-else-if="header.type == 'noyes'">
          <span v-if="!!slotProps.item.raw[header.key]">
            {{ slotProps.item.raw[header.key] ? "Sim" : "Não" }}
          </span>
          <span v-else>
            {{ "-" }}
          </span>
        </template>
        <template v-else-if="header.type == 'cnpj'">
          <span v-if="!!slotProps.item.raw[header.key]">
            {{ cnpjMask(slotProps.item.raw[header.key]) }}
          </span>
          <span v-else>
            {{ "-" }}
          </span>
        </template>
        <div
          v-else-if="header.type == 'icontruefalse'"
          :key="`${slotProps.item.id}_${index}`"
        >
          <v-icon v-if="slotProps.item.raw[header.key]" color="success"
            >mdi-check-bold</v-icon
          >
          <v-icon
            v-else-if="slotProps.item.raw[header.key] == false"
            color="error"
            >mdi-close-thick</v-icon
          >
        </div>
        <template v-else-if="header.type == 'enableddisabled'">
          <span v-if="!!slotProps.item.raw[header.key]">
            {{ slotProps.item.raw[header.key] ? "Ativo" : "Inativo" }}
          </span>
          <span v-else>
            {{ "-" }}
          </span>
        </template>
        <template v-else>
          <span>
            {{
              !!slotProps.item.raw[header.key]
                ? slotProps.item.raw[header.key]
                : "-"
            }}
          </span>
        </template>
      </template>
    </VDataTableServer>
    <template v-else>
      <v-window
        touch
        v-model="page"
        ref="swipeWindow"
        @update:modelValue="loadItems"
        :direction="mobile ? 'vertical' : 'vertical'"
      >
        <v-window-item v-if="page > 1" :value="page - 1"> </v-window-item>
        <v-window-item :value="page">
          <v-row
            class="d-flex align-stretch pa-4"
            ref="rowCardView"
            :min-height="cardViewHeight"
            :style="`min-height: ${cardViewHeight}px;`"
          >
            <template v-for="(item, index) in list">
              <slot name="cardView" v-bind="{ item, index }">
                <ZCDataTableCardView :loading="loading">
                  <v-flex class="h-100 d-flex flex-column justify-between">
                    <v-card-text>
                      <v-row>
                        <slot name="cardViewContent" v-bind="{ item, index }">
                        </slot>
                      </v-row>
                    </v-card-text>
                    <v-card-actions class="d-flex align-end">
                      <slot name="cardViewActions" v-bind="{ item, index }">
                      </slot>
                      <v-spacer
                        v-if="canDelete || canEdit || showVisualize"
                      ></v-spacer>
                      <v-btn
                        v-if="canDelete"
                        size="x-small"
                        variant="outlined"
                        @click="deleteItem(item)"
                        :disabled="!enableDelete(item)"
                        color="error"
                        class="text-subtitle-2"
                        prepend-icon="mdi-delete"
                      >
                        Excluir
                      </v-btn>
                      <v-btn
                        size="x-small"
                        variant="outlined"
                        v-if="canEdit && !onlyVisualize"
                        @click="editItem(item)"
                        color="success"
                        class="mr-0 text-none text-subtitle-2"
                        prepend-icon="mdi-pencil"
                      >
                        Editar
                      </v-btn>
                      <v-btn
                        size="x-small"
                        variant="outlined"
                        v-if="onlyVisualize || showVisualize"
                        @click="visualizeItem(item)"
                        color="success"
                        class="mr-0 text-subtitle-2"
                        prepend-icon="mdi-file-find"
                      >
                        Visualizar
                      </v-btn>
                    </v-card-actions>
                  </v-flex>
                </ZCDataTableCardView>
              </slot>
            </template>
          </v-row>
        </v-window-item>
        <v-window-item :value="page + 1" v-if="page < totalPages">
        </v-window-item>
      </v-window>
    </template>
  </v-container>
</template>

<script>

</script>

<script lang="ts" setup generic="T extends Item">
import ZCDataTableCardView from "./ZCDataTableCardView.vue";
import moment from "moment";
import _ from "lodash";
import { useDisplay } from 'vuetify'
import { ZCDataTableHeader } from '../../types';
//import { QueryOptions, TypedFilter } from "~~/types/core/odata";
import { computed, nextTick, onMounted, ref, useSlots, watch } from "vue";
import { useAxios } from "../../composables/useAxios";
import { useODataQuery } from "../../composables/useODataQuery";


//const nuxtApp = useNuxtApp();
const slots = useSlots();
const { $axios } = useAxios();
const buildQuery = useODataQuery();
const { mobile, xs, sm, md, lg, xl, xxl } = useDisplay()

const emit = defineEmits<{
  (e: "click:row", item: any): void;
  (e: "editItem", id: number, item: any): void;
  (e: "visualizeItem", id: number, item: any): void;
  (e: "deleteItem", id: number, item: any): void;
  (e: "changeDataState", id: number, item: any): void;
  (e: "dataLoaded", response: Response): void;
  (e: "update:loading", loading: boolean): void;
}>();

const props = defineProps({
  slots: {
    type: Object,
  },
  headers: {
    type: Array<ZCDataTableHeader>,
    default() {
      return [];
    },
  },
  resourceUrl: {
    type: String,
    default: "",
  },
  canEdit: {
    type: Boolean,
    default: true,
  },
  canDelete: {
    type: Boolean,
    default: true,
  },
  canActive: {
    type: Boolean,
    default: false,
  },
  onlyVisualize: {
    type: Boolean,
    default: false,
  },
  showVisualize: {
    type: Boolean,
    default: false,
  },
  odataQuery: {
    type: Object,
  },
  queryString: {
    type: Object,
  },
  height: {
    type: String,
    default: "80vh"
  },
  itemsPerPage: {
    type: Number,
  },
});
const viewType = ref<'tableView' | 'cardView'>(!mobile.value ? 'tableView' : 'cardView');

const rowCardView = ref(null);

let list: Object[] = [];

const page = ref<number>(1);
const pagina = ref<number>(0);
const totalItems = ref<number>(0);

const itemsPerPage = computed<number>(() => {
  if (props.itemsPerPage != undefined && props.itemsPerPage != null) {
    return props.itemsPerPage;
  }

  return viewType.value === 'cardView' ?  12 : 10;
});

// const onWindowSwipe = function(e, direction) {
//   let dir = direction?.toLowerCase()

//   if (dir == 'left' || dir == 'up') {
//     changePage('next')
//   }
//   else if (dir == 'right' || dir == 'down') {
//     changePage('prev')
//   }
// };


// const swipeWindow = ref(null)
// const { isSwiping, direction } = useSwipe(swipeWindow, {
//   onSwipeEnd: onWindowSwipe
// })

const totalPages = computed<number>(() => {
  if (itemsPerPage.value == 0) {
    return 0;
  }

  return Math.ceil(totalItems.value / itemsPerPage.value);
});

const changePage = (type: string, irPagina?: Number) => {

  if(page.value == Number(irPagina)) {
    return;
  }
  switch (type) {
    case "prev":
      page.value--;
      break;
    case "next":
      page.value++;
      break;
    case "page":
      irPagina = new Number((irPagina + "").replace(/\D/g, '' ));
    if(isNaN(Number(irPagina)))
    {
      return;
    }
      page.value = Number(irPagina);
      break;
  }
  loadItems();
};

const containsEnumDataState = ref(false);
const loading = ref(false);
const autoHeaders = ref([]);

const innerHeaders = computed<Array<Object>>(() => {
  if (!!props.headers && props.headers.length > 0) {
    for (let i = 0; i < props.headers.length; i++) {
      let header = props.headers[i];
      if (header.key == "id") {
        // header.width = "2%";
        break;
      }
    }
  }

  let functionsHeaders = [] as ZCDataTableHeader[];

  if (props.showVisualize && !props.onlyVisualize) {
    functionsHeaders.push({
      title: "",
      key: "actionVisualize",
      value: "actionVisualize",
      sortable: false,
      // width: "2%"
    });
  }

  if (props.canEdit) {
    functionsHeaders.push({
      title: "",
      key: props.onlyVisualize ? "actionVisualize" : "actionEdit",
      value: props.onlyVisualize ? "actionVisualize" : "actionEdit",
      sortable: false,
      // width: "2%"
    });
  }

  if (props.canDelete) {
    functionsHeaders.push({
      title: "",
      key: "actionDelete",
      value: "actionDelete",
      sortable: false,
      // width: "2%"
    });
  }

  if (containsEnumDataState && props.canActive) {
    functionsHeaders.push({
      title: "",
      key: "enumDataState",
      value: "enumDataState",
      sortable: false,
      // width: '2%'
    });
  }

  if (autoHeaders.value.length > 0) {
    functionsHeaders.push(...autoHeaders.value);
  }

  if (functionsHeaders.length > 0 && !!props.headers) {
    functionsHeaders.push(...props.headers);
    return functionsHeaders;
  } else {
    return props.headers;
  }
});

const headersSlotTyped = computed<Array<Object>>(() => {
  //Verificaçao para não sobrescrever SLOTS
  return !innerHeaders.value
    ? []
    : innerHeaders.value.filter(
        (header) =>
          header.type != undefined &&
          !slots.hasOwnProperty(`item.${header.key}`)
      );
});

const getSlotName = function (header) {
  return `item.${header.key}`;
};

const getId = (item: T) => {
  return item.hasOwnProperty("Id")
    ? item.Id
    : item.hasOwnProperty("id")
    ? item.id
    : 0;
};

const editItem = (item: T) => {
  let id = getId(item);

  emit("editItem", id, item);
};

const visualizeItem = (item: T) => {
  let id = getId(item);

  emit("visualizeItem", id, item);
};

const deleteItem = (item: T) => {
  let id = getId(item);

  emit("deleteItem", id, item);
};

const changeDataStateItem = (item: T) => {
  let id = getId(item);

  emit("changeDataState", id, item);
};

const enableDelete = (item: T) => {
  if (
    !props.canDelete ||
    (item.hasOwnProperty("enumRecordPermission") &&
      item.enumRecordPermission != 1 &&
      item.enumRecordPermission != 4)
  ) {
    return false;
  } else {
    return true;
  }
};

const cardViewHeight = ref(props.height);


const enableDataState = (item: T) => {
  return item.hasOwnProperty("enumDataState");
};
const count = async () => {
  loading.value = true;

  try {
    const top = itemsPerPage.value;
    const skip = itemsPerPage.value * (page.value - 1);


    let url = props.resourceUrl + "/count";

    if (!!props.odataQuery) {
      props.odataQuery.top = top;
      props.odataQuery.skip = skip;

      url += buildQuery(props.odataQuery);
    }
    else {
      props.queryString.top = top;
      props.queryString.skip = skip;
    }

    var reqCount = await $axios({
      url: url,
      method: "GET",
      params: props.queryString,
    });

    totalItems.value = reqCount.data;
  } catch {
  } finally {
    loading.value = false;
  }
};


const loadItems = async () => {
  loading.value = true;
  autoHeaders.value = [];
  try {
    const top = itemsPerPage.value;
    const skip = itemsPerPage.value * (page.value - 1);

    let url = props.resourceUrl;
    let queryString = props.queryString ?? {};

    if (!!props.odataQuery) {
      props.odataQuery.top = top;
      props.odataQuery.skip = skip;

      url += buildQuery(props.odataQuery);
    }
    else
    {
      queryString.top = top;
      queryString.skip = skip;
      queryString.page = page.value;
    }

    var req = await $axios({
      url: url,
      method: "GET",
      params: queryString,
    });

    if (!!req && req.data.hasOwnProperty("items")) {
      list = req.data.items;
    } else {
      list = req.data;
    }

    emit("dataLoaded", req.data);

    if (list[0] && !!list[0].hasOwnProperty("enumDataState")) {
      containsEnumDataState.value = true;
    }

    nextTick(() => {
      if (!!list && !!list.length && !props.headers.length) {
        for (var key in list[0]) {
          autoHeaders.value.push({
            title: key,
            key,
            sortable: true,
          });
        }
      }
    });
  } catch {
  } finally {
    loading.value = false;
    if(cardViewHeight.value < rowCardView.value?.$el?.clientHeight)
    {
        cardViewHeight.value = rowCardView.value?.$el?.clientHeight;
    }
  }
};

const load = async () => {
    if( page.value == 1) {

    }
    await count();
    await loadItems();
};

const updateOptions = async (options) => {

};

const updateGroupBy = async (groupBy:any) => {

};

const updateItemsPerPage = async (itemsPerPage:number) => {
  await loadItems();
};

const updatePage = async (page: number) => {
  await loadItems();
};

const updateSortBy = async (sortBy:Array<Object>) => {
  props.odataQuery.orderBy = sortBy.map((item) => { return item.key + ' ' + item.order; });
  await loadItems();
};



watch(props.resourceUrl, async () => {
  await count();
  await loadItems();
});

watch(loading, async (newVal) => {
  emit('update:loading', newVal);
});

const clickRow = (item: T) => {
  emit("click:row", item);
};

onMounted(async () => await load());

defineExpose({ load });
</script>

<style>
.expanded-row-container {
  width: 100%;
  max-width: 100%;
  overflow: hidden;
}

.subtable-header {
  background-color: #769fdb !important;
  color: #fff !important;
  font-weight: 700 !important;
}

.v-data-table__td.v-data-table-column--align-start.v-data-table__th.v-data-table__th {
  background-color: #769fdb !important;
  color: #fff;
  font-weight: 700;
}

.v-data-table__td.v-data-table-column--align-center.v-data-table__th.v-data-table__th {
  background-color: #769fdb !important;
  color: #fff;
  font-weight: 700;
}
.v-data-table__td.v-data-table-column--align-end.v-data-table__th.v-data-table__th {
  background-color: #769fdb !important;
  color: #fff;
  font-weight: 700;
}

.v-data-table-footer {
  background-color: #769fdb !important;
  color: #fff;
  font-weight: 700;
}

tr:nth-child(even) {
  border-left: 6px solid cyan;
  background-color: #769fdb30;
}

.v-pagination__list {
  justify-content: end !important;
  align-items: center;
}

.v-data-table-headers--loading {
  opacity: 1 !important;
}

.v-data-table__td {
  padding: 0px !important;
}

.v-data-table__td:first-of-type {
  padding: 16px !important;
}

@media screen and (max-width: 768px) {
  tr {
    max-width: 100%;
    position: relative;
    display: block;
  }

  tr:nth-child(odd) {
    border-left: 6px solid deeppink;
  }

  tr:nth-child(even) {
    border-left: 6px solid cyan;
  }

  tr td {
    display: flex;
    width: 100%;
    border-bottom: 1px solid #f5f5f5;
    height: auto;
    padding: 10px;
  }

  tr td ul li:before {
    content: attr(data-label);
    padding-right: 0.5em;
    text-align: left;
    display: block;
    color: #999;
  }

  .v-datatable__actions__select {
    width: 50%;
    margin: 0px;
    justify-content: flex-start;
  }

  .mobile .theme--light.v-table tbody tr:hover:not(.v-datatable__expand-row) {
    background: transparent;
  }
}
</style>
