<template>
  <div class="upload-view">
    <!-- Header -->
    <header class="upload-view__header">
      <button
        v-if="step !== 'done'"
        class="upload-view__back"
        type="button"
        :aria-label="step === 'crop' ? 'Cancel' : 'Back'"
        @click="goBack"
      >
        <svg v-if="step === 'crop'" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true">
          <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
        </svg>
        <svg v-else width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true">
          <polyline points="15 18 9 12 15 6"/>
        </svg>
      </button>
      <span class="upload-view__step-label">{{ stepLabel }}</span>
      <button
        v-if="step === 'stickers'"
        class="upload-view__skip"
        type="button"
        @click="skipStickers"
      >Skip</button>
    </header>

    <!-- Crop step -->
    <CropEditor
      v-if="step === 'crop' && uploadStore.originalUrl"
      :src="uploadStore.originalUrl"
      :orientation="contextOrientation"
      :model="contextModel"
      :device-name="contextDeviceName"
      :initial-params="uploadStore.cropParams"
      :initial-orientation="uploadStore.cropOrientation"
      class="upload-view__stage"
      @crop="onCrop"
    />

    <!-- Stickers step -->
    <StickerCanvas
      v-else-if="step === 'stickers' && uploadStore.croppedUrl"
      :cropped-url="uploadStore.croppedUrl"
      :orientation="effectiveOrientation"
      :model="contextModel"
      :stickers="uploadStore.stickers"
      class="upload-view__stage"
      @add-sticker="uploadStore.addSticker"
      @update-sticker="uploadStore.updateSticker"
      @remove-sticker="uploadStore.removeSticker"
      @done="onStickersDone"
    />

    <!-- Done -->
    <div v-else-if="step === 'done'" class="upload-view__done">
      <div class="upload-view__done-icon" aria-hidden="true">🎉</div>
      <p class="upload-view__done-title">{{ isEdit ? 'Photo updated!' : 'Photo added!' }}</p>
      <p class="upload-view__done-sub">It'll appear on your frame at the next update.</p>
      <BaseButton variant="primary" class="upload-view__done-btn" @click="finish">Done</BaseButton>
    </div>

    <!-- Device picker (only on new uploads, not edits) -->
    <DevicePicker
      v-if="!isEdit"
      v-model="devicePickerOpen"
      :devices="devicesStore.devices"
      :selected="uploadStore.selectedDeviceIds"
      :uploading="uploading"
      @update:selected="uploadStore.selectedDeviceIds = $event"
      @confirm="doUpload"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useUploadStore } from '@/stores/upload'
import { useDevicesStore } from '@/stores/devices'
import { useImagesStore } from '@/stores/images'
import { useToastStore } from '@/stores/toast'
import type { CropParams, DeviceModel } from '@/types'
import CropEditor from '@/components/CropEditor.vue'
import StickerCanvas from '@/components/StickerCanvas.vue'
import DevicePicker from '@/components/DevicePicker.vue'
import BaseButton from '@/components/BaseButton.vue'

const router       = useRouter()
const uploadStore  = useUploadStore()
const devicesStore = useDevicesStore()
const imagesStore  = useImagesStore()
const toast        = useToastStore()

type Step = 'crop' | 'stickers' | 'done'
const step           = ref<Step>('crop')
const uploading      = ref(false)
const devicePickerOpen = ref(false)
let finalBlob: Blob | null = null

const isEdit = computed(() => uploadStore.editingImageId !== null)

// ── Bootstrap ─────────────────────────────────────────────────────────────────

onMounted(async () => {
  await devicesStore.fetchDevices()

  if (!uploadStore.originalFile) {
    router.replace('/')
    return
  }

  // When opening for edit, jump straight to crop (state already loaded by caller)
  step.value = 'crop'
})

// ── Context device ────────────────────────────────────────────────────────────

const contextDevice = computed(() =>
  uploadStore.contextDeviceId
    ? devicesStore.devices.find(d => d.id === uploadStore.contextDeviceId)
    : devicesStore.devices[0]
)

const contextModel = computed<DeviceModel>(() =>
  contextDevice.value?.model ?? 'v1'
)
const contextOrientation = computed<'landscape' | 'portrait'>(() =>
  contextDevice.value?.orientation ?? 'landscape'
)

