<template>
  <q-page padding>
    <div class="row items-center q-mb-md">
      <q-btn flat dense icon="arrow_back" to="/rapports" class="q-mr-sm" />
      <div class="text-h6 text-weight-bold">Clients qui paient cher — Internet</div>
      <q-space />
      <q-btn flat dense icon="travel_explore" class="q-mr-sm"
             :label="svcBusy ? `Concurrence ${svcProgress.done}/${svcProgress.total}` : 'Concurrence'"
             :loading="svcBusy" :disable="!rows.length" @click="fetchServiceability(rows)">
        <q-tooltip max-width="280px">Vérifie, pour chaque adresse, les fournisseurs Internet disponibles (données ouvertes Québec IHV). Cogeco surligné = alternative existante = risque de churn.</q-tooltip>
      </q-btn>
      <q-btn flat dense icon="download" label="CSV" :href="csvUrl" :disable="!rows.length" />
    </div>

    <div class="text-caption text-grey-7 q-mb-md" style="max-width:820px">
      Total mensuel net du service Internet (forfait + rabais récurrents, forfaits annuels
      ramenés au mois) par adresse de service, depuis la base legacy.
      <strong>Comptes clients actifs uniquement</strong> — exclut les comptes résiliés,
      prospects, relais/infrastructure et propriétaires-hébergeurs. Exclut aussi TV,
      téléphonie, frais ponctuels (équipement, installation) et crédits promo expirés.
      Sert à repérer les clients qui gagneraient à être déplacés vers un forfait mieux adapté.
    </div>

    <!-- Filters -->
    <div class="row q-col-gutter-sm q-mb-md items-end">
      <div class="col-auto">
        <q-input v-model.number="threshold" type="number" min="0" step="5" label="Seuil $/mois"
                 dense outlined style="width:130px" />
      </div>
      <div class="col-auto">
        <q-select v-model="segment" :options="segmentOptions" emit-value map-options
                  label="Segment" dense outlined style="width:170px" />
      </div>
      <div class="col-auto">
        <q-toggle v-model="addons" label="Inclure add-ons (IP fixe, etc.)" />
      </div>
      <div class="col-auto">
        <q-btn color="primary" label="Générer" icon="play_arrow" @click="loadReport" :loading="loading" />
      </div>
    </div>

    <!-- Data freshness banner — the legacy copy is a snapshot, not live -->
    <q-banner v-if="loaded && dataAsOf" dense rounded
              :class="staleClass" class="q-mb-md">
      <template #avatar><q-icon :name="isStale ? 'warning' : 'schedule'" /></template>
      Données legacy au <strong>{{ formatDate(dataAsOf) }}</strong>
      <span v-if="isStale"> — copie figée ({{ daysOld }} jours). Les renégociations,
        nouveaux rabais et résiliations récents ne sont pas reflétés.</span>
    </q-banner>

    <!-- Summary cards -->
    <div v-if="loaded" class="row q-col-gutter-sm q-mb-md">
      <div class="col-auto">
        <div class="ops-card text-center" style="min-width:140px">
          <div class="text-caption text-grey-6">Adresses</div>
          <div class="text-h6 text-weight-bold">{{ rows.length }}</div>
        </div>
      </div>
      <div class="col-auto">
        <div class="ops-card text-center" style="min-width:160px">
          <div class="text-caption text-grey-6">Total mensuel net</div>
          <div class="text-h6 text-weight-bold text-primary">{{ formatMoney(totalNet) }}</div>
        </div>
      </div>
      <div class="col-auto">
        <div class="ops-card text-center" style="min-width:140px">
          <div class="text-caption text-grey-6">Moyenne / adresse</div>
          <div class="text-h6 text-weight-bold">{{ formatMoney(avgNet) }}</div>
        </div>
      </div>
      <div class="col-auto">
        <div class="ops-card text-center" style="min-width:140px">
          <div class="text-caption text-grey-6">Rabais mensuels</div>
          <div class="text-h6 text-weight-bold text-positive">{{ formatMoney(totalDiscounts) }}</div>
        </div>
      </div>
      <div class="col-auto" v-if="svcProgress.total">
        <div class="ops-card text-center" style="min-width:180px">
          <div class="text-caption text-grey-6">Cogeco disponible</div>
          <div class="text-h6 text-weight-bold text-warning">{{ cogecoCount }}</div>
          <div class="text-caption text-grey-6">{{ svcBusy ? `vérifié ${svcProgress.done}/${svcProgress.total}` : 'risque de churn' }}</div>
        </div>
      </div>
    </div>

    <!-- Data table -->
    <DataTable
      v-if="loaded"
      :rows="rows"
      :columns="columns"
      row-key="delivery_id"
      flat bordered
      class="ops-table"
      :pagination="{ rowsPerPage: 50, sortBy: 'net_internet', descending: true }"
      dense
      :filter="search"
    >
      <template #top-right>
        <q-input v-model="search" dense outlined placeholder="Filtrer (nom, ville, courriel…)" clearable style="width:240px">
          <template #prepend><q-icon name="search" /></template>
        </q-input>
      </template>

      <template #body-cell-client="props">
        <q-td :props="props">
          <div class="text-weight-medium">{{ props.row.client_name || '(sans nom)' }}</div>
          <div v-if="props.row.company" class="text-caption text-grey-7">{{ props.row.company }}</div>
        </q-td>
      </template>

      <template #body-cell-address="props">
        <q-td :props="props">
          <div>{{ props.row.address1 || '—' }}</div>
          <div class="text-caption text-grey-7">{{ props.row.zip }}</div>
        </q-td>
      </template>

      <template #body-cell-net_internet="props">
        <q-td :props="props">
          <span class="text-weight-bold" :class="props.value >= 110 ? 'text-negative' : 'text-warning'">
            {{ formatMoney(props.value) }}
          </span>
        </q-td>
      </template>

      <template #body-cell-discounts="props">
        <q-td :props="props">
          <span v-if="props.value < 0" class="text-positive">{{ formatMoney(props.value) }}</span>
          <span v-else class="text-grey-5">—</span>
        </q-td>
      </template>

      <template #body-cell-recent_expired_discount="props">
        <q-td :props="props">
          <span v-if="props.value < 0" class="text-warning text-weight-medium">
            {{ formatMoney(props.value) }}
            <q-icon name="warning" size="14px" class="q-ml-xs" />
            <q-tooltip>Rabais expiré dans les 6 derniers mois — la facture vient d'augmenter d'autant. Candidat à la rétention.</q-tooltip>
          </span>
          <span v-else class="text-grey-5">—</span>
        </q-td>
      </template>

      <template #body-cell-detail="props">
        <q-td :props="props">
          <span class="text-caption" style="font-family:monospace">{{ shorten(props.value) }}</span>
          <q-tooltip v-if="props.value" max-width="420px" class="text-body2">{{ props.value }}</q-tooltip>
        </q-td>
      </template>

      <template #body-cell-contact="props">
        <q-td :props="props">
          <a v-if="props.row.email" :href="`mailto:${props.row.email}`" class="text-primary block">{{ props.row.email }}</a>
          <span v-if="props.row.cell || props.row.tel_home" class="text-caption text-grey-7">
            {{ props.row.cell || props.row.tel_home }}
          </span>
        </q-td>
      </template>

      <template #body-cell-concurrence="props">
        <q-td :props="props" style="min-width:210px">
          <div class="row items-center no-wrap">
            <div class="col">
              <div v-if="svcLoadingOf(props.row)" class="text-grey-5"><q-spinner size="14px" /></div>
              <template v-else-if="svcOf(props.row)">
                <div v-if="hasProviders(props.row)" class="q-gutter-xs">
                  <q-chip v-for="p in svcOf(props.row).providers" :key="p.nom" dense size="sm"
                    :color="isCogeco(p.nom) ? 'deep-orange-3' : 'blue-grey-2'"
                    :text-color="isCogeco(p.nom) ? 'deep-orange-10' : 'blue-grey-9'"
                    :icon="isCogeco(p.nom) ? 'priority_high' : undefined"
                    :label="p.nom">
                    <q-tooltip v-if="p.url">{{ p.url }}</q-tooltip>
                  </q-chip>
                </div>
                <span v-else class="text-grey-6 text-caption">{{ svcOf(props.row).etat_label }}</span>
              </template>
              <span v-else class="text-grey-5">—</span>
            </div>
            <q-btn dense flat round size="xs" icon="open_in_new" color="grey-5" @click="checkCogeco(props.row)">
              <q-tooltip>Ouvrir Cogeco pour valider manuellement</q-tooltip>
            </q-btn>
          </div>
        </q-td>
      </template>
    </DataTable>

    <div v-if="loaded && !rows.length" class="text-center q-pa-xl text-grey-7">
      <q-icon name="search_off" size="42px" />
      <div class="q-mt-sm">Aucune adresse au-dessus de {{ formatMoney(threshold) }}/mois pour ce segment.</div>
    </div>
  </q-page>
