<template>
  <q-dialog :model-value="modelValue" @update:model-value="$emit('update:modelValue', $event)" :maximized="$q.screen.lt.md" persistent>
    <q-card class="qw-card column no-wrap">
      <q-card-section class="row items-center no-wrap q-py-sm">
        <q-icon name="request_quote" size="22px" color="teal-7" class="q-mr-sm" />
        <div class="text-h6 col ellipsis">Nouvelle soumission</div>
        <q-btn flat round dense icon="close" @click="$emit('update:modelValue', false)" />
      </q-card-section>

      <!-- Progression (slides) -->
      <div class="qw-steps row items-center no-wrap q-px-md q-pb-sm">
        <template v-for="(s, i) in steps" :key="s.key">
          <div class="qw-step row items-center no-wrap" :class="{ done: i < stepIdx, current: i === stepIdx }">
            <div class="qw-dot row items-center justify-center"><q-icon v-if="i < stepIdx" name="check" size="14px" /><span v-else>{{ i + 1 }}</span></div>
            <div class="qw-step-lbl gt-xs">{{ s.label }}</div>
          </div>
          <div v-if="i < steps.length - 1" class="qw-line col" :class="{ done: i < stepIdx }"></div>
        </template>
      </div>
      <q-separator />

      <q-carousel v-model="step" animated swipeable transition-prev="slide-right" transition-next="slide-left" class="qw-body col" :navigation="false" :arrows="false" keep-alive>
        <!-- 1 · ADRESSE + qualification fibre -->
        <q-carousel-slide name="adresse" class="q-pa-md column no-wrap">
          <div class="text-subtitle1 text-weight-medium">Adresse de service</div>
          <div class="text-caption text-grey-7 q-mb-sm">Cherchez l'adresse civique — on vérifie la disponibilité de la fibre avant tout (base RQA + réseau Targo).</div>
          <q-input dense outlined v-model="addrQuery" placeholder="Ex. 123 rue Principale, Ville…" :loading="addrLoading" clearable autofocus @update:model-value="searchAddr">
            <template #prepend><q-icon name="place" /></template>
          </q-input>
          <q-list v-if="addrResults.length" bordered class="qw-results q-mt-xs">
            <q-item v-for="(a, i) in addrResults" :key="i" clickable @click="pickAddress(a)">
              <q-item-section avatar style="min-width:30px"><q-icon :name="a.fiber_available ? 'check_circle' : 'cancel'" :color="a.fiber_available ? 'positive' : 'grey-5'" /></q-item-section>
              <q-item-section><q-item-label>{{ a.address_full }}</q-item-label><q-item-label caption>{{ a.fiber_available ? ('Fibre disponible' + (a.max_speed ? ' · jusqu\'à ' + a.max_speed + ' Mbps' : '')) : 'Fibre non disponible à cette adresse' }}</q-item-label></q-item-section>
            </q-item>
          </q-list>
          <q-banner v-if="chosen.address" class="qw-chosen q-mt-md" :class="chosen.fiber ? 'bg-green-1' : 'bg-orange-1'">
            <template #avatar><q-icon :name="chosen.fiber ? 'wifi' : 'wifi_off'" :color="chosen.fiber ? 'positive' : 'orange-8'" /></template>
            <div class="text-weight-medium">{{ chosen.address }}</div>
            <div class="text-caption">{{ chosen.fiber ? ('✓ Fibre disponible' + (chosen.maxSpeed ? ' — jusqu\'à ' + chosen.maxSpeed + ' Mbps' : '')) : '⚠ Fibre non desservie ici — soumission possible mais à valider (hors zone / à déployer).' }}</div>
          </q-banner>
          <!-- Mini-carte : repère (✓ vert) sur l'adresse trouvée → confirmation visuelle ; bouton satellite (voir le bâtiment) -->
          <div v-show="chosen.address && chosen.lat != null" class="qw-map-wrap q-mt-sm">
            <div ref="qwMapEl" class="qw-map"></div>
            <q-btn round dense size="sm" class="qw-sat-btn" :color="satellitePref ? 'primary' : 'grey-9'" text-color="white" :icon="satellitePref ? 'map' : 'satellite_alt'" @click="toggleMiniSat"><q-tooltip>{{ satellitePref ? 'Vue carte' : 'Vue satellite' }}</q-tooltip></q-btn>
          </div>
        </q-carousel-slide>

        <!-- 2 · FORFAITS — services + promos VISIBLES avant de demander le contact (lead-first) -->
        <q-carousel-slide name="forfaits" class="q-pa-md column no-wrap">
          <div class="text-subtitle1 text-weight-medium">Forfaits Internet<span v-if="chosen.fiber"> disponibles ici</span></div>
          <div class="text-caption text-grey-7 q-mb-sm">Prix promotionnels — rabais 24 mois déjà appliqué. Choisissez-en un (facultatif) ou continuez.</div>
          <div v-if="!chosen.fiber" class="text-caption text-orange-8 q-mb-sm"><q-icon name="info" size="14px" /> Fibre à valider à cette adresse — prix indicatifs.</div>
          <div class="qw-tiers column q-gutter-sm">
            <q-card v-for="t in tiers" :key="t.id" flat bordered class="qw-tier" :class="{ sel: chosen.tier && chosen.tier.id === t.id }" @click="pickTier(t)">
              <q-card-section class="row items-center no-wrap q-py-sm">
                <q-icon :name="chosen.tier && chosen.tier.id === t.id ? 'check_circle' : (t.icon || 'wifi')" size="26px" :color="chosen.tier && chosen.tier.id === t.id ? 'teal-7' : 'grey-6'" class="q-mr-md" />
                <div class="col">
                  <div class="row items-center no-wrap">
                    <span class="text-weight-bold">{{ t.label }}</span>
                    <q-badge v-if="t.badge" :color="t.default ? 'teal-7' : 'grey-6'" class="q-ml-sm">{{ t.badge }}</q-badge>
                  </div>
                  <div class="text-caption text-grey-7">{{ t.speed }} · {{ t.desc }}</div>
                </div>
                <div class="text-right q-pl-sm">
                  <div class="text-h6 text-teal-8 text-weight-bold" style="line-height:1.1">{{ money(t.price_effective) }}<span class="text-caption text-grey-6">/mois</span></div>
                  <div v-if="t.price_base > t.price_effective" class="text-caption text-grey-5"><s>{{ money(t.price_base) }}</s></div>
                </div>
              </q-card-section>
            </q-card>
          </div>
          <div class="text-caption text-grey-6 q-mt-sm">+ Installation {{ money(99.95) }} (frais unique)</div>
        </q-carousel-slide>

        <!-- 3 · CONTACT (fiche existante ou nouveau prospect) -->
        <q-carousel-slide name="contact" class="q-pa-md column no-wrap">
          <div class="text-subtitle1 text-weight-medium">Contact</div>
          <div class="text-caption text-grey-7 q-mb-sm">Associez une fiche existante, ou créez un prospect (courriel <b>ou</b> mobile suffit pour la confirmation).</div>
          <q-input dense outlined v-model="custQuery" placeholder="Chercher par nom · téléphone · courriel…" :loading="custLoading" clearable @update:model-value="searchCust" class="q-mb-xs">
            <template #prepend><q-icon name="search" /></template>
          </q-input>
          <q-list v-if="custResults.length" bordered class="qw-results q-mb-sm">
            <q-item v-for="c in custResults" :key="c.name" clickable @click="pickCustomer(c)" :active="chosen.customer && chosen.customer.name === c.name" active-class="bg-teal-1">
              <q-item-section avatar style="min-width:30px"><q-icon name="badge" color="teal-7" /></q-item-section>
              <q-item-section><q-item-label>{{ c.customer_name || c.name }}</q-item-label><q-item-label caption>{{ [c.cell_phone || c.phone, c.email_id].filter(Boolean).join(' · ') || c.name }}</q-item-label></q-item-section>
            </q-item>
          </q-list>
          <q-banner v-if="chosen.customer" class="bg-teal-1 q-mb-sm">
            <template #avatar><q-icon name="how_to_reg" color="teal-8" /></template>
            Fiche existante : <b>{{ chosen.customer.customer_name || chosen.customer.name }}</b>
            <template #action><q-btn flat dense no-caps label="Changer" @click="chosen.customer = null" /></template>
          </q-banner>
          <template v-else>
            <div class="text-caption text-grey-6 q-mb-xs">…ou nouveau prospect :</div>
            <q-btn-toggle v-model="lead.type" :options="[{label:'Résidentiel',value:'Individual'},{label:'Commercial',value:'Company'}]" unelevated dense no-caps toggle-color="teal-7" color="grey-3" text-color="grey-8" class="q-mb-sm" />
            <div class="row q-col-gutter-sm">
              <q-input class="col-6" dense outlined v-model="lead.first" label="Prénom" />
              <q-input class="col-6" dense outlined v-model="lead.last" :label="lead.type === 'Company' ? 'Entreprise' : 'Nom'" />
              <q-input class="col-6" dense outlined v-model="lead.email" label="Courriel" type="email" :error="showLeadErr && !leadContactOk" />
              <q-input class="col-6" dense outlined v-model="lead.mobile" label="Mobile" mask="(###) ###-####" :error="showLeadErr && !leadContactOk" />
            </div>
            <div v-if="showLeadErr && !leadContactOk" class="text-caption text-negative q-mt-xs">Au moins un courriel ou un mobile est requis.</div>
          </template>
        </q-carousel-slide>
      </q-carousel>

      <q-separator />
      <q-card-actions class="row items-center q-px-md q-py-sm">
        <q-btn flat no-caps icon="chevron_left" label="Retour" :disable="stepIdx === 0" @click="go(stepIdx - 1)" />
        <q-space />
        <q-btn v-if="step === 'adresse'" unelevated no-caps color="teal-7" icon-right="chevron_right" label="Voir les forfaits" :disable="!chosen.address" @click="go(1)" />
        <q-btn v-else-if="step === 'forfaits'" unelevated no-caps color="teal-7" icon-right="chevron_right" label="Continuer" @click="go(2)" />
        <q-btn v-else unelevated no-caps color="teal-8" icon-right="request_quote" label="Continuer vers la soumission" :loading="submitting" @click="finish" />
      </q-card-actions>
    </q-card>
  </q-dialog>