// Once the user picks a crop orientation it drives the rest of the flow
// (StickerCanvas aspect, output blob dims). Falls back to the device's
// orientation while the crop step hasn't been completed yet.
const effectiveOrientation = computed<'landscape' | 'portrait'>(() =>
  uploadStore.cropOrientation ?? contextOrientation.value
)

const contextDeviceName = computed(() => contextDevice.value?.name)

// ── Steps ─────────────────────────────────────────────────────────────────────

const stepLabel = computed(() => {
  if (step.value === 'crop')     return isEdit.value ? 'Edit crop' : 'Crop photo'
  if (step.value === 'stickers') return 'Add stickers'
  return isEdit.value ? 'Updated' : 'Added'
})

function onCrop({ blob, params, orientation }: { blob: Blob; params: CropParams; orientation: 'landscape' | 'portrait' }) {
  uploadStore.setCrop(blob, params, orientation)
  step.value = 'stickers'
}

function skipStickers() {
  if (!uploadStore.croppedBlob) return
  finalBlob = uploadStore.croppedBlob
  if (isEdit.value) {
    doUpload()
  } else {
    devicePickerOpen.value = true
  }
}

function onStickersDone(blob: Blob) {
  finalBlob = blob
  if (isEdit.value) {
    doUpload()
  } else {
    devicePickerOpen.value = true
  }
}

function goBack() {
  if (step.value === 'crop') {
    uploadStore.cleanup()
    router.replace('/library')
    return
  }
  if (step.value === 'stickers') {
    step.value = 'crop'
  }
}

// ── Upload / reprocess ────────────────────────────────────────────────────────

async function doUpload() {
  if (!finalBlob) return
  uploading.value = true
  try {
    const composited = new File([finalBlob], 'photo.jpg', { type: 'image/jpeg' })

    if (isEdit.value) {
      await imagesStore.reprocessImage(uploadStore.editingImageId!, composited, {
        cropParams:      uploadStore.cropParams ?? undefined,
        stickerState:    uploadStore.stickers,
        cropOrientation: uploadStore.cropOrientation ?? undefined,
      })
      devicePickerOpen.value = false
      step.value = 'done'
      return
    }

    const image = await imagesStore.uploadImage(composited, {
      original:        uploadStore.originalFile ?? undefined,
      cropParams:      uploadStore.cropParams ?? undefined,
      stickerState:    uploadStore.stickers,
      cropOrientation: uploadStore.cropOrientation ?? undefined,
    })

    await Promise.all(
      uploadStore.selectedDeviceIds.map(deviceId =>
        imagesStore.setApproval(image.id, deviceId, true)
      )
    )
    devicePickerOpen.value = false
    step.value = 'done'
  } catch (e) {
    toast.show(e instanceof Error ? e.message : 'Upload failed', 'error')
  } finally {
    uploading.value = false
  }
}

function finish() {
  uploadStore.cleanup()
  router.replace('/library')
}
</script>

<style scoped lang="scss">
.upload-view {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--color-bg);
  display: flex;
  flex-direction: column;
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);

  &__header {
    flex-shrink: 0;
    height: 56px;
    display: flex;
    align-items: center;
    padding: 0 var(--space-4);
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-border);
    position: relative;
  }

  &__back {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: none;
    background: transparent;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text);
    margin-left: -8px;
  }

  &__step-label {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    font-size: var(--text-base);
    font-weight: 700;
    color: var(--color-text);
  }

  &__skip {
    margin-left: auto;
    background: none;
    border: none;
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--color-text-muted);
    cursor: pointer;
    padding: var(--space-2) 0;
  }

  &__stage {
    flex: 1;
    min-height: 0;
  }

  &__done {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-4);
    padding: var(--space-6) var(--space-5);
    text-align: center;
  }

  &__done-icon {
    font-size: 64px;
    line-height: 1;
    font-family: "Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji",sans-serif;
  }

  &__done-title {
    font-size: var(--text-xl);
    font-weight: 700;
  }

  &__done-sub {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    max-width: 260px;
    line-height: 1.5;
  }

  &__done-btn {
    width: 100%;
    max-width: 320px;
  }
}
</style>