</template>

<script setup>
import { ref, computed } from 'vue'
import { useQuasar, copyToClipboard } from 'quasar'
import { fetchOverpricedInternet, overpricedInternetCsvUrl, lookupServiceabilityBatch } from 'src/api/reports'
import DataTable from 'src/components/shared/DataTable.vue'
import { formatMoney } from 'src/composables/useFormatters'

const $q = useQuasar()
const threshold = ref(90)
const segment = ref('residential')
const addons = ref(true)
const loading = ref(false)
const loaded = ref(false)
const rows = ref([])
const search = ref('')
const dataAsOf = ref(null)

// Serviceability (Québec IHV) state — keyed by delivery_id
const svc = ref({})              // delivery_id -> { matched, etat_label, providers, cogeco }
const svcLoading = ref({})       // delivery_id -> bool
const svcBusy = ref(false)
const svcProgress = ref({ done: 0, total: 0 })

const segmentOptions = [
  { label: 'Résidentiel', value: 'residential' },
  { label: 'Commercial', value: 'commercial' },
  { label: 'Tous', value: 'all' },
]

const columns = [
  { name: 'client', label: 'Client', field: 'client_name', align: 'left', sortable: true },
  { name: 'address', label: 'Adresse de service', field: 'address1', align: 'left', sortable: true },
  { name: 'city', label: 'Ville', field: 'city', align: 'left', sortable: true },
  { name: 'net_internet', label: 'Net Internet /mois', field: 'net_internet', align: 'right', sortable: true },
  { name: 'gross', label: 'Brut', field: 'gross', align: 'right', sortable: true, format: v => formatMoney(v) },
  { name: 'discounts', label: 'Rabais actifs', field: 'discounts', align: 'right', sortable: true },
  { name: 'recent_expired_discount', label: 'Rabais expirés (6 mois)', field: 'recent_expired_discount', align: 'right', sortable: true },
  { name: 'n_lines', label: 'Lignes', field: 'n_lines', align: 'center', sortable: true },
  { name: 'detail', label: 'Détail forfait', field: 'detail', align: 'left' },
  { name: 'contact', label: 'Contact', field: 'email', align: 'left' },
  { name: 'concurrence', label: 'Concurrence (FSI)', field: 'delivery_id', align: 'left' },
]

