<template>
  <div>
    <input
      ref="importFileInput"
      type="file"
      accept=".xlsx"
      class="hidden"
      @change="onFileSelected"
    />

    <DefaultHeaderPage>
      <template #after>
        <div class="flex gap-sm q-mt-md">
          <q-btn
            unelevated
            class="btn-gradient"
            :label="$t('associado.import_afastamentos')"
            icon="mdi-upload"
            padding="8px 12px"
          />
          <q-btn
            unelevated
            class="btn-gradient"
            :label="$t('associado.import_associados')"
            icon="mdi-upload"
            padding="8px 12px"
            :loading="importing"
            @click="onImportClick"
          />
          <q-btn
            unelevated
            class="btn-gradient"
            icon="mdi-clock-outline"
            padding="8px 12px"
            :title="$t('import_log.history_title')"
            @click="onOpenImportHistory"
          />
          <q-btn
            unelevated
            class="btn-gradient"
            :label="$t('common.actions.new')"
            icon="mdi-plus"
            padding="8px 12px"
            @click="onAddItem"
          />
        </div>
      </template>
    </DefaultHeaderPage>

    <DefaultTableServerSide
      ref="tableRef"
      :columns="columns"
      :api-call="getAssociadosPaginated"
      :add-item="false"
      open-item
      @on-row-click="onRowClick"
    >
      <template #body-cell-actions="{ row }">
        <div class="row no-wrap items-center" style="gap: 4px">
          <q-btn flat round dense color="violet-normal" icon="mdi-pencil" @click.stop="onRowClick({ row })" />
          <q-btn
            flat round dense
            :color="row.status === 'on_leave' || row.status?.value === 'on_leave' ? 'grey-4' : 'violet-normal'"
            icon="mdi-account-minus"
            :disable="row.status === 'on_leave' || row.status?.value === 'on_leave'"
            @click.stop="onSetOnLeave(row)"
          />
          <q-btn flat round dense color="violet-normal" icon="mdi-calendar" @click.stop />
          <q-btn flat round dense color="violet-normal" icon="mdi-sofa" @click.stop />
        </div>
      </template>

      <template #body-cell-status="{ row }">
        <q-td class="text-center">
          <q-badge
            outline
            :color="getStatusColor(row.status)"
            :label="$t(getStatusI18nKey(row.status))"
          />
        </q-td>
      </template>
    </DefaultTableServerSide>

    <q-separator class="q-my-xl" />

    <AccessLogsTable />
  </div>
</template>

<script setup>
import { ref, computed, defineAsyncComponent, useTemplateRef } from "vue";
import { useQuasar } from "quasar";
import { useI18n } from "vue-i18n";
import { permissionStore } from "src/stores/permission";
import { getAssociadosPaginated, importAssociados, setUserOnLeave } from "src/api/user";
import { getStatusColor, getStatusI18nKey } from "src/helpers/utils";
import { useImportPoller } from "src/composables/useImportPoller";
import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.vue";
import DefaultTableServerSide from "src/components/defaults/DefaultTableServerSide.vue";
import AccessLogsTable from "./components/AccessLogsTable.vue";

const AddEditAssociadoDialog = defineAsyncComponent(
  () => import("./components/AddEditAssociadoDialog.vue"),
);
const ImportHistoryDialog = defineAsyncComponent(
  () => import("src/components/ImportHistoryDialog.vue"),
);

const permission_store = permissionStore();
const $q = useQuasar();
const { t } = useI18n();
const tableRef = ref(null);
const importFileInput = useTemplateRef("importFileInput");
const { polling: importing, start: startPolling } = useImportPoller();

