<script setup>
import BaseAlert from "../../components/base/BaseAlert.vue";
import BaseButton from "../../components/base/BaseButton.vue";
import BaseTag from "../../components/base/BaseTag.vue";
import BaseToggleSwitch from "../../components/base/BaseToggleSwitch.vue";
import { useBaseToast } from "../../composables/useBaseToast.js";
import { onMounted, reactive, ref } from "vue";

import { hydrateUser } from "../../composables/useAuth.js";
import { api, ensureCsrf } from "../../services/api.js";

const toast = useBaseToast();

const loading = ref(false);
const updatingInstallSlug = ref("");
const updatingRuntimeSlug = ref("");
const error = ref("");
const checkedAt = ref("");
const modules = ref([]);
/** @type {Record<string, boolean>} */
const expanded = reactive({});

const SIGNAL_LABELS = {
  config: "Config",
  database: "Database",
  seeder: "Seeder",
  routes: "Routes",
};

const SIGNAL_KEYS = ["config", "database", "seeder", "routes"];

async function load() {
  loading.value = true;
  error.value = "";
  try {
    await ensureCsrf();
    const { data } = await api.get("/api/superadmin/modules");
    checkedAt.value = data?.checked_at ?? "";
    modules.value = Array.isArray(data?.modules) ? data.modules : [];
    for (const mod of modules.value) {
      if (!(mod.slug in expanded)) {
        expanded[mod.slug] = Boolean(mod.is_install_enabled);
      }
    }
  } catch (e) {
    error.value =
      e?.response?.data?.message ?? "Kon modules niet laden (geen toestemming?).";
    modules.value = [];
  } finally {
    loading.value = false;
  }
}

function toggleDetail(slug) {
  expanded[slug] = !expanded[slug];
}

async function activate(mod) {
  updatingRuntimeSlug.value = mod.slug;
  error.value = "";
  try {
    await ensureCsrf();
    const { data } = await api.patch(`/api/superadmin/modules/${mod.slug}/runtime`, {
      is_enabled: true,
    });
    mod.is_runtime_enabled = true;
    mod.is_enabled = true;
    mod.is_install_enabled = Boolean(data?.data?.is_install_enabled ?? mod.is_install_enabled);
    mod.install_locked = Boolean(data?.data?.install_locked ?? mod.install_locked);
    await hydrateUser();
    toast.add({
      severity: "success",
      summary: "Module ingeschakeld",
      detail: `${mod.label} is nu zichtbaar voor gebruikers.`,
      life: 3000,
    });
    await load();
  } catch (e) {
    const msg =
      e?.response?.data?.message ?? "Inschakelen mislukt. Probeer opnieuw.";
    error.value = msg;
    toast.add({ severity: "error", summary: "Inschakelen mislukt", detail: msg, life: 5000 });
  } finally {
    updatingRuntimeSlug.value = "";
  }
}

async function setInstall(mod, nextValue) {
  if (!nextValue && isInstallLocked(mod)) return;

  updatingInstallSlug.value = mod.slug;
  error.value = "";
  try {
    await ensureCsrf();
    const { data } = await api.patch(`/api/superadmin/modules/${mod.slug}/installation`, {
      is_enabled: nextValue,
    });
    mod.is_install_enabled = Boolean(data?.data?.is_install_enabled);
    mod.install_locked = Boolean(data?.data?.install_locked);

    if (nextValue) {
      expanded[mod.slug] = true;
      toast.add({
        severity: "success",
        summary: "Installatie voorbereid",
        detail: `Draai nu migraties en seeders voor ${mod.label}.`,
        life: 3500,
      });
    } else {
      expanded[mod.slug] = false;
      mod.is_runtime_enabled = false;
      mod.is_enabled = false;
      await hydrateUser();
      toast.add({
        severity: "success",
        summary: "Installatie uitgezet",
        detail: `${mod.label} installatietoggle staat uit.`,
        life: 3000,
      });
    }

    await load();
  } catch (e) {
    const msg = e?.response?.data?.message ?? "Installatietoggle bijwerken mislukt.";
    error.value = msg;
    toast.add({
      severity: "error",
      summary: "Installatietoggle mislukt",
      detail: msg,
      life: 5000,
    });
  } finally {
    updatingInstallSlug.value = "";
  }
}