</template>

<script setup>
import { ref, reactive, computed, watch, nextTick, onBeforeUnmount } from 'vue'
import { useQuasar } from 'quasar'
import { useAddressSearch } from 'src/composables/useAddressSearch'
import { createPlanMap, addSatelliteLayer, satellitePref, setSatellitePref, setSatelliteVisible } from 'src/config/basemap' // init carte MapLibre/OSM commune + satellite ESRI
import { listDocs, createDoc } from 'src/api/erp'
import { INTERNET_HERO_TIERS } from 'src/data/wizard-constants' // forfaits « héros » (prix promo 24 mois) — vitrine AVANT le contact

const props = defineProps({ modelValue: Boolean })
// « qualified » : émis avec le customer (doc ERPNext) prêt pour ProjectWizard, + l'adresse/fibre + le forfait d'intérêt.
const emit = defineEmits(['update:modelValue', 'qualified'])
const $q = useQuasar()

// Ordre lead-first : Adresse (dispo fibre) → Forfaits (services + promos VISIBLES avant de demander quoi que ce soit) → Contact.
const steps = [{ key: 'adresse', label: 'Adresse' }, { key: 'forfaits', label: 'Forfaits' }, { key: 'contact', label: 'Contact' }]
const step = ref('adresse')
const stepIdx = computed(() => Math.max(0, steps.findIndex(s => s.key === step.value)))
function go (i) { const n = Math.min(steps.length - 1, Math.max(0, i)); step.value = steps[n].key }

