<template>
  <div class="camera-capture">
    <div v-if="!hasPermission && !error" class="camera-placeholder">
      <UIcon name="i-heroicons-camera" class="w-16 h-16 text-gray-400" />
      <p class="text-gray-600 dark:text-gray-400 mt-4">
        {{ permissionMessage }}
      </p>
      <UButton
        v-if="!isRequestingPermission"
        @click="requestCamera"
        color="primary"
        class="mt-4"
      >
        <UIcon name="i-heroicons-camera" class="w-5 h-5" />
        Activar cámara
      </UButton>
      <div v-else class="mt-4">
        <UIcon name="i-heroicons-arrow-path" class="w-6 h-6 animate-spin text-primary-500" />
        <p class="text-sm text-gray-500 mt-2">Solicitando permisos...</p>
      </div>
    </div>

    <div v-else-if="error" class="camera-error">
      <UIcon name="i-heroicons-exclamation-triangle" class="w-16 h-16 text-error-500" />
      <p class="text-error-600 dark:text-error-400 mt-4 font-semibold">
        {{ error }}
      </p>
      <p class="text-sm text-gray-600 dark:text-gray-400 mt-2">
        {{ errorHelp }}
      </p>
      <UButton
        @click="retry"
        color="primary"
        variant="soft"
        class="mt-4"
      >
        <UIcon name="i-heroicons-arrow-path" class="w-5 h-5" />
        Reintentar
      </UButton>
    </div>

    <div v-else-if="!capturedImage" class="camera-active">
      <div class="video-container">
        <video
          ref="videoElement"
          autoplay
          playsinline
          muted
          class="camera-video"
        ></video>

        <!-- Overlay con guías de encuadre -->
        <div class="camera-overlay">
          <div class="camera-guide"></div>
        </div>
      </div>

      <div class="camera-controls">
        <!-- Selector de cámara (si hay múltiples) -->
        <UButton
          v-if="cameras.length > 1"
          @click="switchCamera"
          color="neutral"
          variant="ghost"
          :disabled="isSwitching"
        >
          <UIcon name="i-heroicons-arrow-path" class="w-5 h-5" />
          Cambiar cámara
        </UButton>

        <!-- Botón de captura -->
        <UButton
          @click="capture"
          color="primary"
          size="xl"
          class="capture-button"
        >
          <UIcon name="i-heroicons-camera" class="w-6 h-6" />
          Capturar foto
        </UButton>

        <!-- Botón de cancelar -->
        <UButton
          @click="cancel"
          color="neutral"
          variant="ghost"
        >
          <UIcon name="i-heroicons-x-mark" class="w-5 h-5" />
          Cancelar
        </UButton>
      </div>
    </div>

    <div v-else class="camera-preview">
      <div class="preview-container">
        <img :src="capturedImage" alt="Foto capturada" class="preview-image" />
      </div>

      <div class="preview-controls">
        <UButton
          @click="retake"
          color="neutral"
          variant="soft"
        >
          <UIcon name="i-heroicons-arrow-path" class="w-5 h-5" />
          Tomar otra
        </UButton>

        <UButton
          @click="confirm"
          color="primary"
        >
          <UIcon name="i-heroicons-check" class="w-5 h-5" />
          Usar esta foto
        </UButton>
      </div>
    </div>

    <canvas ref="canvasElement" style="display: none;"></canvas>
  </div>
</template>

<script setup lang="ts">
interface CameraDevice {
  deviceId: string
  label: string
  kind: string
}

const emit = defineEmits<{
  (e: 'capture', image: Blob): void
  (e: 'cancel'): void
}>()

const videoElement = ref<HTMLVideoElement | null>(null)
const canvasElement = ref<HTMLCanvasElement | null>(null)
const stream = ref<MediaStream | null>(null)
const capturedImage = ref<string | null>(null)
const hasPermission = ref(false)
const isRequestingPermission = ref(false)
const isSwitching = ref(false)
const error = ref<string | null>(null)
const errorHelp = ref<string>('')
const permissionMessage = ref('Necesitamos acceso a tu cámara para tomar una foto de perfil')
const cameras = ref<CameraDevice[]>([])
const currentCameraIndex = ref(0)

// Detectar capacidades del dispositivo
const getUserMedia = navigator.mediaDevices?.getUserMedia?.bind(navigator.mediaDevices)
const enumerateDevices = navigator.mediaDevices?.enumerateDevices?.bind(navigator.mediaDevices)

// Listar cámaras disponibles
const listCameras = async () => {
  if (!enumerateDevices) return

  try {
    const devices = await enumerateDevices()
    cameras.value = devices
      .filter(device => device.kind === 'videoinput')
      .map(device => ({
        deviceId: device.deviceId,
        label: device.label || `Cámara ${cameras.value.length + 1}`,
        kind: device.kind
      }))
  } catch (err) {
    console.error('Error listing cameras:', err)
  }
}

// Solicitar acceso a la cámara
const requestCamera = async () => {
  if (!getUserMedia) {
    error.value = 'Tu navegador no soporta acceso a la cámara'
    errorHelp.value = 'Por favor usa un navegador moderno como Chrome, Firefox o Safari'
    return
  }

  isRequestingPermission.value = true
  error.value = null

  try {
    // Primero solicitar permisos básicos
    const testStream = await getUserMedia({ video: true })
    testStream.getTracks().forEach(track => track.stop())

    // Listar cámaras disponibles
    await listCameras()

    // Iniciar con la cámara preferida
    await startCamera()

    hasPermission.value = true
  } catch (err: any) {
    handleCameraError(err)
  } finally {
    isRequestingPermission.value = false
  }
}