const totalNet = computed(() => rows.value.reduce((s, r) => s + Number(r.net_internet || 0), 0))
const avgNet = computed(() => rows.value.length ? totalNet.value / rows.value.length : 0)
const totalDiscounts = computed(() => rows.value.reduce((s, r) => s + Number(r.discounts || 0), 0))
const cogecoCount = computed(() => Object.values(svc.value).filter(v => v && v.cogeco).length)

function isCogeco (nom) { return /cogeco/i.test(nom || '') }
function svcOf (row) { return svc.value[row.delivery_id] }
function svcLoadingOf (row) { return !!svcLoading.value[row.delivery_id] }
function hasProviders (row) { const v = svc.value[row.delivery_id]; return !!(v && v.providers && v.providers.length) }

const csvUrl = computed(() => overpricedInternetCsvUrl({
  threshold: threshold.value, segment: segment.value, addons: addons.value,
}))

const daysOld = computed(() => {
  if (!dataAsOf.value) return 0
  return Math.floor((Date.now() - new Date(dataAsOf.value)) / 86400000)
})
const isStale = computed(() => daysOld.value > 7)
const staleClass = computed(() => isStale.value ? 'bg-orange-2 text-warning' : 'bg-blue-1 text-info')

// formatMoney unifié via useFormatters (import ci-dessus) — même format fr-CA
function formatDate (iso) {
  return iso ? new Date(iso).toLocaleDateString('fr-CA', { day: 'numeric', month: 'long', year: 'numeric' }) : ''
}
function shorten (s) {
  if (!s) return ''
  return s.length > 48 ? s.slice(0, 48) + '…' : s
}

