<script setup>
import { onMounted, onBeforeUnmount, computed, ref, watch } from "vue";
import { RouterView, RouterLink, useRouter, useRoute } from "vue-router";
import { state, isAuthenticated, logout, refreshProfile } from "./auth";
import { prefs, applyProfilePrefs } from "./prefs";
import { servers } from "./servers";
import { api } from "./api";
import { t } from "./i18n";
import Logo from "./components/Logo.vue";
import ConfirmDialog from "./components/ConfirmDialog.vue";
import ServerSwitcher from "./components/ServerSwitcher.vue";

const router = useRouter();
const route = useRoute();

function onLogout() {
  logout();
  router.replace({ name: "login" });
}

// Effective dark state, kept reactive by observing the <html> class (prefs.js
// toggles `.dark` there, incl. on system-scheme changes).
const isDark = ref(document.documentElement.classList.contains("dark"));
let themeObserver = null;

// Global theme toggle (light ⇄ dark). Applies instantly and persists to the
// profile, mirroring what Settings › Appearance does.
function toggleTheme() {
  const next = isDark.value ? "light" : "dark";
  applyProfilePrefs({ ...prefs, theme: next });
  if (isAuthenticated.value) api.updateMe({ theme: next }).catch(() => {});
}

// Drag lock (on ⇄ off), the same shape as the theme toggle: applies instantly
// and persists to the profile, so a locked account stays locked on the next
// device. It holds every arrangement still — the garage, a car's tabs, its
// Information rows, the provider's readings — which is a guard against nudging
// a layout while reading it, not a permission: what a user may edit is
// unchanged.
function toggleDragLock() {
  const next = !prefs.dragLocked;
  prefs.dragLocked = next;
  if (isAuthenticated.value) api.updateMe({ dragLocked: next }).catch(() => {});
}

// Switching servers puts you in front of a different garage. Record ids belong
// to the server that issued them, so nothing on screen survives the change —
// hence back to the garage every time, and a keyed RouterView below so the view
// remounts and re-fetches even when the route itself doesn't change.
watch(
  () => servers.activeId,
  () => {
    if (route.name !== "login") router.replace({ name: "dashboard" });
  }
);

const userInitial = computed(() =>
  (state.user?.name || state.user?.email || "?").charAt(0).toUpperCase()
);

// Sidebar nav. User management is a tab inside Settings, not a rail item.
const nav = computed(() => [
  { to: "/", label: t("nav.garage"), icon: "grid", exact: true },
  { to: "/charging", label: t("nav.charging"), icon: "bolt" },
  { to: "/settings", label: t("nav.settings"), icon: "gear" },
]);

function active(item) {
  return item.exact ? route.path === item.to : route.path.startsWith(item.to);
}

// Covers a page reload: the token survives in localStorage, but the richer
// profile (theme, etc.) is only ever kept in memory, so re-fetch it.
onMounted(() => {
  if (isAuthenticated.value && !state.profile) refreshProfile().catch(() => {});
  themeObserver = new MutationObserver(() => {
    isDark.value = document.documentElement.classList.contains("dark");
  });
  themeObserver.observe(document.documentElement, { attributes: true, attributeFilter: ["class"] });
});

onBeforeUnmount(() => themeObserver?.disconnect());
</script>