// Iniciar stream de cámara
const startCamera = async () => {
  if (!getUserMedia) return

  const constraints: MediaStreamConstraints = {
    video: {
      width: { ideal: 1280 },
      height: { ideal: 720 },
      facingMode: currentCameraIndex.value === 0 ? 'user' : 'environment'
    },
    audio: false
  }

  // Si tenemos un deviceId específico, úsalo
  if (cameras.value.length > 0 && cameras.value[currentCameraIndex.value]) {
    const camera = cameras.value[currentCameraIndex.value]!
    if (typeof constraints.video === 'object' && constraints.video !== null) {
      constraints.video = {
        ...constraints.video,
        deviceId: { exact: camera.deviceId }
      } as MediaTrackConstraints
    }
  }

  try {
    stream.value = await getUserMedia(constraints)

    if (videoElement.value) {
      videoElement.value.srcObject = stream.value
    }
  } catch (err: any) {
    handleCameraError(err)
  }
}

// Manejar errores de cámara
const handleCameraError = (err: any) => {
  console.error('Camera error:', err)

  if (err.name === 'NotAllowedError' || err.name === 'PermissionDeniedError') {
    error.value = 'Permiso denegado'
    errorHelp.value = 'Por favor permite el acceso a la cámara en la configuración de tu navegador'
  } else if (err.name === 'NotFoundError' || err.name === 'DevicesNotFoundError') {
    error.value = 'No se encontró ninguna cámara'
    errorHelp.value = 'Asegúrate de que tu dispositivo tenga una cámara conectada'
  } else if (err.name === 'NotReadableError' || err.name === 'TrackStartError') {
    error.value = 'La cámara está en uso'
    errorHelp.value = 'Cierra otras aplicaciones que puedan estar usando la cámara'
  } else if (err.name === 'OverconstrainedError') {
    error.value = 'Configuración no compatible'
    errorHelp.value = 'Tu cámara no soporta la resolución solicitada'
  } else {
    error.value = 'Error al acceder a la cámara'
    errorHelp.value = err.message || 'Intenta recargar la página o usar otro navegador'
  }
}

// Cambiar entre cámaras
const switchCamera = async () => {
  if (cameras.value.length <= 1) return

  isSwitching.value = true

  // Detener stream actual
  stopCamera()

  // Cambiar a siguiente cámara
  currentCameraIndex.value = (currentCameraIndex.value + 1) % cameras.value.length

  // Iniciar nueva cámara
  await startCamera()

  isSwitching.value = false
}

// Capturar foto
const capture = () => {
  if (!videoElement.value || !canvasElement.value) return

  const video = videoElement.value
  const canvas = canvasElement.value

  // Configurar canvas con el tamaño del video
  canvas.width = video.videoWidth
  canvas.height = video.videoHeight

  // Dibujar frame actual del video
  const ctx = canvas.getContext('2d')
  if (!ctx) return

  ctx.drawImage(video, 0, 0, canvas.width, canvas.height)

  // Convertir a imagen
  capturedImage.value = canvas.toDataURL('image/jpeg', 0.9)

  // Detener cámara
  stopCamera()
}

// Reintentar captura
const retake = () => {
  capturedImage.value = null
  error.value = null
  requestCamera()
}

// Confirmar y enviar imagen
const confirm = () => {
  if (!canvasElement.value || !capturedImage.value) return

  canvasElement.value.toBlob(
    (blob) => {
      if (blob) {
        emit('capture', blob)
      }
    },
    'image/jpeg',
    0.9
  )
}

// Cancelar
const cancel = () => {
  stopCamera()
  emit('cancel')
}

// Reintentar
const retry = () => {
  error.value = null
  errorHelp.value = ''
  hasPermission.value = false
  requestCamera()
}

// Detener cámara
const stopCamera = () => {
  if (stream.value) {
    stream.value.getTracks().forEach(track => track.stop())
    stream.value = null
  }
}

// Cleanup al desmontar
onUnmounted(() => {
  stopCamera()
})
</script>

<style scoped>
.camera-capture {
  width: 100%;
  max-width: 600px;
  margin: 0 auto;
}

.camera-placeholder,
.camera-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 3rem 2rem;
  text-align: center;
}

.camera-active,
.camera-preview {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.video-container,
.preview-container {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  background: var(--color-gray-900);
  border-radius: 1rem;
  overflow: hidden;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}

.camera-video,
.preview-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.camera-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  pointer-events: none;
}

.camera-guide {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 70%;
  aspect-ratio: 1;
  border: 3px solid rgba(255, 255, 255, 0.5);
  border-radius: 50%;
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.3);
}

.camera-controls,
.preview-controls {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}

.capture-button {
  flex: 0 0 auto;
}

@media (max-width: 768px) {
  .video-container,
  .preview-container {
    aspect-ratio: 3 / 4;
  }

  .camera-controls,
  .preview-controls {
    flex-direction: column;
    width: 100%;
  }

  .camera-controls button,
  .preview-controls button {
    width: 100%;
  }
}
</style>
