<script setup>
import BaseIndex from "../../components/base/BaseIndex.vue";
import B2CDataTable from "../../components/common/B2CDataTable.vue";

import { api, ensureCsrf } from "../../services/api";
import { getFilterScalar } from "../../composables/useDataTableFilters.js";
import { computed, nextTick, onMounted, ref } from "vue";

/** Event filter (Drawer) — values match Spatie `event` column. */
const EVENT_SELECT_OPTIONS = [
  { label: "Created", value: "created" },
  { label: "Updated", value: "updated" },
  { label: "Deleted", value: "deleted" },
  { label: "Restored", value: "restored" },
];

const BADGE = {
  ok: "bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300",
  info: "bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300",
  muted:
    "bg-surface-200 text-surface-700 dark:bg-surface-600 dark:text-surface-200",
  danger:
    "bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300",
};

const EVENT_VALUE_MAP = {
  created: { label: "Created", class: BADGE.ok },
  updated: { label: "Updated", class: BADGE.info },
  deleted: { label: "Deleted", class: BADGE.danger },
  restored: {
    label: "Restored",
    class:
      "bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-300",
  },
};

const columns = [
  {
    key: "created_at",
    header: "When",
    type: "date",
    searchable: false,
    filterable: false,
    sortable: true,
    defaultVisible: true,
  },
  {
    key: "event",
    header: "Event",
    type: "badge",
    searchable: true,
    filterable: true,
    filterType: "select",
    filterOptions: EVENT_SELECT_OPTIONS,
    sortable: true,
    valueMap: EVENT_VALUE_MAP,
    defaultBadgeEntry: {
      label: "—",
      class: BADGE.muted,
    },
  },
  {
    key: "description",
    header: "Description",
    type: "text",
    searchable: true,
    filterable: true,
    sortable: true,
  },
  {
    key: "causer_display",
    header: "Causer",
    type: "text",
    filterKey: "causer_display",
    searchable: true,
    filterable: false,
    sortable: false,
  },
  {
    key: "subject_line",
    header: "Subject",
    type: "text",
    searchable: true,
    filterable: false,
    sortable: false,
  },
];

const rows = ref([]);
const totalRecords = ref(0);
const totalAllRecords = ref(0);

const loading = ref(false);
const error = ref("");

const pagination = ref({ page: 1, limit: 25 });
const sort = ref([{ field: "created_at", order: -1 }]);

const tableUiState = ref({
  globalSearch: "",
  filters: {},
});

const displayRows = computed(() => rows.value);

let loadTimer = null;
let fetchSeq = 0;

function criteriaSignature(g, filters) {
  return JSON.stringify({
    globalSearch: g,
    filters: filters ?? {},
  });
}

function scheduleLoad() {
  if (loadTimer) clearTimeout(loadTimer);
  loadTimer = setTimeout(() => {
    loadTimer = null;
    load();
  }, 400);
}

function scalarFromFilters(key) {
  const raw = tableUiState.value?.filters?.[key];
  const v = getFilterScalar(raw);
  if (v == null) return "";
  if (Array.isArray(v)) return v.map(String).join(" ").trim();

  return String(v).trim();
}

function sortFieldApi(field) {
  const allowed = new Set([
    "created_at",
    "description",
    "event",
    "causer_id",
  ]);

  return allowed.has(field) ? field : "created_at";
}

async function load() {
  const seq = ++fetchSeq;
  loading.value = true;
  error.value = "";
  try {
    await ensureCsrf();
    const g = String(tableUiState.value?.globalSearch ?? "").trim();

    const eventFilter = scalarFromFilters("event");
    const descriptionFilter = scalarFromFilters("description");

    const s0 = sort.value?.[0];
    const sf = sortFieldApi(s0?.field ?? "created_at");
    const asc = Number(s0?.order) === 1;

    const { data } = await api.get("/api/settings/activity-log", {
      params: {
        page: pagination.value.page,
        per_page: pagination.value.limit,
        search: g || undefined,
        event: eventFilter || undefined,
        description: descriptionFilter || undefined,
        sort_field: sf,
        sort_order: asc ? "asc" : "desc",
      },
    });
    if (seq !== fetchSeq) return;

    const raw = data.data ?? [];
    rows.value = raw.map((r) => ({
      ...r,
      causer_display: causerName(r),
      subject_line: subjectLabel(r),
    }));

    totalRecords.value = data.meta?.total ?? 0;
    totalAllRecords.value = data.meta?.total ?? 0;
  } catch (e) {
    if (seq !== fetchSeq) return;

    error.value = e?.response?.data?.message ?? "Could not load activity log.";
    rows.value = [];
    totalRecords.value = 0;
  } finally {
    if (seq === fetchSeq) loading.value = false;
  }
}

onMounted(async () => {
  await nextTick();
  await load();
});

function onTableState(state) {
  const nextGs = String(state?.globalSearch ?? "");
  const nextFilters =
    state?.filters && typeof state.filters === "object"
      ? { ...state.filters }
      : {};

  const prevSig = criteriaSignature(
    tableUiState.value.globalSearch,
    tableUiState.value.filters,
  );
  const nextSig = criteriaSignature(nextGs, nextFilters);

  tableUiState.value = {
    globalSearch: nextGs,
    filters: nextFilters,
  };

  if (nextSig !== prevSig) {
    pagination.value = { ...pagination.value, page: 1 };
    scheduleLoad();
  }
}

function formatWhen(iso) {
  if (!iso) return "—";
  try {
    return new Date(iso).toLocaleString(undefined, {
      dateStyle: "medium",
      timeStyle: "short",
    });
  } catch {
    return iso;
  }
}

function causerName(row) {
  return row.causer?.name ?? row.causer?.email ?? "—";
}

function subjectLabel(row) {
  const t = row.subject_type;
  const id = row.subject_id;

  if (!t && id == null) return "—";

  const short = t ? t.replace(/^.*\\Models\\/, "") : "";
  const raw = id != null ? `${short} #${id}` : short || "—";

  return raw.charAt(0).toUpperCase() + raw.slice(1);
}
</script>

<template>
  <BaseIndex flush hide-header>
    <B2CDataTable
      table-key="settings.activity-log"
      :columns="columns"
      :rows="displayRows"
      :loading="loading"
      server-mode
      :total-records="totalRecords"
      :total-all-records="totalAllRecords"
      :pagination="pagination"
      :sort="sort"
      :persist-to-server="true"
      search-placeholder="Zoeken…"
      :table-error="error"
      :rows-per-page-options="[10, 25, 50]"
      :paginator="true"
      :enable-export="false"
      resource-label-singular="entry"
      resource-label-plural="entries"
      @update:pagination="
        pagination = $event;
        load();
      "
      @update:sort="
        sort = $event;
        load();
      "
      @update:state="onTableState($event)"
    >
      <template #toolbar-title>
        <div>
          <h1
            class="text-2xl font-semibold tracking-tight text-surface-950 dark:text-surface-0 m-0"
          >
            Activity log
          </h1>
          <p
            class="text-sm text-surface-600 dark:text-surface-400 mt-1.5 mb-0 max-w-3xl"
          >
            Spatie Activity Log audit trail.
          </p>
        </div>
      </template>
      <template #cell-created_at="{ row }">
        {{ formatWhen(row.created_at) }}
      </template>
      <template #cell-description="{ row }">
        <span class="line-clamp-2">{{ row.description }}</span>
      </template>
    </B2CDataTable>
  </BaseIndex>
</template>
