<script setup>
import B2CDataTable from "../../../components/common/B2CDataTable.vue";
import BaseUserIcon from "../../../components/base/BaseUserIcon.vue";
import {
  EVENT_BADGES,
  DEFAULT_BADGE_ENTRY,
  ACTIVITY_CATEGORY_BADGES,
  getEventLabelNl,
} from "../../../constants/badgeStyles.js";
import { ref, computed, onMounted } from "vue";
import { useDataTableData } from "../../../composables/useDataTableData.js";
import { getDataTableColumns } from "../../../services/dataTableService.js";

const tableKey = "settings.activity-log";
const resourceKey = "activity-log";

const ACTIVITY_DEFAULT_BADGE = {
  label: "Actie",
  class: DEFAULT_BADGE_ENTRY.class,
};

const EVENT_FILTER_OPTIONS = Object.entries(EVENT_BADGES).map(([value]) => ({
  value,
  label: getEventLabelNl(value),
}));

const rawColumns = ref([]);
const columns = computed(() =>
  rawColumns.value.map((c) =>
    c.key === "event"
      ? {
          ...c,
          type: "badge",
          filterType: "select",
          filterOptions: EVENT_FILTER_OPTIONS,
          valueMap: ACTIVITY_CATEGORY_BADGES, // color by category (user/export/model)
          defaultBadgeEntry: ACTIVITY_DEFAULT_BADGE,
        }
      : c,
  ),
);
const defaultVisibleColumns = computed(() =>
  rawColumns.value.filter((c) => c.defaultVisible).map((c) => c.key),
);

const { rows, total, totalAll, loading, error, fetchPage } =
  useDataTableData(resourceKey);

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

function actionBadgeClass(row) {
  return (
    ACTIVITY_CATEGORY_BADGES[row.event]?.class ??
    ACTIVITY_CATEGORY_BADGES.default.class
  );
}

function relativeTime(isoString) {
  if (!isoString) return "—";
  const date = new Date(isoString);
  const now = new Date();
  const diffMs = now - date;
  const diffSec = Math.floor(diffMs / 1000);
  const diffMin = Math.floor(diffSec / 60);
  const diffHour = Math.floor(diffMin / 60);
  const diffDay = Math.floor(diffHour / 24);
  if (diffSec < 60) return "Zojuist";
  if (diffMin < 60) return `${diffMin} minuten geleden`;
  if (diffHour < 24) return `${diffHour} uur geleden`;
  if (diffDay === 1) return "Gisteren";
  if (diffDay < 7) return `${diffDay} dagen geleden`;
  return date.toLocaleDateString("nl-NL", {
    day: "numeric",
    month: "short",
    year: "numeric",
    hour: "2-digit",
    minute: "2-digit",
  });
}

function fullTimestamp(isoString) {
  if (!isoString) return "";
  return new Date(isoString).toLocaleString("nl-NL", {
    dateStyle: "full",
    timeStyle: "medium",
  });
}

function capitalizeFirst(str) {
  if (str == null || str === "") return "—";
  const s = String(str).trim();
  if (s.length === 0) return "—";
  return s.charAt(0).toUpperCase() + s.slice(1);
}

function subjectLabel(row) {
  const type = row.subject_type;
  const id = row.subject_id;
  if (!type && id == null) return "—";
  const short = type ? type.replace(/^App\\Models\\/, "") : "";
  const raw = id != null ? `${short} #${id}` : short || "—";
  return capitalizeFirst(raw);
}

function truncate(str, max = 80) {
  if (!str || typeof str !== "string") return "—";
  const s = str.trim();
  if (s.length <= max) return s;
  return s.slice(0, max) + "…";
}

