<template>
  <q-page padding class="scan-page">
    <!-- Job context banner -->
    <q-card v-if="jobContext" flat bordered class="q-mb-md bg-blue-1">
      <q-card-section class="q-py-sm row items-center no-wrap">
        <q-icon name="work" color="primary" class="q-mr-sm" />
        <div class="col">
          <div class="text-subtitle2">{{ jobContext.customer_name || jobContext.customer }}</div>
          <div class="text-caption text-grey" v-if="jobContext.location_name">
            <q-icon name="place" size="xs" /> {{ jobContext.location_name }}
          </div>
        </div>
        <q-btn flat dense size="sm" icon="close" @click="jobContext = null" />
      </q-card-section>
      <q-card-section class="q-pt-none q-pb-sm text-caption text-blue-grey">
        Les équipements scannés seront automatiquement liés à ce client et cette adresse.
      </q-card-section>
    </q-card>

    <!-- Camera capture button -->
    <div class="text-center">
      <q-btn
        color="primary" icon="photo_camera" label="Scanner"
        size="lg" rounded unelevated
        @click="takePhoto"
        :loading="scanner.scanning.value"
        class="q-px-xl"
      />
      <input ref="cameraInput" type="file" accept="image/*" capture="environment" class="hidden" @change="onPhoto" />
    </div>

    <!-- Pending scan indicator (signal faible) -->
    <div v-if="offline.pendingVisionCount > 0" class="text-center q-mt-sm">
      <q-chip icon="wifi_tethering_off" color="orange" text-color="white" dense clickable @click="offline.syncVisionQueue()">
        {{ offline.pendingVisionCount }} scan{{ offline.pendingVisionCount > 1 ? 's' : '' }} en attente · toucher pour réessayer
      </q-chip>
    </div>

    <!-- Last captured photo (thumbnail) -->
    <div v-if="scanner.lastPhoto.value" class="photo-preview q-mt-md">
      <img :src="scanner.lastPhoto.value" class="preview-img" @click="showFullPhoto = true" />
      <div v-if="scanner.scanning.value" class="preview-overlay">
        <q-spinner-dots size="32px" color="white" />
        <div class="text-white text-caption q-mt-xs">Analyse Gemini...</div>
      </div>
    </div>

    <!-- Error / status -->
    <div v-if="scanner.error.value" class="text-caption text-center q-mt-sm text-negative">
      {{ scanner.error.value }}
    </div>

    <!-- Manual entry -->
    <q-input v-model="manualCode" label="Saisie manuelle SN / MAC" outlined dense class="q-mt-md"
      @keyup.enter="addManual">
      <template v-slot:append>
        <q-btn flat dense icon="add" @click="addManual" :disable="!manualCode.trim()" />
      </template>
    </q-input>

    <!-- Scanned barcodes -->
    <div v-if="scanner.barcodes.value.length > 0" class="q-mt-md">
      <div class="text-subtitle2 q-mb-xs">Codes détectés ({{ scanner.barcodes.value.length }}/3)</div>
      <q-card v-for="bc in scanner.barcodes.value" :key="bc.value" class="q-mb-sm">
        <q-card-section class="q-py-sm row items-center no-wrap">
          <q-icon name="qr_code" class="q-mr-sm" color="primary" />
          <div class="col">
            <div class="text-subtitle2 mono">{{ bc.value }}</div>
          </div>
          <q-btn flat dense icon="search" @click="lookupDevice(bc.value)" :loading="lookingUp === bc.value" />
          <q-btn flat dense icon="close" color="negative" @click="scanner.removeBarcode(bc.value)" />
        </q-card-section>

        <!-- Lookup result -->
        <q-card-section v-if="lookupResults[bc.value]" class="q-pt-none">
          <div v-if="lookupResults[bc.value].found">
            <q-badge color="green" label="Trouvé" class="q-mb-xs" />
            <div class="text-caption">
              {{ lookupResults[bc.value].equipment.equipment_type }} —
              {{ lookupResults[bc.value].equipment.brand }} {{ lookupResults[bc.value].equipment.model }}
            </div>
            <div class="text-caption">
              Client: {{ lookupResults[bc.value].equipment.customer_name || lookupResults[bc.value].equipment.customer || 'Aucun' }}
            </div>
            <div v-if="!lookupResults[bc.value].equipment.service_location && !jobContext" class="q-mt-xs">
              <q-btn flat dense size="sm" color="orange" label="Lier à un service" icon="link"
                @click="openLinkDialog(bc.value, lookupResults[bc.value].equipment)" />
            </div>
            <div v-else class="text-caption text-green q-mt-xs">
              <q-icon name="check_circle" size="xs" class="q-mr-xs" />
              {{ lookupResults[bc.value].equipment.service_location }}
            </div>
            <q-btn flat dense size="sm" label="Détails" icon="open_in_new" class="q-mt-xs"
              @click="$router.push({ name: 'device', params: { serial: lookupResults[bc.value].equipment.serial_number || bc.value } })" />
          </div>
          <div v-else>
            <q-badge color="orange" label="Non trouvé" class="q-mb-xs" />
            <q-btn flat dense size="sm" color="primary" label="Créer équipement" icon="add"
              @click="openCreateDialog(bc.value)" />
          </div>
        </q-card-section>
      </q-card>
    </div>

    <!-- Photo history (small thumbnails) -->
    <div v-if="scanner.photos.value.length > 1" class="q-mt-md">
      <div class="text-caption text-grey q-mb-xs">Photos capturées</div>
      <div class="row q-gutter-xs">
        <div v-for="(p, i) in scanner.photos.value" :key="i" class="photo-thumb" @click="viewPhoto(p)">
          <img :src="p.url" />
          <q-badge v-if="p.codes.length" color="green" floating :label="p.codes.length" />
        </div>
      </div>
    </div>

    <!-- Link all to account (manual, when no job context) -->
    <div v-if="scanner.barcodes.value.length > 0 && !jobContext && hasUnlinked" class="q-mt-sm">
      <q-btn color="orange" icon="link" label="Lier les équipements à un service"
        @click="openLinkDialogForAll" outline class="full-width" />
    </div>

    <!-- Full photo viewer -->
    <q-dialog v-model="showFullPhoto" maximized>
      <q-card class="bg-black column">
        <q-card-section class="col-auto row items-center">
          <div class="text-white text-subtitle2 col">Photo</div>
          <q-btn flat round icon="close" color="white" v-close-popup />
        </q-card-section>
        <q-card-section class="col column items-center justify-center">
          <img :src="fullPhotoUrl" style="max-width:100%; max-height:80vh; object-fit:contain" />
        </q-card-section>
      </q-card>
    </q-dialog>

    <!-- Create equipment dialog -->
    <q-dialog v-model="createDialog">
      <q-card style="min-width: 320px">
        <q-card-section>
          <div class="text-h6">Nouvel équipement</div>
        </q-card-section>
        <q-card-section>
          <q-input v-model="newEquip.serial_number" label="Numéro de série" outlined dense readonly class="q-mb-sm" />
          <q-select v-model="newEquip.equipment_type" :options="eqTypes" label="Type" outlined dense class="q-mb-sm" />
          <q-input v-model="newEquip.brand" label="Marque" outlined dense class="q-mb-sm" />
          <q-input v-model="newEquip.model" label="Modèle" outlined dense class="q-mb-sm" />
          <q-input v-model="newEquip.mac_address" label="MAC (optionnel)" outlined dense class="q-mb-sm" />
        </q-card-section>
        <q-card-actions align="right">
          <q-btn flat label="Annuler" v-close-popup />
          <q-btn color="primary" label="Créer" @click="createEquipment" :loading="creating" />
        </q-card-actions>
      </q-card>
    </q-dialog>

    <!-- Link device to service dialog -->
    <q-dialog v-model="linkDialog">
      <q-card style="min-width: 340px">
        <q-card-section>
          <div class="text-h6">Lier à un service</div>
          <div class="text-caption text-grey mono">{{ linkTarget?.serial_number }}</div>
        </q-card-section>
        <q-card-section>
          <q-input v-model="linkSearch" label="Rechercher client" outlined dense class="q-mb-sm"
            @update:model-value="searchCustomers" debounce="400">
            <template v-slot:append><q-icon name="search" /></template>
          </q-input>
          <q-list v-if="customerResults.length" bordered separator class="q-mb-sm" style="max-height: 150px; overflow-y: auto">
            <q-item v-for="c in customerResults" :key="c.name" clickable @click="selectCustomer(c)">
              <q-item-section>
                <q-item-label>{{ c.customer_name || c.name }}</q-item-label>
                <q-item-label caption>{{ c.name }}</q-item-label>
              </q-item-section>
            </q-item>
          </q-list>
          <div v-if="selectedCustomer">
            <div class="text-subtitle2 q-mb-xs">{{ selectedCustomer.customer_name || selectedCustomer.name }}</div>
            <div v-if="loadingLocations" class="text-center q-py-sm"><q-spinner size="sm" /></div>
            <q-list v-else-if="serviceLocations.length" bordered separator>
              <q-item v-for="loc in serviceLocations" :key="loc.name" clickable
                :class="{ 'bg-blue-1': selectedLocation?.name === loc.name }"
                @click="selectedLocation = loc">
                <q-item-section>
                  <q-item-label>{{ loc.location_name || loc.name }}</q-item-label>
                  <q-item-label caption>{{ loc.address_line }} {{ loc.city }}</q-item-label>
                </q-item-section>
                <q-item-section side v-if="selectedLocation?.name === loc.name">
                  <q-icon name="check_circle" color="primary" />
                </q-item-section>
              </q-item>
            </q-list>
            <div v-else class="text-caption text-grey">Aucune adresse de service</div>
          </div>
        </q-card-section>
        <q-card-actions align="right">
          <q-btn flat label="Annuler" v-close-popup />
          <q-btn color="primary" label="Lier" :disable="!selectedCustomer || !selectedLocation"
            @click="linkDeviceToService" :loading="linkingSingle" />
        </q-card-actions>
      </q-card>
    </q-dialog>
  </q-page>
