<script setup>
import BaseAlert from "../../components/base/BaseAlert.vue";
import BaseButton from "../../components/base/BaseButton.vue";
import BaseCheckbox from "../../components/base/BaseCheckbox.vue";
import BaseSelect from "../../components/base/BaseSelect.vue";
import draggable from "vuedraggable/src/vuedraggable.js";
import { useBaseToast } from "../../composables/useBaseToast.js";
import {
  deleteDatatableColumnDefaults,
  fetchDatatableColumnDefaults,
  fetchSuperadminUsersMinimal,
  postUserTableStateReset,
  putDatatableColumnDefaults,
} from "../../services/superadminDataTableSettingsService.js";
import { computed, onMounted, ref, watch } from "vue";

const toast = useBaseToast();

const loading = ref(false);
const error = ref("");
/** @type {import('vue').Ref<Array<{ resourceKey: string, tableKey: string, visibleKeys: string[] | null, columns: Array<{ key: string, header: string, defaultVisible?: boolean }> }>>} */
const resources = ref([]);

const selectedResourceKey = ref("");
/**
 * All columns in order; drag reorders. `visible` drives checkboxes; save sends
 * visible keys in this order.
 * @type {import('vue').Ref<Array<{ key: string, header: string, visible: boolean }>>}
 */
const workingColumnRows = ref([]);

const savingDefaults = ref(false);
const resettingDefaults = ref(false);

/** @type {import('vue').Ref<Array<{ id: number, name: string, email: string }>>} */
const users = ref([]);
const selectedUserId = ref(null);
/** @type {import('vue').Ref<string>} */
const selectedResetTableKey = ref("");
const resettingUserState = ref(false);

const RESOURCE_OPTIONS = computed(() =>
  resources.value.map((r) => ({
    label: resourceLabel(r.resourceKey),
    value: r.resourceKey,
  })),
);

/** Same labels as “Datatabel”; values are B2C `table-key` for user_table_states. */
const RESET_TABLE_OPTIONS = computed(() =>
  resources.value.map((r) => ({
    label: resourceLabel(r.resourceKey),
    value: r.tableKey || fallbackTableKey(r.resourceKey),
  })),
);

const USER_OPTIONS = computed(() =>
  users.value.map((u) => ({
    label: `${u.name} (${u.email})`,
    value: u.id,
  })),
);

function resourceLabel(key) {
  const labels = {
    users: "Gebruikers",
    roles: "Rollen",
    "activity-log": "Activiteitenlogboek",
    customers: "Klanten",
    offers: "Offertes",
    invoices: "Facturen",
  };
  return labels[key] ?? key;
}

/** Align with backend {@see DataTableColumnCatalog::tableStateKeyForResource} if API omits `tableKey`. */
function fallbackTableKey(resourceKey) {
  const m = {
    users: "settings.users",
    roles: "settings.roles",
    "activity-log": "settings.activity-log",
    customers: "customers.index",
    offers: "offers.index",
    invoices: "invoices.index",
  };
  return m[resourceKey] ?? `${resourceKey}.index`;
}

const currentResource = computed(() =>
  resources.value.find((r) => r.resourceKey === selectedResourceKey.value),
);

function syncWorkingColumnRowsFromResource() {
  const r = currentResource.value;
  if (!r?.columns?.length) {
    workingColumnRows.value = [];
    return;
  }
  workingColumnRows.value = r.columns.map((c) => ({
    key: c.key,
    header: c.header ?? c.key,
    visible: c.defaultVisible !== false,
  }));
}

watch(selectedResourceKey, (rk) => {
  syncWorkingColumnRowsFromResource();
  const r = resources.value.find((x) => x.resourceKey === rk);
  const tk = r?.tableKey || fallbackTableKey(rk);
  if (tk && selectedResetTableKey.value !== tk) {
    selectedResetTableKey.value = tk;
  }
});

watch(selectedResetTableKey, (tk) => {
  const r = resources.value.find(
    (x) => x.tableKey === tk || fallbackTableKey(x.resourceKey) === tk,
  );
  if (r?.resourceKey && selectedResourceKey.value !== r.resourceKey) {
    selectedResourceKey.value = r.resourceKey;
  }
});