// ── Étape 1 : adresse + fibre ──
const { addrResults, addrLoading, searchAddr } = useAddressSearch()
const addrQuery = ref('')
const chosen = reactive({ address: '', ville: '', code_postal: '', lat: null, lon: null, fiber: false, maxSpeed: null, zone: null, customer: null, tier: null })

// ── Étape « Forfaits » : vitrine des services + promos à l'adresse, AVANT de demander le contact ──
const tiers = INTERNET_HERO_TIERS
function money (n) { return (Math.round(Number(n || 0) * 100) / 100).toFixed(2).replace('.', ',') + ' $' }
function pickTier (t) { chosen.tier = (chosen.tier && chosen.tier.id === t.id) ? null : t } // clic = sélectionne / re-clic = désélectionne (facultatif)
function pickAddress (a) {
  chosen.address = a.address_full; chosen.ville = a.ville || ''; chosen.code_postal = a.code_postal || ''
  chosen.lat = a.latitude != null ? +a.latitude : null; chosen.lon = a.longitude != null ? +a.longitude : null
  chosen.fiber = !!a.fiber_available; chosen.maxSpeed = a.max_speed || null; chosen.zone = a.zone_tarifaire != null ? a.zone_tarifaire : null // zone tarifaire → le prix dépend de l'adresse
  addrResults.value = []; addrQuery.value = a.address_full
}