</template>

<script setup>
import { ref, computed } from 'vue'
import { useRoute } from 'vue-router'
import { useScanner } from 'src/composables/useScanner'
import { listDocs, createDoc, updateDoc } from 'src/api/erp'
import { useOfflineStore } from 'src/stores/offline'
import { Notify } from 'quasar'

const route = useRoute()
const offline = useOfflineStore()
const scanner = useScanner({
  onNewCode: (code) => {
    Notify.create({ type: 'positive', message: code, timeout: 2500, icon: 'qr_code', color: 'deep-purple' })
    lookupDevice(code)
  },
})

const cameraInput = ref(null)
const manualCode = ref('')
const lookingUp = ref(null)
const lookupResults = ref({})
const createDialog = ref(false)
const creating = ref(false)

// Photo viewer
const showFullPhoto = ref(false)
const fullPhotoUrl = ref('')

// Link dialog
const linkDialog = ref(false)
const linkTarget = ref(null)
const linkTargetBarcode = ref('')
const linkSearch = ref('')
const customerResults = ref([])
const selectedCustomer = ref(null)
const serviceLocations = ref([])
const selectedLocation = ref(null)
const loadingLocations = ref(false)
const linkingSingle = ref(false)

const eqTypes = ['ONT', 'Modem', 'Routeur', 'Décodeur TV', 'VoIP', 'Amplificateur', 'Splitter', 'Câble', 'Autre']
const jobContext = ref(route.query.job ? {
  job: route.query.job,
  customer: route.query.customer,
  customer_name: route.query.customer_name,
  location: route.query.location,
  location_name: route.query.location_name,
} : null)
const newEquip = ref({ serial_number: '', equipment_type: 'ONT', brand: '', model: '', mac_address: '' })