<template>
  <!-- Login page is full-screen and chromeless. -->
  <RouterView v-if="route.name === 'login'" />

  <!-- Outer page: a step off the app surface so the centered shell reads as a panel. -->
  <div v-else class="min-h-screen bg-sunken text-body">
   <div class="mx-auto flex min-h-screen max-w-[1368px] bg-page shadow-pop">
    <!-- Fixed dark app-shell rail -->
    <aside class="sticky top-0 flex h-screen w-16 flex-none flex-col gap-1 bg-brand-900 px-2 py-5 text-white md:w-60 md:px-4">
      <RouterLink to="/" class="mb-5 flex h-8 items-center px-1 md:px-2">
        <Logo on-dark icon-only class="h-7 md:hidden" />
        <Logo on-dark class="hidden h-7 md:flex" />
      </RouterLink>

      <nav class="flex flex-col gap-1">
        <RouterLink
          v-for="item in nav"
          :key="item.to"
          :to="item.to"
          class="flex items-center gap-3 rounded-control px-2.5 py-2.5 text-[15px] font-medium transition-colors md:px-3"
          :class="active(item)
            ? 'bg-brand-400/15 text-white'
            : 'text-white/60 hover:bg-white/5 hover:text-white'"
        >
          <!-- garage -->
          <svg v-if="item.icon === 'grid'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" class="h-5 w-5 shrink-0" :style="active(item) ? 'color:#60A5FA' : ''"><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></svg>
          <!-- charging -->
          <svg v-else-if="item.icon === 'bolt'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" class="h-5 w-5 shrink-0" :style="active(item) ? 'color:#60A5FA' : ''"><path stroke-linecap="round" stroke-linejoin="round" d="M13 2 4.5 13.5H11l-1 8.5 8.5-11.5H12z"/></svg>
          <!-- settings -->
          <svg v-else viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" class="h-5 w-5 shrink-0" :style="active(item) ? 'color:#60A5FA' : ''"><path stroke-linecap="round" stroke-linejoin="round" d="M9.6 3.6 9 6a7.5 7.5 0 0 0-1.7 1L5 6.3l-2 3.4 2 1.5a7.6 7.6 0 0 0 0 2l-2 1.5 2 3.4 2.3-.7c.5.4 1.1.8 1.7 1l.6 2.4h4l.6-2.4c.6-.2 1.2-.6 1.7-1l2.3.7 2-3.4-2-1.5a7.6 7.6 0 0 0 0-2l2-1.5-2-3.4-2.3.7A7.5 7.5 0 0 0 15 6l-.6-2.4z"/><circle cx="12" cy="12" r="2.6"/></svg>
          <span class="hidden md:inline">{{ item.label }}</span>
        </RouterLink>
      </nav>

      <!-- Footer: server + drag lock + theme toggle + user + logout -->
      <div class="mt-auto flex flex-col gap-2 border-t border-white/10 pt-3">
        <ServerSwitcher />

        <button
          class="flex items-center gap-3 rounded-control px-2.5 py-2 text-[15px] font-medium transition-colors hover:bg-white/5 hover:text-white md:px-3"
          :class="prefs.dragLocked ? 'text-white/80' : 'text-white/60'"
          :title="t('nav.dragLockHint')"
          @click="toggleDragLock"
        >
          <!-- closed padlock while locked, open one while things can be dragged -->
          <svg v-if="prefs.dragLocked" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" class="h-5 w-5 shrink-0"><rect x="4" y="10.5" width="16" height="10.5" rx="2"/><path stroke-linecap="round" d="M8 10.5V7a4 4 0 0 1 8 0v3.5"/></svg>
          <svg v-else viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" class="h-5 w-5 shrink-0"><rect x="4" y="10.5" width="16" height="10.5" rx="2"/><path stroke-linecap="round" d="M8 10.5V7a4 4 0 0 1 7.7-1.5"/></svg>
          <span class="hidden md:inline">{{ prefs.dragLocked ? t("nav.unlockDrag") : t("nav.lockDrag") }}</span>
        </button>

        <button
          class="flex items-center gap-3 rounded-control px-2.5 py-2 text-[15px] font-medium text-white/60 transition-colors hover:bg-white/5 hover:text-white md:px-3"
          @click="toggleTheme"
        >
          <svg v-if="isDark" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" class="h-5 w-5 shrink-0"><circle cx="12" cy="12" r="4"/><path stroke-linecap="round" d="M12 2v2m0 16v2M4.9 4.9l1.4 1.4m11.4 11.4 1.4 1.4M2 12h2m16 0h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>
          <svg v-else viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" class="h-5 w-5 shrink-0"><path stroke-linecap="round" stroke-linejoin="round" d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8Z"/></svg>
          <span class="hidden md:inline">{{ isDark ? t("nav.lightMode") : t("nav.darkMode") }}</span>
        </button>

        <div class="flex items-center gap-3 px-1 md:px-2">
          <div class="grid h-9 w-9 flex-none place-items-center rounded-full bg-brand-600 font-mono text-sm text-white">{{ userInitial }}</div>
          <div class="hidden min-w-0 flex-1 md:block">
            <p class="truncate text-sm text-white">{{ state.user?.name || state.user?.email }}</p>
            <p class="truncate font-mono text-[11px] text-white/50">{{ t("nav.signedIn") }}</p>
          </div>
          <button class="hidden text-white/50 transition-colors hover:text-white md:block" :title="t('nav.logOut')" @click="onLogout">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" class="h-5 w-5"><path stroke-linecap="round" stroke-linejoin="round" d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4M10 17l5-5-5-5M15 12H3"/></svg>
          </button>
        </div>
      </div>
    </aside>

    <!-- Main content -->
    <main class="min-w-0 flex-1 px-5 py-6 md:px-8 lg:px-10">
      <div class="mx-auto max-w-5xl">
        <RouterView :key="servers.activeId" />
      </div>
    </main>
   </div>
  </div>

  <!-- Asked from anywhere, drawn here, over everything. -->
  <ConfirmDialog />
</template>
