<script setup lang="ts">
import { computed, onMounted, onUnmounted } from 'vue'
import type { MediaItem, ResolveSource } from '@/types'
import { findViewer } from '@/services/viewer.ts'
import MediaStage from './MediaStage.vue'

/**
 * Fullscreen media viewer surface. Generic: driven entirely by `MediaItem`s and
 * a host-supplied `resolveSource`. Prev/next navigation is opt-in via
 * `navigation` and is suppressed for `standalone` viewers (which bring their
 * own chrome) so their controls never compete with a "next file" arrow.
 */
const props = withDefaults(
  defineProps<{
    modelValue: boolean
    items: MediaItem[]
    index: number
    resolveSource: ResolveSource
    /** Triggers a host download of the given item. */
    download?: (item: MediaItem) => void
    /** Enable prev/next gallery navigation across `items`. */
    navigation?: boolean
  }>(),
  {
    download: undefined,
    navigation: false,
  },
)

const emit = defineEmits<{
  'update:modelValue': [value: boolean]
  'update:index': [value: number]
}>()

const currentItem = computed<MediaItem | null>(
  () => props.items[props.index] ?? null,
)

const filename = computed(() => currentItem.value?.title ?? '')

const activeMode = computed(() => {
  const mime = currentItem.value?.mime
  if (!mime) return undefined
  return findViewer(mime)?.meta?.mode as string | undefined
})

const navVisible = computed(
  () =>
    props.navigation &&
    props.items.length > 1 &&
    activeMode.value !== 'standalone',
)

const hasPrev = computed(() => navVisible.value && props.index > 0)
const hasNext = computed(
  () => navVisible.value && props.index < props.items.length - 1,
)

function navigatePrev() {
  if (hasPrev.value) emit('update:index', props.index - 1)
}

function navigateNext() {
  if (hasNext.value) emit('update:index', props.index + 1)
}

function close() {
  emit('update:modelValue', false)
}

function handleDownload() {
  if (currentItem.value) props.download?.(currentItem.value)
}

function handleKeydown(e: KeyboardEvent) {
  if (!props.modelValue) return
  if (e.key === 'ArrowLeft') { e.preventDefault(); navigatePrev() }
  else if (e.key === 'ArrowRight') { e.preventDefault(); navigateNext() }
  else if (e.key === 'Escape') { e.preventDefault(); close() }
}

onMounted(() => window.addEventListener('keydown', handleKeydown))
onUnmounted(() => window.removeEventListener('keydown', handleKeydown))
</script>

<template>
  <v-dialog
    :model-value="modelValue"
    fullscreen
    transition="dialog-bottom-transition"
    @update:model-value="emit('update:modelValue', $event)"
  >
    <div class="viewer-shell">

      <!-- ── Toolbar ─────────────────────────────────────────────────── -->
      <div class="viewer-toolbar">
        <v-btn icon="mdi-close" variant="text" @click="close" />

        <span class="viewer-filename text-truncate">{{ filename }}</span>

        <div class="viewer-toolbar-actions">
          <span
            v-if="navVisible"
            class="viewer-counter text-caption text-medium-emphasis mr-2"
          >
            {{ index + 1 }} / {{ items.length }}
          </span>
          <v-btn
            v-if="download"
            icon="mdi-download"
            variant="text"
            size="small"
            title="Download"
            @click="handleDownload"
          />
        </div>
      </div>

      <!-- ── Content area ───────────────────────────────────────────── -->
      <div class="viewer-content">

        <!-- Prev arrow -->
        <div class="viewer-nav viewer-nav--prev">
          <v-btn
            v-if="hasPrev"
            icon="mdi-chevron-left"
            variant="elevated"
            size="large"
            @click="navigatePrev"
          />
        </div>

        <!-- Stage -->
        <div class="viewer-stage">
          <MediaStage :item="currentItem" :resolve-source="resolveSource">
            <template #unsupported="{ mime }">
              <div class="viewer-no-preview">
                <v-icon size="64" color="grey-lighten-1">mdi-file-question-outline</v-icon>
                <p class="text-h6 mt-4">No preview available</p>
                <p class="text-body-2 text-medium-emphasis mb-6">
                  {{ mime || 'Unknown file type' }}
                </p>
                <v-btn
                  v-if="download"
                  prepend-icon="mdi-download"
                  variant="tonal"
                  @click="handleDownload"
                >
                  Download file
                </v-btn>
              </div>
            </template>
          </MediaStage>
        </div>

        <!-- Next arrow -->
        <div class="viewer-nav viewer-nav--next">
          <v-btn
            v-if="hasNext"
            icon="mdi-chevron-right"
            variant="elevated"
            size="large"
            @click="navigateNext"
          />
        </div>

      </div>
    </div>
  </v-dialog>
</template>

<style scoped>
.viewer-shell {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: rgb(var(--v-theme-surface));
}

/* Toolbar */
.viewer-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 8px;
  border-bottom: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
  min-height: 56px;
  flex-shrink: 0;
}

.viewer-filename {
  flex: 1;
  font-size: 0.9375rem;
  font-weight: 500;
}

.viewer-toolbar-actions {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

/* Content */
.viewer-content {
  flex: 1;
  display: flex;
  align-items: stretch;
  overflow: hidden;
}

/* Prev/Next nav columns */
.viewer-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  flex-shrink: 0;
  padding: 8px;
}

/* Main stage */
.viewer-stage {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: auto;
  position: relative;
}

/* No-preview fallback */
.viewer-no-preview {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 32px;
}

@media (max-width: 600px) {
  .viewer-nav {
    width: 40px;
    padding: 4px;
  }
}
</style>
