<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";
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, visibleKeys: string[] | null, columns: Array<{ key: string, header: string, defaultVisible?: boolean }> }>>} */
const resources = ref([]);

const selectedResourceKey = ref("");
/** @type {import('vue').Ref<string[]>} */
const workingVisibleKeys = 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);
const selectedResetTableKey = ref("settings.users");
const resettingUserState = ref(false);

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

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

const TABLE_RESET_OPTIONS = [
  {
    value: "settings.users",
    label: "Instellingen › Gebruikers",
  },
  {
    value: "settings.roles",
    label: "Instellingen › Rollen",
  },
  {
    value: "settings.activity-log",
    label: "Instellingen › Activiteitenlogboek",
  },
];

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

/** @param {string} k */
function columnKeyIdentity(k) {
  return k;
}

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

/** Keys currently hidden (not in visible ordered list) */
const hiddenColumnKeys = computed(() => {
  const r = currentResource.value;
  if (!r?.columns?.length) return [];
  const visible = new Set(workingVisibleKeys.value);
  return r.columns.map((c) => c.key).filter((k) => !visible.has(k));
});

function keyHeader(key) {
  const r = currentResource.value;
  const col = r?.columns?.find((c) => c.key === key);
  return col?.header ?? key;
}

function syncWorkingKeysFromResource() {
  const r = currentResource.value;
  if (!r?.columns?.length) {
    workingVisibleKeys.value = [];
    return;
  }
  const saved = r.visibleKeys;
  if (Array.isArray(saved) && saved.length > 0) {
    const allowed = new Set(r.columns.map((c) => c.key));
    workingVisibleKeys.value = saved.filter((k) => allowed.has(k));
    return;
  }
  workingVisibleKeys.value = r.columns
    .filter((c) => c.defaultVisible !== false)
    .map((c) => c.key);
}

watch(selectedResourceKey, () => {
  syncWorkingKeysFromResource();
});

async function load() {
  loading.value = true;
  error.value = "";
  try {
    const data = await fetchDatatableColumnDefaults();
    resources.value = Array.isArray(data?.resources) ? data.resources : [];
    if (
      !selectedResourceKey.value &&
      resources.value.length > 0 &&
      resources.value[0]
    ) {
      selectedResourceKey.value = resources.value[0].resourceKey;
    }
    syncWorkingKeysFromResource();
  } 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 setKeyVisible(key, visible) {
  if (visible) {
    if (!workingVisibleKeys.value.includes(key)) {
      workingVisibleKeys.value = [...workingVisibleKeys.value, key];
    }
    return;
  }
  if (workingVisibleKeys.value.length <= 1) {
    toast.add({
      severity: "warn",
      summary: "Minimaal één kolom",
      detail: "Laat minstens één kolom zichtbaar.",
      life: 4000,
    });
    return;
  }
  workingVisibleKeys.value = workingVisibleKeys.value.filter((k) => k !== key);
}

function addHiddenKey(key) {
  setKeyVisible(key, true);
}

async function saveDefaults() {
  if (!selectedResourceKey.value) return;
  if (workingVisibleKeys.value.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,
      [...workingVisibleKeys.value],
    );
    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 max-w-3xl">
    <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="workingVisibleKeys"
          handle=".datatable-defaults-drag-handle"
          :item-key="columnKeyIdentity"
          tag="div"
          class="flex flex-col gap-2 min-h-[2rem]"
          :animation="180"
        >
          <template #item="{ element: key }">
            <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="true"
                binary
                :input-id="`col-vis-${key}`"
                @update:model-value="(v) => setKeyVisible(key, !!v)"
              />
              <label
                class="flex-1 text-sm text-surface-800 dark:text-surface-100 cursor-pointer"
                :for="`col-vis-${key}`"
              >
                {{ keyHeader(key) }}
                <span class="text-surface-400 text-xs ml-2">{{ key }}</span>
              </label>
            </div>
          </template>
        </draggable>

        <div
          v-if="hiddenColumnKeys.length > 0"
          class="border-t border-surface-200 dark:border-surface-700 pt-4 space-y-2"
        >
          <p class="text-sm font-medium text-surface-700 dark:text-surface-200">
            Verborgen kolommen
          </p>
          <div class="flex flex-wrap gap-2">
            <BaseButton
              v-for="key in hiddenColumnKeys"
              :key="key"
              size="small"
              severity="secondary"
              :label="`Toon: ${keyHeader(key)}`"
              @click="addHiddenKey(key)"
            />
          </div>
        </div>

        <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="TABLE_RESET_OPTIONS"
        option-label="label"
        option-value="value"
      />

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