async function setRuntime(mod, nextValue) {
  updatingRuntimeSlug.value = mod.slug;
  error.value = "";
  try {
    await ensureCsrf();
    const { data } = await api.patch(`/api/superadmin/modules/${mod.slug}/runtime`, {
      is_enabled: nextValue,
    });
    mod.is_runtime_enabled = Boolean(data?.data?.is_runtime_enabled);
    mod.is_enabled = mod.is_runtime_enabled;
    await hydrateUser();

    toast.add({
      severity: "success",
      summary: nextValue ? "Module ingeschakeld" : "Module verborgen",
      detail: nextValue
        ? `${mod.label} is actief voor gebruikers met rechten.`
        : `${mod.label} blijft geinstalleerd maar is nu verborgen.`,
      life: 3200,
    });
    await load();
  } catch (e) {
    const msg = e?.response?.data?.message ?? "Runtime toggle bijwerken mislukt.";
    error.value = msg;
    toast.add({
      severity: "error",
      summary: "Runtime toggle mislukt",
      detail: msg,
      life: 5000,
    });
  } finally {
    updatingRuntimeSlug.value = "";
  }
}

async function copyText(text) {
  try {
    await navigator.clipboard.writeText(text);
    toast.add({
      severity: "success",
      summary: "Gekopieerd",
      detail: "Commando gekopieerd.",
      life: 2000,
    });
  } catch {
    toast.add({
      severity: "error",
      summary: "Kopiëren mislukt",
      detail: "Klembord niet beschikbaar.",
      life: 4000,
    });
  }
}

function signalClass(status) {
  if (status === "ok") return "bg-green-500";
  if (status === "warn") return "bg-amber-400";
  return "bg-red-500";
}

function signalSeverity(status) {
  if (status === "ok") return "success";
  if (status === "warn") return "warn";
  return "danger";
}

function signalLabel(status) {
  if (status === "ok") return "OK";
  if (status === "warn") return "Let op";
  return "Fout";
}

function overallSeverity(overall) {
  return signalSeverity(overall ?? "fail");
}

function overallLabel(overall) {
  if (overall === "ok") return "Klaar om te activeren";
  if (overall === "warn") return "Aandacht nodig";
  return "Geblokkeerd";
}

function migrationStatus(mod) {
  return mod.health?.database?.status ?? "fail";
}

function seederStatus(mod) {
  return mod.health?.seeder?.status ?? "fail";
}

function isInstallLocked(mod) {
  return Boolean(mod.install_locked) || migrationStatus(mod) === "ok";
}

function canEnableRuntime(mod) {
  return (
    Boolean(mod.is_install_enabled) &&
    mod.health?.config?.status === "ok" &&
    migrationStatus(mod) === "ok" &&
    seederStatus(mod) === "ok"
  );
}

function canActivate(mod) {
  return !mod.is_runtime_enabled && canEnableRuntime(mod);
}

onMounted(load);
</script>