async function load() {
  loading.value = true;
  error.value = "";
  try {
    const data = await fetchDatatableColumnDefaults();
    resources.value = Array.isArray(data?.resources) ? data.resources : [];
    if (resources.value.length > 0) {
      const stillValid = resources.value.some(
        (r) => r.resourceKey === selectedResourceKey.value,
      );
      if (!selectedResourceKey.value || !stillValid) {
        selectedResourceKey.value = resources.value[0].resourceKey;
      }
      const cur = resources.value.find(
        (r) => r.resourceKey === selectedResourceKey.value,
      );
      selectedResetTableKey.value =
        cur?.tableKey || fallbackTableKey(selectedResourceKey.value);
    } else {
      selectedResourceKey.value = "";
      selectedResetTableKey.value = "";
    }
    syncWorkingColumnRowsFromResource();
  } catch (e) {
    error.value =
      e?.response?.data?.message ??
      "Kon tabelinstellingen niet laden (rechten?).";
    resources.value = [];
  } finally {
    loading.value = false;
  }
}

async function loadUsers() {
  try {
    const data = await fetchSuperadminUsersMinimal();
    users.value = Array.isArray(data?.data) ? data.data : [];
  } catch {
    users.value = [];
  }
}

function setRowVisible(key, visible) {
  const row = workingColumnRows.value.find((r) => r.key === key);
  if (!row) return;
  if (!visible) {
    const n = workingColumnRows.value.filter((r) => r.visible).length;
    if (n <= 1) {
      toast.add({
        severity: "warn",
        summary: "Minimaal één kolom",
        detail: "Laat minstens één kolom zichtbaar.",
        life: 4000,
      });
      return;
    }
  }
  row.visible = !!visible;
}

async function saveDefaults() {
  if (!selectedResourceKey.value) return;
  const keys = workingColumnRows.value
    .filter((r) => r.visible)
    .map((r) => r.key);
  if (keys.length === 0) {
    toast.add({
      severity: "warn",
      summary: "Geen kolommen",
      detail: "Kies minstens één zichtbare kolom.",
      life: 4000,
    });
    return;
  }
  savingDefaults.value = true;
  try {
    await putDatatableColumnDefaults(selectedResourceKey.value, keys);
    toast.add({
      severity: "success",
      summary: "Opgeslagen",
      detail: "Standaardkolommen zijn bijgewerkt.",
      life: 3000,
    });
    await load();
  } catch (e) {
    toast.add({
      severity: "error",
      summary: "Opslaan mislukt",
      detail: e?.response?.data?.message ?? "Probeer opnieuw.",
      life: 5000,
    });
  } finally {
    savingDefaults.value = false;
  }
}

async function revertDefaultsToCode() {
  if (!selectedResourceKey.value) return;
  resettingDefaults.value = true;
  try {
    await deleteDatatableColumnDefaults(selectedResourceKey.value);
    toast.add({
      severity: "success",
      summary: "Teruggezet",
      detail: "Deployment gebruikt weer de kolommen zoals in code.",
      life: 3000,
    });
    await load();
  } catch (e) {
    toast.add({
      severity: "error",
      summary: "Mislukt",
      detail: e?.response?.data?.message ?? "Probeer opnieuw.",
      life: 5000,
    });
  } finally {
    resettingDefaults.value = false;
  }
}

async function resetUserTableState() {
  if (selectedUserId.value == null || !selectedResetTableKey.value) {
    toast.add({
      severity: "warn",
      summary: "Maak een keuze",
      detail: "Selecteer een gebruiker en een tabel.",
      life: 4000,
    });
    return;
  }
  resettingUserState.value = true;
  try {
    await postUserTableStateReset(
      Number(selectedUserId.value),
      selectedResetTableKey.value,
    );
    toast.add({
      severity: "success",
      summary: "Teruggezet",
      detail: "Opgeslagen tabelweergave voor deze gebruiker is gewist.",
      life: 4000,
    });
  } catch (e) {
    toast.add({
      severity: "error",
      summary: "Reset mislukt",
      detail: e?.response?.data?.message ?? "Probeer opnieuw.",
      life: 5000,
    });
  } finally {
    resettingUserState.value = false;
  }
}

onMounted(async () => {
  await load();
  await loadUsers();
});
</script>