function buildPayload() {
  const state = tableState.value;
  const p = pagination.value;
  const s =
    Array.isArray(sort.value) && sort.value.length
      ? sort.value[0]
      : { field: "created_at", order: -1 };
  const sortField =
    s.field === "user_label" ? "causer_id" : s.field || "created_at";

  const payload = {
    tableKey,
    pagination: {
      page: p.page,
      limit: p.limit,
    },
    sort: [
      {
        field: sortField,
        order: s.order ?? -1,
      },
    ],
    visibleColumns: state?.visibleColumns ?? defaultVisibleColumns.value,
    filters: state?.filters ?? {},
    globalSearch: (state?.globalSearch ?? "").trim(),
  };

  return payload;
}

async function loadPageOne() {
  pagination.value = { ...pagination.value, page: 1 };
  rows.value = [];
  const { data, meta } = await fetchPage(buildPayload());
  rows.value = data.map(enrichRow);
  total.value = meta.total;
  totalAll.value = meta.totalAll;
}

async function onLoadMore() {
  if (loading.value || rows.value.length >= total.value) return;
  pagination.value = { ...pagination.value, page: pagination.value.page + 1 };
  try {
    const { data, meta } = await fetchPage(buildPayload());
    rows.value = [...rows.value, ...data.map(enrichRow)];
    total.value = meta.total;
    totalAll.value = meta.totalAll;
  } catch {
    pagination.value = { ...pagination.value, page: pagination.value.page - 1 };
  }
}

function enrichRow(row) {
  return {
    ...row,
    event_label: getEventLabelNl(row.event),
    user_label:
      row.user_label ??
      row.causer_name ??
      row.causer_email ??
      row.causer?.name ??
      row.causer?.email ??
      "—",
    subject_label: row.subject_label ?? subjectLabel(row),
  };
}

function onState(state) {
  tableState.value = state;
  if (!hasInitialState) {
    hasInitialState = true;
    loadPageOne();
  } else {
    loadPageOne();
  }
}

function onSort(s) {
  sort.value = s?.length ? [...s] : [];
  loadPageOne();
}

async function loadColumns() {
  try {
    const data = await getDataTableColumns(resourceKey);
    rawColumns.value = Array.isArray(data) ? data : [];
  } catch {
    rawColumns.value = [];
  }
}

onMounted(() => {
  loadColumns();
});
</script>

<template>
  <BaseIndex :error="error" flush>
    <B2CDataTable
      v-if="columns.length"
      :table-key="tableKey"
      :columns="columns"
      :rows="rows"
      :total-records="total"
      :total-all-records="totalAll"
      :loading="loading"
      :pagination="pagination"
      :sort="sort"
      :table-error="error"
      resource-key="activity-log"
      resource-label-singular="activiteit"
      resource-label-plural="activiteiten"
      server-mode
      persist-to-server
      infinite-scroll
      scroll-height="60vh"
      @update:state="onState"
      @update:sort="onSort"
      @load-more="onLoadMore"
    >
      <template #toolbar-title>
        <BaseTitle :level="1" class="m-0">Activiteitenlogboek</BaseTitle>
      </template>
      <template #cell-event="{ row }">
        <span
          :class="actionBadgeClass(row)"
          class="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium"
        >
          {{ getEventLabelNl(row.event) }}
        </span>
      </template>
      <template #cell-created_at="{ row }">
        <span v-tooltip="fullTimestamp(row.created_at)" class="cursor-default">
          {{ relativeTime(row.created_at) }}
        </span>
      </template>
      <template #cell-description="{ row, value }">
        <span
          v-tooltip="row.description"
          class="block truncate text-surface-700 dark:text-surface-300"
        >
          {{ truncate(value, 80) }}
        </span>
      </template>
      <template #cell-user_label="{ value }">
        <div class="flex items-center gap-2">
          <BaseUserIcon :name="value ?? ''" size="sm" class="shrink-0" />
        </div>
      </template>
      <template #cell-subject_label="{ value }">
        <span class="text-surface-700 dark:text-surface-300">
          {{ capitalizeFirst(value) }}
        </span>
      </template>
    </B2CDataTable>
  </BaseIndex>
</template>

<style scoped></style>