const hasUnlinked = computed(() =>
  scanner.barcodes.value.some(bc => {
    const r = lookupResults.value[bc.value]
    return r?.found && !r.equipment.service_location
  })
)

// --- Camera ---

function takePhoto () {
  // Reset the input so same file triggers change
  if (cameraInput.value) cameraInput.value.value = ''
  cameraInput.value?.click()
}

async function onPhoto (e) {
  const file = e.target.files?.[0]
  if (!file) return
  // Codes are delivered through the onNewCode callback registered on the
  // scanner — fires both for sync scans and for queued scans that complete
  // later when the signal comes back.
  await scanner.processPhoto(file)
}

function viewPhoto (photo) {
  fullPhotoUrl.value = photo.url
  showFullPhoto.value = true
}

// --- Manual entry ---

function addManual () {
  const code = manualCode.value.trim()
  if (!code) return
  if (scanner.barcodes.value.length >= 3) {
    Notify.create({ type: 'warning', message: 'Maximum 3 codes' })
    return
  }
  if (!scanner.barcodes.value.find(b => b.value === code)) {
    scanner.barcodes.value.push({ value: code, region: 'manuel' })
    lookupDevice(code)
  }
  manualCode.value = ''
}

// --- Device lookup ---

async function lookupDevice (serial) {
  lookingUp.value = serial
  try {
    const results = await listDocs('Service Equipment', {
      filters: { serial_number: serial },
      fields: ['name', 'serial_number', 'equipment_type', 'brand', 'model', 'customer', 'customer_name',
        'service_location', 'status', 'mac_address'],
      limit: 1,
    })
    if (results.length > 0) {
      lookupResults.value[serial] = { found: true, equipment: results[0] }
      return
    }
    const byBarcode = await listDocs('Service Equipment', {
      filters: { barcode: serial },
      fields: ['name', 'serial_number', 'equipment_type', 'brand', 'model', 'customer', 'customer_name',
        'service_location', 'status', 'mac_address'],
      limit: 1,
    })
    if (byBarcode.length > 0) {
      lookupResults.value[serial] = { found: true, equipment: byBarcode[0] }
      return
    }
    const normalized = serial.replace(/[:\-\.]/g, '').toUpperCase()
    if (normalized.length === 12 && /^[A-F0-9]+$/.test(normalized)) {
      const byMac = await listDocs('Service Equipment', {
        filters: { mac_address: ['like', `%${normalized.slice(-6)}%`] },
        fields: ['name', 'serial_number', 'equipment_type', 'brand', 'model', 'customer', 'customer_name',
          'service_location', 'status', 'mac_address'],
        limit: 1,
      })
      if (byMac.length > 0) {
        lookupResults.value[serial] = { found: true, equipment: byMac[0] }
        return
      }
    }
    lookupResults.value[serial] = { found: false }
  } catch {
    lookupResults.value[serial] = { found: false }
  } finally {
    lookingUp.value = null
  }

  // Auto-link to job context if device found but not yet linked
  const result = lookupResults.value[serial]
  if (result?.found && jobContext.value?.customer && !result.equipment.service_location) {
    await autoLinkToJob(serial, result.equipment)
  }
}