<template>
  <div class="flex flex-col gap-8 w-full min-w-0">
    <div>
      <h1 class="text-2xl font-semibold text-surface-900 dark:text-surface-0 mb-1">
        Tabellen
      </h1>
      <p class="text-surface-600 dark:text-surface-400 text-sm">
        Standaard zichtbare kolommen per datatabel (deployment-breed) en een
        gebruiker terugzetten naar die standaard (opgeslagen weergave wissen).
      </p>
    </div>

    <BaseAlert v-if="error" severity="error" class="w-full">
      {{ error }}
    </BaseAlert>

    <section
      class="rounded-xl border border-surface-200 dark:border-surface-700 bg-surface-0 dark:bg-surface-950 p-5 space-y-4"
    >
      <h2 class="text-lg font-medium text-surface-900 dark:text-surface-0">
        Standaardkolommen
      </h2>
      <p class="text-sm text-surface-600 dark:text-surface-400">
        Sleep om de volgorde te wijzigen. Vink uit om een kolom standaard te
        verbergen. Dit geldt voor nieuwe sessies en na &quot;kolommen
        resetten&quot; zonder eigen opgeslagen staat.
      </p>

      <BaseSelect
        v-model="selectedResourceKey"
        label="Datatabel"
        :options="RESOURCE_OPTIONS"
        option-label="label"
        option-value="value"
        placeholder="Kies een tabel"
        :disabled="loading || RESOURCE_OPTIONS.length === 0"
      />

      <div v-if="loading" class="text-sm text-surface-500">Laden…</div>

      <template v-else-if="currentResource">
        <draggable
          v-model="workingColumnRows"
          handle=".datatable-defaults-drag-handle"
          item-key="key"
          tag="div"
          class="flex flex-col gap-2 min-h-[2rem]"
          :animation="180"
        >
          <template #item="{ element: row }">
            <div
              class="flex items-center gap-3 rounded-lg border border-surface-200 dark:border-surface-700 px-3 py-2 bg-surface-50 dark:bg-surface-900/40"
            >
              <span
                class="datatable-defaults-drag-handle cursor-grab text-surface-400 select-none"
                aria-hidden="true"
              >
                ::
              </span>
              <BaseCheckbox
                :model-value="row.visible"
                binary
                :input-id="`col-vis-${row.key}`"
                @update:model-value="(v) => setRowVisible(row.key, !!v)"
              />
              <label
                class="flex-1 text-sm text-surface-800 dark:text-surface-100 cursor-pointer"
                :for="`col-vis-${row.key}`"
              >
                {{ row.header }}
                <span class="text-surface-400 text-xs ml-2">{{ row.key }}</span>
              </label>
            </div>
          </template>
        </draggable>

        <div class="flex flex-wrap gap-3 pt-2">
          <BaseButton
            label="Standaardkolommen opslaan"
            :loading="savingDefaults"
            :disabled="savingDefaults"
            @click="saveDefaults"
          />
          <BaseButton
            label="Terug naar codedefaults"
            severity="secondary"
            :loading="resettingDefaults"
            :disabled="resettingDefaults"
            @click="revertDefaultsToCode"
          />
        </div>
      </template>
    </section>

    <section
      class="rounded-xl border border-surface-200 dark:border-surface-700 bg-surface-0 dark:bg-surface-950 p-5 space-y-4"
    >
      <h2 class="text-lg font-medium text-surface-900 dark:text-surface-0">
        Gebruiker terugzetten
      </h2>
      <p class="text-sm text-surface-600 dark:text-surface-400">
        Wist de opgeslagen tabelweergave (kolommen, filters, zoekveld) voor één
        gebruiker. Bij volgende bezoek gelden de deployment-standaards weer.
      </p>

      <BaseSelect
        v-model="selectedUserId"
        label="Gebruiker"
        :options="USER_OPTIONS"
        option-label="label"
        option-value="value"
        placeholder="Kies gebruiker"
        filter
        show-clear
      />

      <BaseSelect
        v-model="selectedResetTableKey"
        label="Tabel"
        :options="RESET_TABLE_OPTIONS"
        option-label="label"
        option-value="value"
        placeholder="Kies een tabel"
        :disabled="RESET_TABLE_OPTIONS.length === 0"
      />

      <BaseButton
        label="Opgeslagen weergave wissen"
        severity="danger"
        :loading="resettingUserState"
        :disabled="resettingUserState || selectedUserId == null"
        @click="resetUserTableState"
      />
    </section>
  </div>
</template>
