<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'
import { useDisplay, useTheme } from 'vuetify'
import { useRoute, useRouter } from 'vue-router'

import iconImage from '@/assets/images/icon.svg'
import { Visibility, routes } from '@/plugins/routesLayout'

const display = useDisplay()
const theme = useTheme()
const route = useRoute()
const router = useRouter()
const showDrawer = ref(true)
const currentYear = new Date().getFullYear()
const themeStorageKey = 'theme'

function normalizeRoutePath(path: string) {
  if (!path || path === '/') {
    return '/'
  }

  return path.endsWith('/') ? path.slice(0, -1) : path
}

function isWithinRoutePath(currentPath: string, targetPath: string) {
  const normalizedCurrentPath = normalizeRoutePath(currentPath)
  const normalizedTargetPath = normalizeRoutePath(targetPath)

  if (normalizedTargetPath === '/') {
    return normalizedCurrentPath === '/'
  }

  return (
    normalizedCurrentPath === normalizedTargetPath ||
    normalizedCurrentPath.startsWith(`${normalizedTargetPath}/`)
  )
}

function resolveVisibilityRoutes(path: string, visibilityRoute?: string | string[]) {
  if (Array.isArray(visibilityRoute)) {
    return visibilityRoute.map((entry) => entry.trim()).filter((entry) => entry.length > 0)
  }

  const normalizedVisibilityRoute = visibilityRoute?.trim()
  if (normalizedVisibilityRoute && normalizedVisibilityRoute.length > 0) {
    return [normalizedVisibilityRoute]
  }

  return [path]
}

const sidebarRoutes = computed(() =>
  routes.filter((item) => {
    if (item.visible === Visibility.Public) {
      return true
    }

    if (item.visible !== Visibility.Route) {
      return false
    }

    return resolveVisibilityRoutes(item.path, item.visibilityRoute).some((targetPath) =>
      isWithinRoutePath(route.path, targetPath),
    )
  }),
)
const footerRoutes = computed(() => routes.filter((x) => x.visible === Visibility.Footer))

const activeRoute = computed(() => {
  const byName = routes.find((x) => x.meta?.name === route.name)
  if (byName) {
    return byName
  }

  return routes.find((x) => x.path === route.path)
})

const pageName = computed(() => activeRoute.value?.name ?? 'Hoard')
const pageDescription = computed(
  () => activeRoute.value?.description ?? 'Self-hosted Dateiablage im Browser',
)
const shouldShowFooter = computed(() => activeRoute.value?.disableFooter !== true)
const isDarkTheme = computed(() => theme.global.name.value === 'dark')
const themeIcon = computed(() => (isDarkTheme.value ? 'mdi-white-balance-sunny' : 'mdi-weather-night'))
const themeLabel = computed(() =>
  isDarkTheme.value ? 'Hellen Modus aktivieren' : 'Dunklen Modus aktivieren',
)

function applyTheme(nextTheme: 'light' | 'dark', persist = true) {
  theme.global.name.value = nextTheme
  document.documentElement.setAttribute('data-theme', nextTheme)
  if (persist) {
    localStorage.setItem(themeStorageKey, nextTheme)
  }
}

function toggleDrawer() {
  showDrawer.value = !showDrawer.value
  localStorage.setItem('drawer', showDrawer.value ? 'Y' : 'N')
}

function toggleTheme() {
  applyTheme(isDarkTheme.value ? 'light' : 'dark')
}

function changeWebsiteTitle() {
  if (activeRoute.value) {
    document.title = `Hoard | ${activeRoute.value.name}`
    return
  }

  document.title = 'Hoard'
}

onMounted(() => {
  const storedTheme = localStorage.getItem(themeStorageKey)
  const validTheme = storedTheme === 'dark' || storedTheme === 'light' ? storedTheme : 'light'
  applyTheme(validTheme, false)

  const storedDrawer = localStorage.getItem('drawer')
  showDrawer.value = storedDrawer ? storedDrawer.startsWith('Y') : !display.mobile.value
})