const columns = computed(() => [
  {
    name: "registration",
    label: t("associado.cracha"),
    field: "registration",
    align: "left",
    sortable: true,
    width: "10%",
  },
  {
    name: "name",
    label: t("common.terms.name"),
    field: "name",
    align: "left",
    sortable: true,
    width: "25%",
  },
  {
    name: "position",
    label: t("associado.position"),
    field: (row) => row.position?.name ?? "—",
    align: "left",
    sortable: true,
    width: "25%",
  },
  {
    name: "admission_date",
    label: t("associado.admission"),
    field: (row) => (row.admission_date ? row.admission_date : "—"),
    align: "left",
    sortable: true,
    width: "10%",
  },
  {
    name: "expiry_date",
    label: t("associado.validity"),
    field: (row) => (row.expiry_date ? row.expiry_date : "—"),
    align: "left",
    sortable: true,
    width: "10%",
  },
  {
    name: "actions",
    label: t("common.terms.actions"),
    align: "right",
    required: true,
    width: "15%",
  },
  {
    name: "status",
    label: t("common.terms.status"),
    field: "status",
    align: "center",
    sortable: true,
    width: "5%",
  },
]);

const onAddItem = async () => {
  if (!permission_store.getAccess("associado", "add")) {
    $q.notify({ type: "negative", message: t("validation.permissions.add") });
    return;
  }
  $q.dialog({ component: AddEditAssociadoDialog }).onOk(() => {
    tableRef.value?.refresh();
  });
};

const onRowClick = async ({ row }) => {
  if (!permission_store.getAccess("associado", "edit")) {
    $q.notify({ type: "negative", message: t("validation.permissions.edit") });
    return;
  }
  $q.dialog({
    component: AddEditAssociadoDialog,
    componentProps: {
      associado: row,
      title: () => t("common.actions.edit") + " " + t("ui.navigation.associados"),
    },
  }).onOk(() => {
    tableRef.value?.refresh();
  });
};

const onSetOnLeave = (row) => {
  if (!permission_store.getAccess("associado", "edit")) {
    $q.notify({ type: "negative", message: t("validation.permissions.edit") });
    return;
  }

  $q.dialog({
    title: t("associado.set_on_leave_title"),
    message: t("associado.set_on_leave_message", { name: row.name }),
    cancel: { flat: true, label: t("common.actions.cancel"), color: "grey-7" },
    ok: { unelevated: true, label: t("associado.set_on_leave_confirm"), color: "violet-normal" },
    persistent: true,
  }).onOk(async () => {
    try {
      await setUserOnLeave(row.id);
      tableRef.value?.refresh();
    } catch {
      // silent
    }
  });
};

const onOpenImportHistory = () => {
  $q.dialog({ component: ImportHistoryDialog, componentProps: { type: 'associado' } });
};

const onImportClick = () => {
  if (!permission_store.getAccess("associado", "add")) {
    $q.notify({ type: "negative", message: t("validation.permissions.add") });
    return;
  }
  importFileInput.value.value = null;
  importFileInput.value.click();
};

const onFileSelected = async (event) => {
  const file = event.target.files?.[0];
  if (!file) return;

  try {
    const { import_id } = await importAssociados(file);

    startPolling(import_id, {
      onComplete: (stats) => {
        $q.notify({
          type: "positive",
          message: t("associado.import_sync_result", {
            created:     stats.created,
            updated:     stats.updated,
            inactivated: stats.inactivated,
          }),
          timeout: 6000,
        });
        tableRef.value?.refresh();
      },
      onError: () => $q.notify({ type: "negative", message: t("http.errors.failed") }),
      onTimeout: () => $q.notify({ type: "warning", message: t("associado.import_processing") }),
    });
  } catch {
    $q.notify({ type: "negative", message: t("http.errors.failed") });
  }
};
</script>

<style scoped>
.gap-sm {
  gap: 8px;
}

.btn-gradient {
  background: linear-gradient(90deg, #4d1658 0%, #8b30a5 100%) !important;
  color: white !important;
  border-radius: 8px !important;
}

.btn-gradient :deep(.q-icon) {
  color: white !important;
}
</style>