// --- Auto-link device to job context ---

async function autoLinkToJob (serial, equipment) {
  if (!jobContext.value?.customer) return
  const updates = { customer: jobContext.value.customer }
  if (jobContext.value.location) updates.service_location = jobContext.value.location
  try {
    await updateDoc('Service Equipment', equipment.name, updates)
    equipment.customer = jobContext.value.customer
    equipment.customer_name = jobContext.value.customer_name
    if (jobContext.value.location) equipment.service_location = jobContext.value.location
    // Update lookupResults
    if (lookupResults.value[serial]) {
      lookupResults.value[serial].equipment = { ...equipment }
    }
    Notify.create({
      type: 'positive',
      message: 'Lié à ' + (jobContext.value.customer_name || jobContext.value.customer),
      caption: jobContext.value.location_name || undefined,
      icon: 'link',
    })
  } catch (e) {
    Notify.create({ type: 'negative', message: 'Erreur liaison: ' + e.message })
  }
}

// --- Create equipment ---

function openCreateDialog (serial) {
  newEquip.value = { serial_number: serial, equipment_type: 'ONT', brand: '', model: '', mac_address: '' }
  createDialog.value = true
}

async function createEquipment () {
  creating.value = true
  const data = {
    ...newEquip.value,
    status: 'Actif',
    customer: jobContext.value?.customer || '',
    service_location: jobContext.value?.location || '',
  }
  try {
    if (offline.online) {
      const doc = await createDoc('Service Equipment', data)
      lookupResults.value[data.serial_number] = { found: true, equipment: doc }
      Notify.create({ type: 'positive', message: 'Équipement créé' })
    } else {
      await offline.enqueue({ type: 'create', doctype: 'Service Equipment', data })
      Notify.create({ type: 'info', message: 'Sauvegardé hors ligne' })
    }
    createDialog.value = false
  } catch (e) {
    Notify.create({ type: 'negative', message: 'Erreur: ' + e.message })
  } finally {
    creating.value = false
  }
}

