<script setup>
import { ref, computed } from 'vue';
import { QrcodeStream } from 'vue-qrcode-reader';

/** Props y Emits */
const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  }
});

const emit = defineEmits(['update:modelValue', 'qr-detected']);

/** Refs */
const error = ref('');
const isScanning = ref(true);

/** Formatos de código de barras soportados */
const barcodeFormats = ref({
  qr_code: true,        // QR codes
  ean_13: true,         // Código de barras estándar (13 dígitos)
  ean_8: true,          // Código de barras corto (8 dígitos)
  code_128: true,       // Común en retail y logística
  code_39: true,        // Común en inventario industrial
  upc_a: true,          // Común en productos USA
  upc_e: true,          // Común en productos USA (versión corta)
  aztec: false,
  code_93: false,
  codabar: false,
  databar: false,
  databar_expanded: false,
  data_matrix: false,
  dx_film_edge: false,
  itf: false,
  maxi_code: false,
  micro_qr_code: false,
  pdf417: false,
  rm_qr_code: false,
  linear_codes: false,
  matrix_codes: false
});

// Computed para obtener solo los formatos activados
const selectedBarcodeFormats = computed(() => {
  return Object.keys(barcodeFormats.value).filter((format) => barcodeFormats.value[format]);
});

/** Métodos */
function paintBoundingBox(detectedCodes, ctx) {
  for (const detectedCode of detectedCodes) {
    const {
      boundingBox: { x, y, width, height }
    } = detectedCode;

    ctx.lineWidth = 4;
    ctx.strokeStyle = '#10b981';
    ctx.strokeRect(x, y, width, height);
  }
}

function onDetect(detectedCodes) {
  if (detectedCodes.length > 0) {
    const code = detectedCodes[0].rawValue;

    // Emitir el código escaneado al componente padre
    emit('update:modelValue', code);

    // Pausar el escaneo después de detectar
    isScanning.value = false;

    // Emitir evento con el código detectado
    emit('qr-detected', code);

    // Reactivar el escaneo después de 2 segundos
    setTimeout(() => {
      isScanning.value = true;
      error.value = '';
    }, 2000);
  }
}

function onError(err) {
  error.value = `[${err.name}]: `;

  if (err.name === 'NotAllowedError') {
    error.value += 'Necesitas otorgar permiso de acceso a la cámara';
  } else if (err.name === 'NotFoundError') {
    error.value += 'No se encontró cámara en este dispositivo';
  } else if (err.name === 'NotSupportedError') {
    error.value += 'Se requiere contexto seguro (HTTPS o localhost)';
  } else if (err.name === 'NotReadableError') {
    error.value += '¿La cámara ya está en uso?';
  } else if (err.name === 'OverconstrainedError') {
    error.value += 'Las cámaras instaladas no son adecuadas';
  } else if (err.name === 'StreamApiNotSupportedError') {
    error.value += 'No es compatible con este navegador';
  } else if (err.name === 'InsecureContextError') {
    error.value += 'El acceso a la cámara solo se permite en contexto seguro (HTTPS).';
  } else {
    error.value += err.message;
  }

  console.error('Error de cámara:', err);
}
</script>

<template>
  <div class="relative w-full h-full">
    <!-- Componente de escaneo QR y códigos de barras -->
    <QrcodeStream
      v-if="isScanning"
      @detect="onDetect"
      @error="onError"
      :track="paintBoundingBox"
      :formats="selectedBarcodeFormats"
      :constraints="{ facingMode: 'environment' }"
      class="w-full h-full rounded-lg overflow-hidden"
    >
    </QrcodeStream>

    <!-- Mensaje de éxito -->
    <div
      v-else
      class="w-full h-full rounded-lg bg-green-600 flex items-center justify-center"
    >
      <div class="text-center text-white">
        <svg
          xmlns="http://www.w3.org/2000/svg"
          class="h-16 w-16 mx-auto mb-2"
          fill="none"
          viewBox="0 0 24 24"
          stroke="currentColor"
        >
          <path
            stroke-linecap="round"
            stroke-linejoin="round"
            stroke-width="2"
            d="M5 13l4 4L19 7"
          />
        </svg>
        <p class="text-lg font-semibold">¡Código detectado!</p>
      </div>
    </div>

    <!-- Mensaje de error -->
    <div
      v-if="error"
      class="absolute bottom-0 left-0 right-0 bg-red-500 text-white p-3 text-sm"
    >
      {{ error }}
    </div>
  </div>
</template>

<style scoped>
:deep(video) {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
</style>