watch(
  () => route.fullPath,
  () => {
    changeWebsiteTitle()
    if (display.mobile.value) {
      showDrawer.value = false
    }
  },
  { immediate: true },
)
</script>

<template>
  <v-app class="hoard-shell">
    <v-app-bar class="hoard-app-bar" elevation="0" height="64">
      <template #prepend>
        <v-app-bar-nav-icon
          v-tooltip="!showDrawer ? 'Menü öffnen' : 'Menü schließen'"
          @click="toggleDrawer()"
        />
      </template>

      <button type="button" class="brand-button" @click="router.push({ name: 'Home' })">
        <span class="brand-mark">
          <img :src="iconImage" alt="Hoard Icon" class="brand-logo" />
        </span>
        <span class="brand-text">
          <span class="brand-title">Hoard</span>
          <span class="brand-subtitle">Dateien zuerst</span>
        </span>
      </button>

      <v-divider vertical class="mx-3 topbar-context-divider" />

      <div class="page-context">
        <p class="page-name">{{ pageName }}</p>
        <p class="page-description">{{ pageDescription }}</p>
      </div>

      <v-spacer />

      <div class="topbar-actions">
        <v-tooltip location="bottom">
          <template #activator="{ props }">
            <v-btn
              icon
              :aria-label="themeLabel"
              v-bind="props"
              @click="toggleTheme"
            >
              <v-icon>{{ themeIcon }}</v-icon>
            </v-btn>
          </template>
          {{ themeLabel }}
        </v-tooltip>

        <v-tooltip v-if="!display.smAndDown.value" location="bottom">
          <template #activator="{ props }">
            <v-btn variant="outlined" prepend-icon="mdi-account-circle-outline" to="/login" v-bind="props">
              Konto
            </v-btn>
          </template>
          Zum Login
        </v-tooltip>

        <v-tooltip v-else location="bottom">
          <template #activator="{ props }">
            <v-btn icon to="/login" v-bind="props" aria-label="Zum Login">
              <v-icon>mdi-account-circle-outline</v-icon>
            </v-btn>
          </template>
          Zum Login
        </v-tooltip>
      </div>
    </v-app-bar>

    <v-navigation-drawer
      v-model="showDrawer"
      :class="['hoard-drawer', { 'hoard-drawer--mobile': display.mobile.value }]"
      :location="display.mobile.value ? 'bottom' : 'left'"
      :temporary="display.mobile.value"
      :permanent="!display.mobile.value"
      :width="268"
      :elevation="display.mobile.value ? 6 : 0"
    >
      <div class="drawer-top">
        <p class="drawer-kicker hoard-kicker hoard-kicker--xs">Navigation</p>
      </div>

      <v-list nav :density="display.mobile.value ? 'default' : 'comfortable'" class="px-1">
        <v-list-item
          v-for="item in sidebarRoutes"
          :key="item.path"
          :to="item.path"
          :active="route.path === item.path"
          :prepend-icon="item.icon"
          :title="item.name"
          class="hoard-nav-item"
          rounded="lg"
          link
        />
      </v-list>

      <template #append>
        <div class="drawer-bottom">
          <v-btn variant="text" prepend-icon="mdi-home" to="/" :block="display.mobile.value">
            Zur Startseite
          </v-btn>
        </div>
      </template>
    </v-navigation-drawer>

    <v-main class="hoard-main">
      <div class="main-shell">
        <router-view />
      </div>

      <v-footer
        v-if="shouldShowFooter"
        class="hoard-footer d-flex align-center justify-space-between ga-2 flex-wrap py-3"
      >
        <div class="footer-links">
          <v-btn
            v-for="link in footerRoutes"
            :key="link.path"
            :to="link.path"
            :text="link.name"
            variant="text"
            rounded
          />
        </div>
        <p class="footer-copy">{{ currentYear }} - <strong>Hoard</strong></p>
      </v-footer>
    </v-main>
  </v-app>
</template>

<style scoped>
.hoard-shell {
  min-height: 100vh;
}

.hoard-app-bar {
  padding-inline: var(--space-2);
}

