<script setup lang="ts" generic="T extends Record<string, any>">
import DataTable from 'primevue/datatable';
import InputText from 'primevue/inputtext';
import IconField from 'primevue/iconfield';
import InputIcon from 'primevue/inputicon';
import { ref } from 'vue';
import { PAGINATION } from '@/core/constants/app.constants';

const props = withDefaults(
  defineProps<{
    value: T[];
    loading?: boolean;
    totalRecords?: number;
    dataKey?: string;
    globalFilterFields?: string[];
    paginator?: boolean;
    rowsPerPage?: number;
    emptyMessage?: string;
    selectionMode?: 'single' | 'multiple';
    exportFilename?: string;
  }>(),
  {
    loading: false,
    dataKey: 'id',
    paginator: true,
    rowsPerPage: PAGINATION.defaultPageSize,
    emptyMessage: '데이터가 없습니다.',
  },
);

const emit = defineEmits<{
  'row-select': [row: T];
  'page': [event: any];
}>();

const globalFilter = ref('');
const dt = ref();

function exportCSV() {
  dt.value?.exportCSV();
}

defineExpose({ exportCSV });
</script>

<template>
  <div class="crud-table">
    <!-- Toolbar -->
    <div class="crud-table__toolbar">
      <div class="crud-table__toolbar-left">
        <slot name="toolbar-left" />
      </div>
      <div class="crud-table__toolbar-right">
        <slot name="toolbar-right" />
        <IconField v-if="globalFilterFields?.length">
          <InputIcon class="pi pi-search" />
          <InputText
            v-model="globalFilter"
            placeholder="검색..."
            size="small"
          />
        </IconField>
      </div>
    </div>

    <!-- DataTable -->
    <DataTable
      ref="dt"
      :value="value"
      :loading="loading"
      :dataKey="dataKey"
      :paginator="paginator"
      :rows="rowsPerPage"
      :rowsPerPageOptions="[...PAGINATION.pageSizeOptions]"
      :totalRecords="totalRecords"
      :globalFilterFields="globalFilterFields"
      :globalFilter="globalFilter"
      :selectionMode="selectionMode"
      :exportFilename="exportFilename"
      removableSort
      stripedRows
      showGridlines
      responsiveLayout="scroll"
      size="small"
      class="crud-table__datatable"
      @row-select="(e: any) => emit('row-select', e.data)"
      @page="(e: any) => emit('page', e)"
    >
      <template #empty>
        <div class="crud-table__empty">
          <i class="pi pi-inbox" style="font-size: 2rem" />
          <p>{{ emptyMessage }}</p>
        </div>
      </template>

      <slot />
    </DataTable>
  </div>
</template>

<style lang="scss" scoped>
@use '@/assets/styles/variables' as *;

.crud-table {
  &__toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: $space-sm;
    margin-bottom: $space-md;
  }

  &__toolbar-left,
  &__toolbar-right {
    display: flex;
    gap: $space-sm;
    align-items: center;
    flex-wrap: wrap;
  }

  &__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: $space-sm;
    padding: $space-2xl;
    color: $color-text-muted;
  }

  @media (max-width: $bp-mobile) {
    &__toolbar {
      flex-direction: column;
      align-items: stretch;
    }
  }
}
</style>
