<template>
  <div class="kiosk-root" tabindex="0" ref="kioskRoot">
    <!-- Kiosk launcher grid -->
    <div class="kiosk-launcher">
      <!-- Header -->
      <div class="kiosk-header">
        <div class="flex items-center gap-4">
          <img :src="FALLBACK_ICON" alt="Archipelago" class="w-10 h-10" />
          <div>
            <h1 class="text-2xl font-bold text-white font-archipelago">Archipelago</h1>
            <p class="text-sm text-white/50">{{ currentTime }}</p>
          </div>
        </div>
        <div class="flex items-center gap-3">
          <div class="kiosk-status-pill" :class="isConnected ? 'status-success' : 'status-error'">
            <div class="w-2 h-2 rounded-full" :class="isConnected ? 'bg-green-400' : 'bg-red-400'"></div>
            {{ isConnected ? t('kiosk.online') : t('kiosk.offline') }}
          </div>
        </div>
      </div>

      <!-- App grid -->
      <div class="kiosk-grid">
        <button
          v-for="app in launchableApps"
          :key="app.id"
          class="kiosk-app-tile"
          @click="openApp(app)"
          :data-controller-focusable="true"
        >
          <div class="kiosk-app-icon-wrap">
            <img
              :src="app.icon"
              :alt="app.title"
              class="kiosk-app-icon"
              @error="($event.target as HTMLImageElement).src = FALLBACK_ICON"
            />
            <div
              class="kiosk-app-status"
              :class="app.running ? 'bg-green-400' : 'bg-white/30'"
            />
          </div>
          <span class="kiosk-app-label">{{ app.title }}</span>
        </button>
      </div>

      <!-- Footer -->
      <div class="kiosk-footer">
        <span class="text-white/30 text-sm">{{ t('kiosk.navHint') }}</span>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { useI18n } from 'vue-i18n'
import { useAppStore } from '@/stores/app'
import { useAppLauncherStore } from '@/stores/appLauncher'

const { t } = useI18n()
const store = useAppStore()
const appLauncher = useAppLauncherStore()
const kioskRoot = ref<HTMLElement | null>(null)

interface KioskApp {
  id: string
  title: string
  icon: string
  url: string
  running: boolean
}

// Public asset path — construct with BASE_URL to avoid Vite resolving it as a module import
const FALLBACK_ICON = `${import.meta.env.BASE_URL}assets/img/favico.png`

const currentTime = ref('')

const isConnected = computed(() => store.isConnected)

// Build list of launchable apps from the store's package data
const launchableApps = computed<KioskApp[]>(() => {
  const pkgs = store.data?.['package-data'] || {}
  const apps: KioskApp[] = []

  // App URL mappings. Bitcoin UI uses its direct host-network port; loading it
  // through /app/bitcoin-ui/ can render a blank shell because its assets are
  // rooted at /.
  const urlMap: Record<string, string> = {
    'bitcoin-knots': 'http://' + window.location.hostname + ':8334',
    'lnd': '/app/lnd/',
    'mempool': '/app/mempool/',
    'btcpay-server': '/app/btcpay/',
    'homeassistant': '/app/homeassistant/',
    'grafana': '/app/grafana/',
    'jellyfin': '/app/jellyfin/',
    'nextcloud': '/app/nextcloud/',
    'immich': '/app/immich/',
    'photoprism': '/app/photoprism/',
    'vaultwarden': '/app/vaultwarden/',
    'filebrowser': '/app/filebrowser/',
    'searxng': '/app/searxng/',
    'ollama': '/app/ollama/',
    'portainer': '/app/portainer/',
    'uptime-kuma': '/app/uptime-kuma/',
    'nginx-proxy-manager': '/app/nginx-proxy-manager/',
    'tailscale': '/app/tailscale/',
    'fedimint': '/app/fedimint/',
    'fedimint-gateway': '/app/fedimint-gateway/',
    'indeedhub': 'http://localhost:7778',
    'botfights': 'http://localhost:9100',
    'nwnn': 'https://nwnn.l484.com',
    '484-kitchen': 'https://484.kitchen',
    'call-the-operator': 'https://cta.tx1138.com',
    'arch-presentation': 'https://present.l484.com',
    'syntropy-institute': 'https://syntropy.institute',
    't-zero': 'https://teeminuszero.net',
  }

  for (const [id, pkg] of Object.entries(pkgs)) {
    const url = urlMap[id]
    if (!url) continue

    const isRunning = pkg.state === 'running' ||
      pkg.installed?.status === 'running'

    apps.push({
      id,
      title: pkg.manifest?.title || id,
      icon: pkg['static-files']?.icon || FALLBACK_ICON,
      url,
      running: isRunning,
    })
  }

  // Sort: running apps first, then alphabetical
  return apps.sort((a, b) => {
    if (a.running !== b.running) return a.running ? -1 : 1
    return a.title.localeCompare(b.title)
  })
})

function openApp(app: KioskApp) {
  // Delegate to the app launcher — handles iframe overlay vs new-tab
  appLauncher.open({ url: app.url, title: app.title })
}

// Clock updater
let clockInterval: ReturnType<typeof setInterval> | undefined
function updateClock() {
  const now = new Date()
  currentTime.value = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
}

onMounted(() => {
  updateClock()
  clockInterval = setInterval(updateClock, 30000)
  kioskRoot.value?.focus()

  // Connect WebSocket if not already
  if (!store.isConnected) {
    store.connectWebSocket().catch(() => {})
  }
})

onUnmounted(() => {
  if (clockInterval) clearInterval(clockInterval)
})
</script>

<style scoped>
.kiosk-root {
  position: fixed;
  left: var(--kiosk-safe-area-x, 0px);
  top: var(--kiosk-safe-area-y, 0px);
  width: calc(100vw - (var(--kiosk-safe-area-x, 0px) * 2));
  height: calc(100vh - (var(--kiosk-safe-area-y, 0px) * 2));
  background: #000;
  outline: none;
  overflow: hidden;
  z-index: 9999;
}

.kiosk-launcher {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: clamp(1rem, 3vh, 2rem) clamp(1.5rem, 4vw, 3rem);
  background: linear-gradient(180deg, #0a0a12 0%, #000 100%);
  box-sizing: border-box;
}

.kiosk-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-bottom: 2rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  margin-bottom: 2rem;
}

.kiosk-status-pill {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.375rem 0.75rem;
  border-radius: 9999px;
  font-size: 0.875rem;
  font-weight: 500;
}

.kiosk-grid {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 1.5rem;
  align-content: start;
  overflow-y: auto;
  padding: 0.5rem;
}

.kiosk-app-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  padding: 1.25rem 0.75rem;
  border-radius: 1rem;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.06);
  transition: all 0.25s ease;
  cursor: pointer;
}

.kiosk-app-tile:hover,
.kiosk-app-tile:focus-visible {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(251, 146, 60, 0.4);
  transform: scale(1.05);
  box-shadow: 0 0 30px rgba(251, 146, 60, 0.15);
  outline: none;
}

.kiosk-app-icon-wrap {
  position: relative;
  width: 64px;
  height: 64px;
}

.kiosk-app-icon {
  width: 64px;
  height: 64px;
  border-radius: 16px;
  object-fit: cover;
  background: rgba(255, 255, 255, 0.05);
}

.kiosk-app-status {
  position: absolute;
  bottom: -2px;
  right: -2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 3px solid #000;
}

.kiosk-app-label {
  font-size: 0.8125rem;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.85);
  text-align: center;
  line-height: 1.2;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.kiosk-footer {
  padding-top: 1.5rem;
  text-align: center;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  margin-top: 1.5rem;
}
</style>