.brand-button {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  padding: 0;
  border: none;
  color: inherit;
  background: transparent;
  cursor: pointer;
}

.brand-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.brand-logo {
  width: 46px;
  height: 46px;
  object-fit: contain;
}

.brand-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.1;
}

.brand-title {
  color: var(--color-text);
  font-size: 16px;
  font-weight: 700;
}

.brand-subtitle {
  color: var(--color-text-muted);
  font-size: var(--font-size-xs);
  font-weight: 500;
}

.page-context {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.topbar-context-divider {
  display: flex;
}

.topbar-actions {
  display: inline-flex;
  align-items: center;
  gap: 0;
}

.page-name,
.page-description,
.drawer-kicker,
.drawer-text,
.footer-copy {
  margin: 0;
}

.page-name {
  color: var(--color-text);
  font-size: var(--font-size-md);
  font-weight: 600;
}

.page-description {
  max-width: min(360px, 32vw);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (width <= 1360px) {
  .page-description {
    display: none;
  }

  .page-context {
    gap: 0;
  }
}

@media (width <= 1180px) {
  .topbar-context-divider {
    display: none;
  }
}

.hoard-drawer {
  padding-top: var(--space-2);
}

.hoard-drawer--mobile {
  border-top-left-radius: var(--radius-lg);
  border-top-right-radius: var(--radius-lg);
  max-height: min(72vh, 560px);
}

.drawer-top {
  padding: var(--space-2) var(--space-4) var(--space-4);
  border-bottom: 1px solid color-mix(in srgb, var(--color-border) 85%, white 15%);
}

.drawer-title {
  margin: var(--space-2) 0 var(--space-1);
  color: var(--color-text);
  font-size: var(--font-size-lg);
}

.drawer-text {
  color: var(--color-text-secondary);
  font-size: var(--font-size-sm);
}

.drawer-bottom {
  padding: var(--space-3) var(--space-2) var(--space-4);
  border-top: 1px solid color-mix(in srgb, var(--color-border) 90%, white 10%);
}

:deep(.hoard-nav-item) {
  min-height: 44px;
}

:deep(.hoard-nav-item .v-list-item-title) {
  font-weight: 500;
}

.hoard-main {
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - 64px);
}

.main-shell {
  flex: 1;
  padding: var(--space-6);
}

.hoard-footer {
  padding-inline: var(--space-6);
}

.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

.footer-copy {
  color: var(--color-text-secondary);
  font-size: var(--font-size-sm);
}

@media (width <= 960px) {
  .hoard-app-bar {
    padding-inline:
      max(var(--space-1), env(safe-area-inset-left))
      max(var(--space-1), env(safe-area-inset-right));
  }

  .brand-button {
    min-width: 0;
    gap: var(--space-2);
  }

  .brand-logo {
    width: 40px;
    height: 40px;
  }

  .brand-title {
    font-size: 15px;
  }

  .topbar-actions {
    gap: 2px;
  }

  .topbar-context-divider,
  .page-context {
    display: none;
  }

  .hoard-drawer {
    padding-top: var(--space-1);
  }

  .drawer-top {
    padding: var(--space-3) var(--space-4);
  }

  .drawer-bottom {
    padding: var(--space-2) var(--space-3) calc(var(--space-3) + env(safe-area-inset-bottom));
  }

  :deep(.drawer-bottom .v-btn) {
    min-height: 44px;
  }

  .main-shell {
    padding: var(--space-4);
  }

  .brand-subtitle {
    display: none;
  }

  .hoard-footer {
    justify-content: center !important;
    gap: var(--space-2);
    padding-inline:
      max(var(--space-2), env(safe-area-inset-left))
      max(var(--space-2), env(safe-area-inset-right));
  }

  .footer-links {
    width: 100%;
    justify-content: center;
    gap: var(--space-2);
  }
}

@media (width <= 600px) {
  .main-shell {
    padding: var(--space-3);
  }

  .brand-title {
    font-size: var(--font-size-md);
  }

  .footer-links {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  }

  :deep(.footer-links .v-btn) {
    width: 100%;
    min-height: 44px;
  }
}
</style>
