<template>
  <div class="app-shell">
    <aside class="app-sidebar">
      <RouterLink
        class="brand"
        :to="brandTarget"
      >
        <span class="brand-mark" />
        <span>
          <strong>{{ t('app.name') }}</strong>
          <small>OMS</small>
        </span>
      </RouterLink>

      <nav
        class="app-nav"
        :aria-label="t('app.navigationAria')"
      >
        <RouterLink
          v-for="item in navItems"
          :key="item.menu_code"
          :to="item.route_path"
          class="app-nav__item"
        >
          <i
            :class="item.icon_key || 'pi pi-circle'"
            aria-hidden="true"
          />
          <span>{{ menuLabel(item) }}</span>
        </RouterLink>
      </nav>
    </aside>

    <div class="app-main">
      <header class="app-topbar">
        <div>
          <strong>{{ pageTitle }}</strong>
          <small>{{ currentHotelLabel }}</small>
        </div>

        <div class="app-topbar__actions">
          <div
            v-if="authStore.isAuthenticated"
            class="auth-context"
          >
            <span class="user-chip">
              <i
                class="pi pi-user"
                aria-hidden="true"
              />
              {{ currentUserLabel }}
            </span>

            <label
              v-if="hotelSwitchable"
              class="hotel-select"
              :title="t('auth.currentHotel')"
            >
              <i
                class="pi pi-building"
                aria-hidden="true"
              />
              <select
                :value="authStore.selectedHotelId ?? ''"
                @change="changeHotel"
              >
                <option
                  v-for="hotel in authStore.hotels"
                  :key="hotel.hotel_id"
                  :value="hotel.hotel_id"
                >
                  {{ hotel.hotel_name || hotel.hotel_id }}
                </option>
              </select>
            </label>

            <span
              v-else
              class="hotel-chip"
            >
              <i
                class="pi pi-building"
                aria-hidden="true"
              />
              {{ currentHotelLabel }}
            </span>
          </div>

          <span
            class="health-pill"
            :class="`health-pill--${healthState}`"
          >
            <i
              class="pi pi-circle-fill"
              aria-hidden="true"
            />
            {{ healthLabel }}
          </span>

          <div
            class="locale-switch"
            :aria-label="t('app.language')"
          >
            <button
              v-for="option in localeOptions"
              :key="option.value"
              type="button"
              :class="{ active: locale === option.value }"
              @click="setLocale(option.value)"
            >
              {{ option.label }}
            </button>
          </div>

          <button
            type="button"
            class="theme-button"
            :title="t('app.theme')"
            @click="preferences.toggleTheme()"
          >
            <i
              class="pi pi-moon"
              aria-hidden="true"
            />
          </button>

          <button
            v-if="authStore.isAuthenticated"
            type="button"
            class="logout-button"
            :title="t('auth.logout')"
            @click="logout"
          >
            <i
              class="pi pi-sign-out"
              aria-hidden="true"
            />
          </button>
        </div>
      </header>

      <main class="app-content">
        <slot />
      </main>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { RouterLink, useRoute, useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'

import type { AuthMenuResult } from '@/types/auth'
import { fetchBackendHealth } from '@/services/healthService'
import { useAppPreferencesStore, type SupportedLocale } from '@/stores/appPreferences'
import { useAuthStore } from '@/stores/authStore'
import { resolveAuthenticatedEntryPath } from '@/utils/authNavigation'

const route = useRoute()
const router = useRouter()
const { t, locale } = useI18n()
const preferences = useAppPreferencesStore()
const authStore = useAuthStore()
const healthState = ref<'checking' | 'up' | 'down'>('checking')

const localeOptions: Array<{ value: SupportedLocale; label: string }> = [
  { value: 'zh-CN', label: '中文' },
  { value: 'en-US', label: 'EN' },
  { value: 'th-TH', label: 'ไทย' },
]

const menuLabelKeys: Record<string, string> = {
  RESERVATION_ORDERS: 'nav.orders',
  RESERVATION_TASKS: 'nav.taskQueue',
  DEBUG_EML_SUPERAGENT: 'nav.debugEml',
  SYSTEM_SETTINGS: 'nav.systemSettings',
}

const navItems = computed(() => authStore.visibleMenus)
const brandTarget = computed(() => resolveAuthenticatedEntryPath(authStore.firstMenuPath))
const currentUserLabel = computed(() => authStore.user?.display_name || authStore.user?.username || '-')
const currentHotelLabel = computed(() => {
  const hotel = authStore.selectedHotel
  return hotel?.hotel_name || hotel?.hotel_id || '-'
})
const hotelSwitchable = computed(() => authStore.hotels.length > 1 && authStore.hasPermission('HOTEL_SWITCH'))

const pageTitle = computed(() => {
  const titleKey = typeof route.meta.titleKey === 'string' ? route.meta.titleKey : 'nav.orders'
  return t(titleKey)
})

const healthLabel = computed(() => {
  if (healthState.value === 'up') {
    return t('app.healthUp')
  }
  if (healthState.value === 'down') {
    return t('app.healthDown')
  }
  return t('app.healthChecking')
})

onMounted(() => {
  void checkHealth()
})

function setLocale(nextLocale: SupportedLocale): void {
  preferences.setLocale(nextLocale)
  locale.value = nextLocale
}

function menuLabel(item: AuthMenuResult): string {
  const labelKey = menuLabelKeys[item.menu_code]
  return labelKey ? t(labelKey) : item.menu_name
}

function changeHotel(event: Event): void {
  const select = event.target
  if (select instanceof HTMLSelectElement) {
    authStore.setSelectedHotelId(select.value)
  }
}

async function logout(): Promise<void> {
  await authStore.logout()
  await router.push('/login')
}

async function checkHealth(): Promise<void> {
  healthState.value = 'checking'
  try {
    const health = await fetchBackendHealth()
    healthState.value = health.status === 'UP' ? 'up' : 'down'
  } catch {
    healthState.value = 'down'
  }
}
</script>

<style scoped>
.app-shell {
  min-height: 100vh;
  display: grid;
  grid-template-columns: var(--th-sidebar-width) minmax(0, 1fr);
  background: var(--th-color-slate-100);
}

.app-sidebar {
  position: sticky;
  top: 0;
  height: 100vh;
  display: grid;
  grid-template-rows: auto 1fr;
  gap: 28px;
  background: linear-gradient(180deg, var(--th-color-navy-950), var(--th-color-navy-900));
  color: var(--th-color-white);
  padding: 28px 18px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.brand-mark {
  width: 36px;
  height: 36px;
  flex: 0 0 auto;
  border-radius: 10px;
  background: linear-gradient(135deg, #0a7cff, #0057e5);
}

.brand strong,
.brand small {
  display: block;
}

.brand strong {
  font-size: 15px;
  line-height: 1.1;
}

.brand small {
  margin-top: 2px;
  color: rgb(255 255 255 / 72%);
  font-size: 11px;
}

.app-nav {
  display: grid;
  align-content: start;
  gap: 8px;
}

.app-nav__item {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  border-radius: var(--th-radius-sm);
  color: rgb(255 255 255 / 78%);
  font-size: 13px;
  font-weight: 700;
  padding: 0 12px;
}

.app-nav__item.router-link-active {
  background: rgb(255 255 255 / 12%);
  color: var(--th-color-white);
  box-shadow: inset 3px 0 0 var(--th-color-blue-600);
}

.app-main {
  min-width: 0;
  display: grid;
  grid-template-rows: var(--th-topbar-height) 1fr;
}

.app-topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  border-bottom: 1px solid var(--th-color-slate-200);
  background: rgb(255 255 255 / 92%);
  backdrop-filter: blur(14px);
  padding: 0 28px;
}

.app-topbar strong,
.app-topbar small {
  display: block;
}

.app-topbar strong {
  color: var(--th-color-slate-900);
  font-size: 15px;
}

.app-topbar small {
  margin-top: 4px;
  color: var(--th-color-slate-500);
  font-size: 12px;
}

.app-topbar__actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

.health-pill,
.locale-switch,
.theme-button,
.logout-button,
.user-chip,
.hotel-chip,
.hotel-select {
  min-height: 36px;
  border: 1px solid var(--th-color-slate-200);
  border-radius: var(--th-radius-sm);
  background: var(--th-color-white);
}

.auth-context {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.user-chip,
.hotel-chip,
.hotel-select {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--th-color-slate-700);
  font-size: 12px;
  font-weight: 800;
  padding: 0 10px;
  white-space: nowrap;
}

.hotel-select {
  padding-right: 6px;
}

.hotel-select select {
  max-width: 150px;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  outline: 0;
}

.health-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--th-color-slate-500);
  font-size: 12px;
  font-weight: 800;
  padding: 0 10px;
  white-space: nowrap;
}

