<template>
  <BaseBottomSheet
    :model-value="modelValue"
    label="Manage frames for this photo"
    @update:model-value="$emit('update:modelValue', $event)"
  >
    <h2 class="manage__title">Manage frames</h2>
    <p class="manage__sub">
      Toggle which frames show this photo, or lock it to a frame so it stays
      visible until you unlock it.
    </p>

    <div v-if="!devices.length" class="manage__empty">
      You don't have any frames set up yet.
    </div>

    <div v-else class="manage__list">
      <div
        v-for="device in devices"
        :key="device.id"
        class="manage__row"
      >
        <div class="manage__device">
          <span class="manage__device-name">{{ device.name }}</span>
          <span class="manage__device-meta">{{ device.orientation }}</span>
        </div>

        <!-- Lock control. Hidden entirely when the photo isn't approved on
             this frame — no need to show a disabled lock when it can't
             apply. When locked, shows "Locked" + closed padlock; otherwise
             icon-only so the toggle stays the visual primary. -->
        <button
          v-if="isApproved(device.id)"
          type="button"
          class="manage__lock"
          :class="{ 'manage__lock--on': device.lockedImageId === image?.id }"
          :disabled="pendingLock === device.id"
          :aria-label="device.lockedImageId === image?.id
            ? `Unlock from ${device.name}`
            : `Lock to ${device.name}`"
          @click="onLockClick(device)"
        >
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true">
            <rect x="3" y="11" width="18" height="11" rx="2" ry="2"/>
            <path v-if="device.lockedImageId === image?.id" d="M7 11V7a5 5 0 0 1 10 0v4"/>
            <path v-else d="M7 11V7a5 5 0 0 1 9.9-1"/>
          </svg>
          <span v-if="device.lockedImageId === image?.id">Locked</span>
        </button>

        <!-- Show / hide this photo on this frame. Primary control on the row. -->
        <label class="manage__toggle-wrap">
          <span class="manage__toggle-label">
            {{ isApproved(device.id) ? 'Show' : 'Hidden' }}
          </span>
          <button
            type="button"
            class="manage__toggle"
            :class="{ 'manage__toggle--on': isApproved(device.id) }"
            :disabled="pendingApproval === device.id"
            :aria-label="isApproved(device.id)
              ? `Hide this photo from ${device.name}`
              : `Show this photo on ${device.name}`"
            @click="onApprovalClick(device)"
          ></button>
        </label>
      </div>
    </div>

    <BaseButton
      variant="primary"
      class="manage__done"
      @click="$emit('update:modelValue', false)"
    >
      Done
    </BaseButton>
  </BaseBottomSheet>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import BaseBottomSheet from '@/components/BaseBottomSheet.vue'
import BaseButton from '@/components/BaseButton.vue'
import type { Device, Image } from '@/types'

const props = defineProps<{
  modelValue: boolean
  image: Image | null
  devices: Device[]
}>()

const emit = defineEmits<{
  (e: 'update:modelValue', v: boolean): void
  (e: 'approval', payload: { imageId: number; deviceId: number; approved: boolean }): void
  (e: 'lock',     payload: { imageId: number; deviceId: number; locked: boolean }):    void
}>()

// Optimistic-locking guards so a fast double-tap doesn't fire two requests.
const pendingApproval = ref<number | null>(null)
const pendingLock     = ref<number | null>(null)

function isApproved(deviceId: number): boolean {
  return !!props.image?.approvedDeviceIds.includes(deviceId)
}

function onApprovalClick(device: Device) {
  if (!props.image) return
  pendingApproval.value = device.id
  const approved = !isApproved(device.id)
  emit('approval', { imageId: props.image.id, deviceId: device.id, approved })
  // The parent updates the store; we just need a brief debounce.
  setTimeout(() => { pendingApproval.value = null }, 200)
}

function onLockClick(device: Device) {
  if (!props.image) return
  if (!isApproved(device.id)) return
  pendingLock.value = device.id
  const locked = device.lockedImageId !== props.image.id
  emit('lock', { imageId: props.image.id, deviceId: device.id, locked })
  setTimeout(() => { pendingLock.value = null }, 200)
}
</script>

<style scoped lang="scss">
.manage {
  &__title {
    font-size: var(--text-md);
    font-weight: 700;
    margin: 0 0 var(--space-2);
  }

  &__sub {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    margin: 0 0 var(--space-4);
    line-height: 1.4;
  }

  &__empty {
    text-align: center;
    color: var(--color-text-muted);
    font-size: var(--text-sm);
    padding: var(--space-6) 0;
  }

  &__list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-bottom: var(--space-5);
  }

  &__row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--color-border);
    min-height: 56px;
  }
  &__row:last-child { border-bottom: 0; }

  &__device {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
  }
  &__device-name {
    font-size: var(--text-base);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  &__device-meta {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
    text-transform: capitalize;
  }

  // Lock pill — visible only when approved; disabled state for not-approved.
  &__lock {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: transparent;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-full);
    padding: 4px 10px;
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--color-text-muted);
    transition: background var(--duration-fast, 150ms), color var(--duration-fast, 150ms);

    &:disabled {
      opacity: 0.4;
      cursor: not-allowed;
    }
    &--on {
      background: #c49a20;
      border-color: #c49a20;
      color: white;
    }
  }

  // Show/hide toggle group — label above the slider so the meaning is
  // obvious before tapping.
  &__toggle-wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    cursor: pointer;
    flex-shrink: 0;
  }

  &__toggle-label {
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--color-text-muted);
    user-select: none;
  }

  // iOS-style approval toggle
  &__toggle {
    width: 48px;
    height: 28px;
    background: var(--color-border);
    border: 0;
    border-radius: var(--radius-full);
    position: relative;
    transition: background var(--duration-fast, 150ms);
    flex-shrink: 0;

    &::after {
      content: '';
      position: absolute;
      top: 3px;
      left: 3px;
      width: 22px;
      height: 22px;
      border-radius: 50%;
      background: white;
      transition: left var(--duration-fast, 150ms);
      box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
    }
    &--on {
      background: var(--color-primary);
    }
    &--on::after {
      left: 23px;
    }
  }

  &__done {
    width: 100%;
  }
}
</style>