// ── Mini-carte : repère (✓ vert) sur l'adresse trouvée (MapLibre/OSM auto-hébergé) ──
const qwMapEl = ref(null); let _qwMap = null; let _qwMarker = null
function initMiniMap () {
  if (!qwMapEl.value || chosen.lat == null || chosen.lon == null) return
  if (_qwMap) { _qwMap.setCenter([chosen.lon, chosen.lat]); if (_qwMarker) _qwMarker.setLngLat([chosen.lon, chosen.lat]); setTimeout(() => { try { _qwMap.resize() } catch (e) {} }, 60); return }
  _qwMap = createPlanMap(qwMapEl.value, { center: [chosen.lon, chosen.lat], zoom: 15 })
  _qwMap.on('load', () => {
    try { _qwMap.resize() } catch (e) {}
    addSatelliteLayer(_qwMap, satellitePref.value) // satellite (voir le bâtiment) — masqué par défaut, bouton pour basculer
    const el = document.createElement('div'); el.className = 'qw-pin'; el.innerHTML = '<span class="material-icons">check</span>'
    _qwMarker = new window.mapboxgl.Marker({ element: el, anchor: 'bottom' }).setLngLat([chosen.lon, chosen.lat]).addTo(_qwMap)
  })
}
function toggleMiniSat () { setSatellitePref(!satellitePref.value); if (_qwMap) setSatelliteVisible(_qwMap, satellitePref.value) }
watch(satellitePref, (v) => { if (_qwMap) setSatelliteVisible(_qwMap, v) })
function destroyMiniMap () { if (_qwMap) { try { _qwMap.remove() } catch (e) {} _qwMap = null; _qwMarker = null } }
watch(() => [props.modelValue, step.value, chosen.lat, chosen.lon], () => {
  if (props.modelValue && step.value === 'adresse' && chosen.lat != null) nextTick(() => setTimeout(initMiniMap, 80))
})
watch(() => props.modelValue, (open) => { if (!open) destroyMiniMap() })
onBeforeUnmount(destroyMiniMap)

// ── Étape 2 : contact (recherche fiche + création prospect) ──
const custQuery = ref(''); const custResults = ref([]); const custLoading = ref(false); let custT = null
const lead = reactive({ type: 'Individual', first: '', last: '', email: '', mobile: '' })
const showLeadErr = ref(false)
const leadContactOk = computed(() => !!(lead.email.trim() || lead.mobile.replace(/\D/g, '').length >= 10))
function searchCust (q) {
  clearTimeout(custT); if (!q || q.trim().length < 3) { custResults.value = []; return }
  custLoading.value = true
  custT = setTimeout(async () => {
    try {
      const digits = q.replace(/\D/g, '')
      const or = [['customer_name', 'like', '%' + q + '%'], ['email_id', 'like', '%' + q + '%']]
      if (digits.length >= 4) or.push(['cell_phone', 'like', '%' + digits.slice(-10) + '%'], ['phone', 'like', '%' + digits.slice(-10) + '%'])
      const r = await listDocs('Customer', { or_filters: or, fields: ['name', 'customer_name', 'cell_phone', 'phone', 'email_id'], limit: 8 })
      custResults.value = Array.isArray(r) ? r : (r.data || [])
    } catch (e) { custResults.value = [] } finally { custLoading.value = false }
  }, 320)
}
function pickCustomer (c) { chosen.customer = c; custResults.value = [] }

