<template>
  <div :class="wrapperClasses">
    <!-- Heading Section -->
    <div class="mb-4">
      <h2 class="font-domaine text-titan-green-800 text-[20px] leading-[1.3] max-w-[274px]">
        {{ label }}
      </h2>
    </div>

    <!-- Empty State: Drop Zone -->
    <div
      v-if="!previewUrl"
      :class="dropZoneClasses"
      @dragenter.prevent="handleDragEnter"
      @dragover.prevent="handleDragOver"
      @dragleave.prevent="handleDragLeave"
      @drop.prevent="handleDrop"
      @click="!disabled && triggerFileInput()"
      role="button"
      :tabindex="disabled ? -1 : 0"
      :aria-label="disabled ? undefined : 'Upload image file'"
      :aria-disabled="disabled"
      @keydown.enter.prevent="!disabled && triggerFileInput()"
      @keydown.space.prevent="!disabled && triggerFileInput()"
    >
      <div class="flex flex-col items-center justify-center h-full pointer-events-none">
        <p class="font-work-sans font-bold text-[13px] text-titan-green-800 tracking-[0.78px] uppercase mb-2">
          {{ dragText }}
        </p>
        <p class="font-work-sans font-bold text-[13px] text-titan-green-800 tracking-[0.78px] uppercase mb-4">
          OR
        </p>
        <button
          type="button"
          :class="selectButtonClasses"
          :disabled="disabled"
          class="pointer-events-auto"
          @click.stop="triggerFileInput"
          aria-label="Select file from computer"
        >
          <span class="font-work-sans font-bold text-[13px] text-titan-green-800 tracking-[0.78px] uppercase">
            {{ buttonText }}
          </span>
        </button>
      </div>
    </div>

    <!-- Preview State: Image with Delete Button -->
    <div
      v-else
      class="relative w-full h-[223px] rounded-[15px] overflow-hidden"
    >
      <img
        :src="previewUrl"
        :alt="previewAlt"
        class="w-full h-full object-contain"
      />
      <button
        v-if="!disabled"
        type="button"
        class="absolute top-2 right-2 w-[25px] h-[25px] bg-red-600 hover:bg-red-700 rounded-full flex items-center justify-center transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
        @click="handleRemove"
        aria-label="Remove image"
      >
        <span class="text-white text-sm font-bold leading-none">✕</span>
      </button>
    </div>

    <!-- Hidden File Input -->
    <input
      ref="fileInputRef"
      type="file"
      :accept="accept"
      :disabled="disabled"
      :required="required"
      class="sr-only"
      @change="handleInputChange"
      aria-hidden="true"
    />

    <!-- Error Message -->
    <Transition name="error-fade">
      <div
        v-if="hasError && errorMessage"
        class="mt-2 text-sm text-red-600 font-work-sans"
        role="alert"
        aria-live="polite"
      >
        {{ errorMessage }}
      </div>
    </Transition>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { useFileUpload } from '@/composables/useFileUpload'
import type { ImageUploadProps, ImageUploadEmits } from '@/types/components'

const props = withDefaults(defineProps<ImageUploadProps>(), {
  accept: 'image/*',
  maxSize: 5242880, // 5MB
  disabled: false,
  required: false,
  error: false,
  label: "Let's start with an image of your loved one for their portrait.",
  dragText: 'DRAG PHOTO HERE',
  buttonText: 'SELECT FILE ⇧',
  previewAlt: 'Uploaded image preview'
})

const emit = defineEmits<ImageUploadEmits>()

// File input ref
const fileInputRef = ref<HTMLInputElement | null>(null)

// Use file upload composable
const {
  isDragging,
  previewUrl,
  validationError,
  handleFileSelect,
  handleFileRemove,
  handleDragEnter,
  handleDragOver,
  handleDragLeave,
  handleDrop
} = useFileUpload({
  accept: computed(() => props.accept),
  maxSize: computed(() => props.maxSize),
  maxWidth: computed(() => props.maxWidth),
  maxHeight: computed(() => props.maxHeight),
  onFileSelect: (file: File) => {
    emit('update:modelValue', file)
    emit('change', file)
  },
  onFileRemove: () => {
    emit('update:modelValue', null)
    emit('remove')
  },
  onError: (error: string) => {
    emit('error', error)
  }
})

// Computed properties
const hasError = computed(() => props.error || !!validationError.value)
const errorMessage = computed(() => props.errorMessage || validationError.value || '')

const wrapperClasses = computed(() => {
  const classes = ['titan-image-upload']

  if (props.class) {
    classes.push(props.class)
  }

  return classes.join(' ')
})

const dropZoneClasses = computed(() => {
  const classes = [
    'w-full',
    'h-[223px]',
    'rounded-[15px]',
    'border-2',
    'border-dashed',
    'border-titan-green-800',
    'flex',
    'items-center',
    'justify-center',
    'transition-all',
    'duration-200',
    'cursor-pointer',
    'p-6'
  ]

  if (isDragging.value) {
    classes.push('bg-titan-green-50', 'border-solid')
  } else {
    classes.push('hover:bg-titan-green-50/50')
  }

  if (props.disabled) {
    classes.push('opacity-50', 'cursor-not-allowed', 'pointer-events-none')
  }

  if (hasError.value) {
    classes.push('border-red-500')
  }

  return classes.join(' ')
})

const selectButtonClasses = computed(() => {
  const classes = [
    'border-3',
    'border-titan-yellow-400',
    'bg-transparent',
    'text-titan-green-800',
    'rounded-[20px]',
    'px-5',
    'py-3',
    'transition-all',
    'duration-200',
    'hover:bg-titan-yellow-400',
    'focus:outline-none',
    'focus:ring-2',
    'focus:ring-titan-yellow-400',
    'focus:ring-offset-2'
  ]

  if (props.disabled) {
    classes.push('opacity-50', 'cursor-not-allowed')
  }

  return classes.join(' ')
})

// Methods
const triggerFileInput = () => {
  if (!props.disabled && fileInputRef.value) {
    fileInputRef.value.click()
  }
}

const handleInputChange = async (event: Event) => {
  const target = event.target as HTMLInputElement
  const files = target.files

  if (files && files.length > 0) {
    await handleFileSelect(files[0])
  }

  // Reset input value to allow selecting the same file again
  target.value = ''
}

const handleRemove = () => {
  handleFileRemove()
  if (fileInputRef.value) {
    fileInputRef.value.value = ''
  }
}

// Watch for external modelValue changes
watch(() => props.modelValue, (newValue) => {
  if (newValue === null && previewUrl.value) {
    handleFileRemove()
  } else if (newValue instanceof File && !previewUrl.value) {
    handleFileSelect(newValue)
  }
})
</script>

<style scoped>
.error-fade-enter-active,
.error-fade-leave-active {
  transition: all 0.2s ease-in-out;
}

.error-fade-enter-from {
  opacity: 0;
  transform: translateY(-4px);
}

.error-fade-leave-to {
  opacity: 0;
  transform: translateY(-4px);
}

/* Screen reader only class */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}
</style>