.health-pill i {
  font-size: 7px;
}

.health-pill--up {
  color: var(--th-color-success);
}

.health-pill--down {
  color: var(--th-color-danger);
}

.locale-switch {
  display: inline-flex;
  padding: 3px;
}

.locale-switch button,
.theme-button,
.logout-button {
  border: 0;
  background: transparent;
  color: var(--th-color-slate-700);
  cursor: pointer;
  font-weight: 800;
}

.locale-switch button {
  min-width: 46px;
  border-radius: 5px;
  padding: 0 8px;
  font-size: 12px;
}

.locale-switch button.active {
  background: var(--th-color-blue-100);
  color: var(--th-color-blue-600);
}

.theme-button,
.logout-button {
  width: 38px;
}

.app-content {
  min-width: 0;
  padding: 28px;
}

@media (max-width: 780px) {
  .app-shell {
    grid-template-columns: minmax(0, 1fr);
  }

  .app-sidebar {
    position: static;
    height: auto;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto;
    gap: 12px;
    padding: 14px 18px 16px;
  }

  .app-nav {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    width: 100%;
  }

  .app-nav__item {
    flex: 1 1 128px;
    justify-content: center;
    min-width: 0;
  }

  .app-nav__item span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .app-nav__item.router-link-active {
    box-shadow: inset 0 -3px 0 var(--th-color-blue-600);
  }

  .app-main {
    grid-template-rows: auto 1fr;
  }

  .app-topbar {
    min-height: var(--th-topbar-height);
    padding: 0 18px;
  }

  .health-pill {
    display: none;
  }

  .auth-context {
    max-width: 100%;
  }

  .user-chip {
    display: none;
  }

  .app-content {
    padding: 18px;
  }
}

@media (max-width: 520px) {
  .app-sidebar {
    padding: 12px 14px;
  }

  .brand strong {
    font-size: 14px;
  }

  .app-nav__item {
    flex-basis: calc(50% - 4px);
    font-size: 12px;
    padding: 0 10px;
  }

  .app-topbar {
    align-items: start;
    display: grid;
    gap: 10px;
    grid-template-columns: minmax(0, 1fr);
    min-height: auto;
    padding: 12px 14px;
  }

  .app-topbar__actions {
    justify-content: space-between;
    width: 100%;
  }

  .locale-switch {
    flex: 1;
    max-width: 136px;
  }

  .locale-switch button {
    flex: 1;
    min-width: 0;
  }

  .theme-button,
  .logout-button {
    flex: 0 0 38px;
  }

  .app-content {
    padding: 14px;
  }
}
</style>