// --- Link dialog for unlinked devices (no job context) ---

function openLinkDialogForAll () {
  // Find first unlinked device
  for (const bc of scanner.barcodes.value) {
    const r = lookupResults.value[bc.value]
    if (r?.found && !r.equipment.service_location) {
      openLinkDialog(bc.value, r.equipment)
      return
    }
  }
}

// --- Link device to service ---

function openLinkDialog (barcode, equipment) {
  linkTarget.value = equipment
  linkTargetBarcode.value = barcode
  linkSearch.value = ''
  customerResults.value = []
  selectedCustomer.value = null
  serviceLocations.value = []
  selectedLocation.value = null
  if (equipment.customer) {
    selectedCustomer.value = { name: equipment.customer, customer_name: equipment.customer_name }
    loadServiceLocations(equipment.customer)
  }
  linkDialog.value = true
}

async function searchCustomers (text) {
  if (!text || text.length < 2) { customerResults.value = []; return }
  try {
    customerResults.value = await listDocs('Customer', {
      filters: { customer_name: ['like', `%${text}%`] },
      fields: ['name', 'customer_name'],
      limit: 10,
    })
  } catch { customerResults.value = [] }
}

async function selectCustomer (customer) {
  selectedCustomer.value = customer
  customerResults.value = []
  linkSearch.value = ''
  selectedLocation.value = null
  await loadServiceLocations(customer.name)
}

async function loadServiceLocations (customerId) {
  loadingLocations.value = true
  try {
    serviceLocations.value = await listDocs('Service Location', {
      filters: { customer: customerId },
      fields: ['name', 'location_name', 'address_line', 'city', 'connection_type'],
      limit: 50,
    })
  } catch { serviceLocations.value = [] }
  finally { loadingLocations.value = false }
}

async function linkDeviceToService () {
  if (!linkTarget.value || !selectedCustomer.value || !selectedLocation.value) return
  linkingSingle.value = true
  try {
    await updateDoc('Service Equipment', linkTarget.value.name, {
      customer: selectedCustomer.value.name,
      service_location: selectedLocation.value.name,
    })
    linkTarget.value.customer = selectedCustomer.value.name
    linkTarget.value.customer_name = selectedCustomer.value.customer_name
    linkTarget.value.service_location = selectedLocation.value.name
    if (lookupResults.value[linkTargetBarcode.value]) {
      lookupResults.value[linkTargetBarcode.value].equipment = { ...linkTarget.value }
    }
    Notify.create({ type: 'positive', message: 'Lié à ' + (selectedLocation.value.location_name || selectedLocation.value.name) })
    linkDialog.value = false
  } catch (e) {
    Notify.create({ type: 'negative', message: 'Erreur: ' + e.message })
  } finally {
    linkingSingle.value = false
  }
}
</script>

<style lang="scss" scoped>
.scan-page {
  padding-bottom: 16px !important;
}

.photo-preview {
  position: relative;
  text-align: center;
}

.preview-img {
  max-width: 100%;
  max-height: 250px;
  border-radius: 12px;
  cursor: pointer;
}

.preview-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: rgba(0,0,0,0.5);
  border-radius: 12px;
}

.photo-thumb {
  position: relative;
  width: 60px;
  height: 60px;
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
  img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}
</style>