// Build a clean single-line address for the competitor's address checker.
// e.g. "147 Montée Richard, Saint-Bernard-de-Lacolle, QC J0J 1V0"
function fullAddress (row) {
  const prov = 'QC' + (row.zip ? ' ' + String(row.zip).toUpperCase() : '')
  return [row.address1, row.city, prov].filter(Boolean).join(', ')
}

// Assisted spot-check: Cogeco's checker is gated by reCAPTCHA Enterprise so we
// can't qualify addresses automatically at volume. Instead, one click copies
// the address and opens Cogeco's availability page in a new tab — a human
// pastes + reads the verdict in ~10s, only for the leads that matter.
const COGECO_URL = 'https://www.cogeco.ca/en/internet/packages'
async function checkCogeco (row) {
  const addr = fullAddress(row)
  let copied = true
  try { await copyToClipboard(addr) } catch { copied = false }
  window.open(COGECO_URL, '_blank', 'noopener')
  $q.notify({
    color: 'primary',
    icon: 'travel_explore',
    message: copied ? 'Adresse copiée : ' + addr : addr,
    caption: copied
      ? 'Dans l’onglet Cogeco : clique « Check Availability », colle (⌘V / Ctrl+V) puis choisis la suggestion.'
      : 'Copie l’adresse ci-dessus, puis dans Cogeco clique « Check Availability » et colle-la.',
    timeout: 7000,
    multiLine: true,
    actions: [{ label: 'OK', color: 'white', round: true }],
  })
}

// Batch-fetch provider availability for the given rows via the hub
// (Québec IHV open data). Chunked + progressive so the column fills as it goes.
async function fetchServiceability (rowsList) {
  const items = (rowsList || []).filter(r => r.address1).map(r => ({
    key: String(r.delivery_id), address1: r.address1, city: r.city, zip: r.zip,
  }))
  if (!items.length) return
  svcBusy.value = true
  svc.value = {}
  const ld = {}; items.forEach(it => { ld[it.key] = true }); svcLoading.value = ld
  svcProgress.value = { done: 0, total: items.length }
  const CHUNK = 40
  try {
    for (let i = 0; i < items.length; i += CHUNK) {
      const chunk = items.slice(i, i + CHUNK)
      try {
        const { results } = await lookupServiceabilityBatch(chunk)
        const sv = { ...svc.value }; const ldd = { ...svcLoading.value }
        for (const [k, v] of Object.entries(results)) { sv[k] = v; ldd[k] = false }
        svc.value = sv; svcLoading.value = ldd
      } catch (e) {
        const ldd = { ...svcLoading.value }; chunk.forEach(c => { ldd[c.key] = false }); svcLoading.value = ldd
        $q.notify({ type: 'warning', message: 'Concurrence : lot ignoré (' + e.message + ')', timeout: 3000 })
      }
      svcProgress.value = { done: Math.min(i + CHUNK, items.length), total: items.length }
    }
  } finally {
    svcBusy.value = false
  }
}

async function loadReport () {
  loading.value = true
  svc.value = {}; svcLoading.value = {}; svcProgress.value = { done: 0, total: 0 }
  try {
    const data = await fetchOverpricedInternet({
      threshold: threshold.value, segment: segment.value, addons: addons.value, limit: 5000,
    })
    rows.value = data.rows || []
    dataAsOf.value = data.data_as_of || null
    loaded.value = true
  } catch (e) {
    $q.notify({ type: 'negative', message: 'Erreur de chargement : ' + e.message })
  } finally {
    loading.value = false
  }
}
</script>
