<template>
  <div
    :class="[
      'frame-card',
      `frame-card--${size}`,
      `frame-card--${status}`,
    ]"
  >
    <!-- Settings button (large card only) -->
    <button
      v-if="size === 'large'"
      class="frame-card__settings-btn"
      type="button"
      aria-label="Frame settings"
      @click="$emit('edit', deviceId)"
    >
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true">
        <circle cx="12" cy="12" r="3"/>
        <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
      </svg>
    </button>

    <!-- Preview area -->
    <div class="frame-card__preview" :style="previewStyle">
      <img
        v-if="thumbnailUrl"
        :src="thumbnailUrl"
        :alt="`Current photo on ${name}`"
        class="frame-card__img"
      />
      <div v-else class="frame-card__empty-preview" :style="emptyAspectStyle" aria-hidden="true">
        <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
          <rect x="3" y="3" width="18" height="18" rx="2"/>
          <circle cx="8.5" cy="8.5" r="1.5"/>
          <polyline points="21,15 16,10 5,21"/>
        </svg>
      </div>
    </div>

    <div class="frame-card__body">
      <div class="frame-card__info">
        <p class="frame-card__name">{{ name }}</p>
        <p class="frame-card__status-line" aria-live="polite">
          <span class="frame-card__status-dot" aria-hidden="true" />
          <span class="frame-card__status-text">{{ statusText }}</span>
        </p>
        <p v-if="size === 'large' && (lastSync || nextSync)" class="frame-card__sync-line">
          <span v-if="lastSync">synced {{ lastSync }}</span>
          <span v-if="lastSync && nextSync" class="frame-card__sync-sep" aria-hidden="true">·</span>
          <span v-if="nextSync">{{ nextSync }}</span>
        </p>
        <p v-else-if="size === 'compact' && photoCount !== undefined" class="frame-card__count">
          {{ photoCount }} {{ photoCount === 1 ? 'photo' : 'photos' }}
        </p>
      </div>

      <BaseButton
        :variant="size === 'large' ? 'primary' : 'icon-pill'"
        :aria-label="`Add photo to ${name}`"
        class="frame-card__add-btn"
        @click="$emit('add-photo', deviceId)"
      >
        <span v-if="size === 'large'">+ Add Photo</span>
        <span v-else aria-hidden="true">+</span>
      </BaseButton>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import BaseButton from '@/components/BaseButton.vue'

const props = defineProps<{
  deviceId: number
  name: string
  size: 'large' | 'compact'
  status: 'ok' | 'offline' | 'sync-fail'
  orientation: 'landscape' | 'portrait'
  thumbnailUrl?: string
  photoCount?: number
  lastSync?: string | null
  nextSync?: string | null
}>()

defineEmits<{ 'add-photo': [deviceId: number]; edit: [deviceId: number] }>()

// On large cards we let the <img> drive the preview height (its intrinsic
// aspect ratio is the device's actual aspect). Until the image loads — or
// when no thumbnail exists yet — we want the empty placeholder to reserve
// roughly the same shape so the layout doesn't jump.
const previewStyle = computed(() => ({}))

const emptyAspectStyle = computed(() =>
  props.size === 'large'
    ? { aspectRatio: props.orientation === 'portrait' ? '3 / 5' : '5 / 3' }
    : {}
)

const statusText = computed(() => {
  switch (props.status) {
    case 'ok':        return 'Online'
    case 'sync-fail': return 'Sync issue'
    case 'offline':   return 'Offline'
  }
})
</script>

<style scoped lang="scss">
.frame-card {
  position: relative;
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: border-color var(--duration-fast);

  &--ok        { border-color: var(--color-border); }
  &--sync-fail { border-color: #c49a20; }
  &--offline   { border-color: #c0392b; }

  &__settings-btn {
    position: absolute;
    top: var(--space-2);
    right: var(--space-2);
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: none;
    background: rgba(255, 255, 255, 0.85);
    backdrop-filter: blur(4px);
    color: var(--color-text);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
  }

  &__status-line {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--text-sm);
    font-weight: 600;

    .frame-card--ok        & { color: #1a7f4b; }
    .frame-card--sync-fail & { color: #8a6a00; }
    .frame-card--offline   & { color: #c0392b; }
  }

  &__status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;

    .frame-card--ok        & { background: #1a7f4b; }
    .frame-card--sync-fail & { background: #c49a20; }
    .frame-card--offline   & { background: #c0392b; }
  }

  &__sync-line {
    margin-top: 2px;
    font-size: var(--text-xs);
    color: var(--color-text-muted);
    display: flex;
    flex-wrap: wrap;
    gap: 0 6px;
  }

  &__sync-sep {
    opacity: 0.6;
  }

  // ── Large (single device or carousel slide) ──────────────────────────────
  // The card stretches to fill its parent (slide or single-card container).
  // The preview hugs the photo's natural aspect — no letterbox bars, no min-
  // height forcing extra blank space. Whatever vertical room is left after
  // the photo gets absorbed by the body, with the Add button pinned to the
  // bottom so the card never has a "huge gap" floating above the nav.
  &--large {
    display: flex;
    flex-direction: column;
    height: 100%;
  }

  &--large &__preview {
    flex: 0 0 auto;
    background: var(--color-surface-2);
    display: block;
    overflow: hidden;
  }

  &--large &__img {
    display: block;
    width: 100%;
    height: auto;
  }

  &--large &__empty-preview {
    color: var(--color-text-muted);
    opacity: 0.5;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
  }

  &--large &__body {
    flex: 1;
    min-height: 0;
    padding: var(--space-4);
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
  }

  &--large &__info {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
  }

  &--large &__name {
    font-size: var(--text-md);
    font-weight: 700;
  }

  &--large &__add-btn {
    margin-top: auto;
    width: 100%;
  }

  // ── Compact (multi device) ───────────────────────────────────────────────
  &--compact {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
  }

  &--compact &__preview {
    width: 52px;
    height: 52px;
    border-radius: var(--radius-sm);
    background: var(--color-surface-2);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
  }

  &--compact &__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  &--compact &__empty-preview {
    color: var(--color-text-muted);
    opacity: 0.4;
  }

  &--compact &__body {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    min-width: 0;
  }

  &--compact &__info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
  }

  &--compact &__name {
    font-size: var(--text-base);
    font-weight: 700;
  }

  &--compact &__count {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
  }

  &__add-btn { flex-shrink: 0; }

  // ── Landscape phone: dense horizontal layout ─────────────────────────────
  // Photo is height-constrained (preview takes flex:1, image letterboxed) so
  // it doesn't blow past the short viewport. Body collapses to a single row
  // — name + status on the left, Add button on the right — and the sync
  // line is dropped to keep the card tight.
  @media (orientation: landscape) and (max-height: 600px) {
    &--large &__preview {
      flex: 1;
      min-height: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      overflow: hidden;
    }

    &--large &__img {
      width: 100%;
      height: 100%;
      object-fit: contain;
    }

    &--large &__body {
      flex: 0 0 auto;
      flex-direction: row;
      align-items: center;
      gap: var(--space-3);
      padding: var(--space-2) var(--space-3);
    }

    &--large &__info {
      flex: 1;
      min-width: 0;
    }

    &--large &__sync-line { display: none; }

    &--large &__add-btn {
      margin-top: 0;
      width: auto;
      flex-shrink: 0;
    }

    &--large &__settings-btn {
      width: 32px;
      height: 32px;
      top: var(--space-1);
      right: var(--space-1);
    }
  }
}
</style>