// Cherche une fiche EXISTANTE par courriel/mobile → évite de créer un doublon (garde-fou).
async function findExistingCustomer (email, mobile) {
  const or = []; const em = (email || '').trim(); const digits = (mobile || '').replace(/\D/g, '')
  if (em) or.push(['email_id', '=', em])
  if (digits.length >= 10) { const d = digits.slice(-10); or.push(['cell_phone', 'like', '%' + d + '%'], ['phone', 'like', '%' + d + '%']) }
  if (!or.length) return null
  try { const r = await listDocs('Customer', { or_filters: or, fields: ['name', 'customer_name', 'cell_phone', 'phone', 'email_id'], limit: 1 }); const rows = Array.isArray(r) ? r : (r.data || []); return rows[0] || null } catch (e) { return null }
}
// Message d'erreur LISIBLE (jamais le stack trace Frappe brut).
function friendlyError (e) {
  const m = String((e && e.message) || e || '')
  if (/duplicate|unique|already exists/i.test(m)) return 'Un client avec ces coordonnées existe déjà — cherchez-le dans l\'étape « Contact ».'
  if (/mandatory|required|reqd/i.test(m)) return 'Il manque une information obligatoire pour créer le client.'
  if (/permission|not permitted|forbidden|\b403\b/i.test(m)) return 'Permission insuffisante pour créer un client.'
  return 'Impossible de créer le prospect. Réessayez, ou cherchez une fiche existante.'
}
const submitting = ref(false)
async function finish () {
  if (!chosen.customer) {
    if (!leadContactOk.value) { showLeadErr.value = true; return }
    submitting.value = true
    try {
      // 1) DÉ-DUP : ce courriel/mobile correspond-il déjà à une fiche ? → on la réutilise (pas de doublon).
      const existing = await findExistingCustomer(lead.email, lead.mobile)
      if (existing) {
        chosen.customer = existing
        $q.notify({ type: 'info', icon: 'how_to_reg', message: 'Fiche existante réutilisée — ' + (existing.customer_name || existing.name), timeout: 2600 })
      } else {
        const name = [lead.first.trim(), lead.last.trim()].filter(Boolean).join(' ') || (lead.email || lead.mobile)
        const doc = await createDoc('Customer', {
          customer_name: name, customer_type: lead.type, customer_group: lead.type === 'Company' ? 'Commercial' : 'Individual', territory: 'Canada',
          ...(lead.email.trim() ? { email_id: lead.email.trim() } : {}), ...(lead.mobile.replace(/\D/g, '') ? { cell_phone: lead.mobile } : {}),
        })
        chosen.customer = doc && (doc.data || doc)
        $q.notify({ type: 'positive', icon: 'person_add', message: 'Prospect créé — ' + name, timeout: 2000 })
      }
    } catch (e) { $q.notify({ type: 'negative', message: friendlyError(e) }); submitting.value = false; return }
    submitting.value = false
  }
  // Handoff : ProjectWizard (panier + rabais rab-x + devis + acceptation) prend le relais, pré-rempli.
  // On transmet le forfait d'intérêt (facultatif) pour pré-remplir le panier — le client l'a déjà vu/choisi.
  emit('qualified', { customer: chosen.customer, address: { address: chosen.address, ville: chosen.ville, code_postal: chosen.code_postal, lat: chosen.lat, lon: chosen.lon, fiber: chosen.fiber, zone: chosen.zone }, tier: chosen.tier ? { id: chosen.tier.id, code: chosen.tier.code, label: chosen.tier.label } : null })
  emit('update:modelValue', false)
}
</script>

<style scoped>
.qw-card { width: 620px; max-width: 96vw; height: 70vh; max-height: 720px; }
.q-dialog--maximized .qw-card { width: 100%; height: 100%; max-height: none; }
.qw-steps { gap: 4px; }
.qw-step { gap: 6px; } .qw-dot { width: 24px; height: 24px; border-radius: 50%; background: #e2e8f0; color: #64748b; font-size: 12px; font-weight: 700; flex: 0 0 auto; transition: all .2s; }
.qw-step.current .qw-dot { background: #0f766e; color: #fff; } .qw-step.done .qw-dot { background: #14b8a6; color: #fff; }
.qw-step-lbl { font-size: 12px; color: #64748b; font-weight: 600; } .qw-step.current .qw-step-lbl { color: #0f766e; }
.qw-line { height: 2px; background: #e2e8f0; margin: 0 6px; border-radius: 2px; } .qw-line.done { background: #14b8a6; }
.qw-body { min-height: 0; } .qw-body :deep(.q-carousel__slide) { overflow-y: auto; }
.qw-results { border-radius: 8px; max-height: 260px; overflow-y: auto; }
.qw-chosen { border-radius: 8px; }
.qw-tier { cursor: pointer; border-radius: 10px; transition: border-color .15s, background .15s, box-shadow .15s; }
.qw-tier:hover { border-color: #14b8a6; }
.qw-tier.sel { border-color: #0f766e; background: #f0fdfa; box-shadow: 0 0 0 1px #0f766e inset; }
.qw-map-wrap { position: relative; }
.qw-map { height: 180px; border-radius: 10px; overflow: hidden; border: 1px solid #e2e8f0; }
.qw-sat-btn { position: absolute; top: 6px; left: 6px; z-index: 3; }
/* Repère « adresse trouvée » : goutte verte + ✓ blanc */
:deep(.qw-pin) { width: 30px; height: 30px; border-radius: 50% 50% 50% 0; background: #16a34a; transform: rotate(-45deg); display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 6px rgba(0,0,0,.3); border: 2px solid #fff; }
:deep(.qw-pin .material-icons) { transform: rotate(45deg); color: #fff; font-size: 16px; }
</style>