<template>
  <div>
    <div class="flex flex-wrap items-start justify-between gap-3 mb-6">
      <div>
        <h1 class="title-h5 mb-1">Modules</h1>
        <p class="body-small text-surface-600 dark:text-surface-400">
          Per module zijn er twee schakelaars: eerst installatie (migraties + seeders), daarna
          runtime (zichtbaar/toegankelijk in app). Na een uitgevoerde migratie blijft
          installatietoggle vast aan.
        </p>
      </div>
      <BaseButton
        label="Vernieuwen"
        icon="refresh"
        variant="secondary"
        outlined
        :loading="loading"
        @click="load"
      />
    </div>

    <BaseAlert v-if="error" severity="error" class="mb-6" :closable="false">
      {{ error }}
    </BaseAlert>

    <div
      v-if="!loading && modules.length === 0"
      class="text-center py-12 text-surface-500"
    >
      Geen modules gevonden. Voer migraties en seeders uit.
    </div>

    <div class="flex flex-col gap-4">
      <div
        v-for="mod in modules"
        :key="mod.slug"
        class="rounded-xl border overflow-hidden flex flex-col"
        :class="
          mod.is_runtime_enabled
            ? 'border-green-300 dark:border-green-800'
            : 'border-surface-200 dark:border-surface-700'
        "
      >
        <!-- Header: hoofdstatus + uitklappen -->
        <button
          type="button"
          class="w-full px-4 py-3 flex flex-wrap items-center justify-between gap-3 text-left transition-colors"
          :class="
            mod.is_runtime_enabled
              ? 'bg-green-50 dark:bg-green-950/30'
              : 'bg-surface-50 dark:bg-surface-900'
          "
          @click="toggleDetail(mod.slug)"
        >
          <div class="flex items-center gap-2 min-w-0">
            <span
              class="inline-flex h-2.5 w-2.5 rounded-full shrink-0"
              :class="signalClass(mod.health.overall)"
            />
            <span class="font-semibold text-surface-800 dark:text-surface-100 truncate">
              {{ mod.label }}
            </span>
          </div>
          <div class="flex items-center gap-2 shrink-0">
            <BaseTag
              v-if="mod.is_runtime_enabled"
              severity="success"
              value="Actief"
              class="text-xs"
            />
            <BaseTag
              v-else
              :severity="overallSeverity(mod.health.overall)"
              :value="overallLabel(mod.health.overall)"
              class="text-xs"
            />
            <i
              class="pi text-surface-500"
              :class="expanded[mod.slug] ? 'pi-chevron-up' : 'pi-chevron-down'"
            />
          </div>
        </button>

        <div
          class="px-4 py-3 border-t border-surface-100 dark:border-surface-800 bg-surface-0 dark:bg-surface-950/30"
        >
          <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div class="rounded-lg border border-surface-200 dark:border-surface-700 p-3">
              <div class="flex items-center justify-between gap-3">
                <div class="min-w-0">
                  <p class="text-sm font-medium text-surface-800 dark:text-surface-100">
                    Installatie
                  </p>
                  <p class="text-xs text-surface-500 dark:text-surface-400">
                    Zet aan om module-migraties en seeders toe te laten.
                  </p>
                </div>
                <BaseToggleSwitch
                  :model-value="Boolean(mod.is_install_enabled)"
                  :disabled="updatingInstallSlug === mod.slug || (isInstallLocked(mod) && mod.is_install_enabled)"
                  @update:model-value="setInstall(mod, $event)"
                />
              </div>
              <p
                v-if="isInstallLocked(mod) && mod.is_install_enabled"
                class="text-xs text-amber-600 dark:text-amber-400 mt-2"
              >
                Installatietoggle staat vast omdat migraties al zijn uitgevoerd.
              </p>
            </div>

            <div class="rounded-lg border border-surface-200 dark:border-surface-700 p-3">
              <div class="flex items-center justify-between gap-3">
                <div class="min-w-0">
                  <p class="text-sm font-medium text-surface-800 dark:text-surface-100">
                    Runtime
                  </p>
                  <p class="text-xs text-surface-500 dark:text-surface-400">
                    Schakelt navigatie/API toegang voor gebruikers.
                  </p>
                </div>
                <BaseToggleSwitch
                  :model-value="Boolean(mod.is_runtime_enabled)"
                  :disabled="
                    updatingRuntimeSlug === mod.slug ||
                    (!mod.is_runtime_enabled && !canEnableRuntime(mod))
                  "
                  @update:model-value="setRuntime(mod, $event)"
                />
              </div>
              <p
                v-if="!mod.is_runtime_enabled && !canEnableRuntime(mod)"
                class="text-xs text-surface-500 dark:text-surface-400 mt-2"
              >
                Runtime kan pas aan wanneer Config, Migration en Seeder groen zijn.
              </p>
            </div>
          </div>
        </div>

        <!-- Afhankelijkheden -->
        <div
          v-if="mod.dependencies.length || mod.dependents.length"
          class="px-4 py-2 border-t border-surface-100 dark:border-surface-800 flex flex-wrap gap-x-4 gap-y-1 bg-surface-0 dark:bg-surface-950/30"
        >
          <span
            v-if="mod.dependencies.length"
            class="text-xs text-surface-500 dark:text-surface-400"
          >
            Vereist:
            <span
              v-for="dep in mod.dependencies"
              :key="dep"
              class="font-medium text-surface-700 dark:text-surface-300"
            >
              {{ dep }}
            </span>
          </span>
          <span
            v-if="mod.dependents.length"
            class="text-xs text-surface-400 dark:text-surface-500"
          >
            Gebruikt door:
            <template v-for="(dep, i) in mod.dependents" :key="dep">
              <span v-if="i > 0">, </span>
              <span class="font-medium">{{ dep }}</span>
            </template>
          </span>
        </div>

        <!-- Uitklap: elk signaal + commando's -->
        <div
          v-show="expanded[mod.slug]"
          class="px-4 py-4 border-t border-surface-100 dark:border-surface-800 space-y-3 bg-surface-0 dark:bg-surface-900"
        >
          <div
            v-for="key in SIGNAL_KEYS"
            :key="key"
            class="rounded-lg border border-surface-100 dark:border-surface-800 bg-surface-50/90 dark:bg-surface-950/50 px-3 py-2.5"
          >
            <div class="flex flex-wrap items-center gap-2 mb-1">
              <span
                class="inline-flex h-2 w-2 rounded-full shrink-0"
                :class="signalClass(mod.health[key]?.status)"
              />
              <span class="text-sm font-medium text-surface-800 dark:text-surface-100">
                {{ SIGNAL_LABELS[key] }}
              </span>
              <BaseTag
                :severity="signalSeverity(mod.health[key]?.status)"
                :value="signalLabel(mod.health[key]?.status)"
                class="text-xs"
              />
            </div>
            <p class="text-xs text-surface-600 dark:text-surface-400 ml-4 mb-1">
              {{ mod.health[key]?.detail }}
            </p>
            <div
              v-if="mod.health[key]?.commands?.length"
              class="ml-4 mt-2 flex flex-col gap-2"
            >
              <div
                v-for="cmd in mod.health[key].commands"
                :key="cmd"
                class="flex items-start gap-1 max-w-full"
              >
                <code
                  class="text-xs px-2 py-1.5 rounded bg-surface-100 dark:bg-surface-800 break-all flex-1 min-w-0"
                >
                  {{ cmd }}
                </code>
                <BaseButton
                  variant="secondary"
                  icon="copy"
                  text
                  rounded
                  size="small"
                  class="shrink-0"
                  :icon-only="true"
                  v-tooltip.bottom="'Kopiëren'"
                  @click="copyText(cmd)"
                />
              </div>
            </div>
          </div>
        </div>

        <div class="px-4 py-2.5 border-t border-surface-100 dark:border-surface-800 bg-surface-50/30 dark:bg-surface-950/20">
          <div class="flex flex-wrap items-center gap-2">
            <BaseTag
              :severity="signalSeverity(migrationStatus(mod))"
              :value="`Migration: ${signalLabel(migrationStatus(mod))}`"
              class="text-xs"
            />
            <BaseTag
              :severity="signalSeverity(seederStatus(mod))"
              :value="`Seeder: ${signalLabel(seederStatus(mod))}`"
              class="text-xs"
            />
            <BaseTag
              :severity="mod.is_runtime_enabled ? 'success' : 'contrast'"
              :value="mod.is_runtime_enabled ? 'Runtime: Aan' : 'Runtime: Uit'"
              class="text-xs"
            />
            <BaseButton
              v-if="canActivate(mod)"
              label="Runtime nu inschakelen"
              icon="check-circle"
              variant="secondary"
              outlined
              size="small"
              :loading="updatingRuntimeSlug === mod.slug"
              :disabled="updatingRuntimeSlug === mod.slug"
              @click="activate(mod)"
            />
          </div>
        </div>
      </div>
    </div>

    <p v-if="checkedAt && !loading" class="text-xs text-surface-400 mt-6">
      Laatst gecontroleerd {{ checkedAt }}
    </p>
  </div>
</template>
