<template>
  <q-page padding>
    <div class="row items-center q-mb-sm">
      <q-btn flat dense icon="arrow_back" to="/rapports" class="q-mr-sm" />
      <div class="text-h6 text-weight-bold">Explorateur de revenus</div>
      <q-space />
      <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">
      Revenu récurrent mensuel (MRR) net — forfaits + rabais récurrents, forfaits annuels ramenés au mois — depuis
      la base legacy. <strong>Comptes clients actifs uniquement</strong> (exclut résiliés, prospects, relais/infra,
      propriétaires-hébergeurs) ; exclut les frais ponctuels et rabais promo expirés. Choisis un regroupement et des
      critères pour explorer d'un seul rapport ce qui exigeait auparavant plusieurs rapports séparés.
    </div>

    <!-- Critères en chips -->
    <div class="ops-card q-pa-sm q-mb-md">
      <div class="row items-center q-gutter-xs q-mb-sm">
        <q-icon name="pivot_table_chart" size="18px" class="text-grey-6" />
        <span class="text-caption text-weight-medium text-grey-7 q-mr-sm">Regrouper par</span>
        <q-chip v-for="d in dimensionOptions" :key="d.value" clickable dense :icon="d.icon"
                :color="dimension === d.value ? 'primary' : 'grey-3'"
                :text-color="dimension === d.value ? 'white' : 'grey-8'"
                @click="dimension = d.value">{{ d.label }}</q-chip>
      </div>
      <div class="row items-center q-gutter-x-md q-gutter-y-xs">
        <div class="row items-center q-gutter-xs">
          <span class="text-caption text-grey-6 q-mr-xs">Service</span>
          <q-chip v-for="t in typeOptions" :key="t.value" clickable dense size="sm"
                  :color="type === t.value ? 'teal-6' : 'grey-3'"
                  :text-color="type === t.value ? 'white' : 'grey-8'"
                  @click="type = t.value">{{ t.label }}</q-chip>
        </div>
        <div class="row items-center q-gutter-xs">
          <span class="text-caption text-grey-6 q-mr-xs">Segment</span>
          <q-chip v-for="s in segmentOptions" :key="s.value" clickable dense size="sm"
                  :color="segment === s.value ? 'indigo-5' : 'grey-3'"
                  :text-color="segment === s.value ? 'white' : 'grey-8'"
                  @click="segment = s.value">{{ s.label }}</q-chip>
        </div>
        <q-toggle v-model="active" dense size="sm" label="Actifs seulement" />
        <q-input v-model.number="threshold" type="number" min="0" step="10" dense outlined
                 label="Seuil $/mois" style="width:130px" class="no-spin" />
        <q-space />
        <q-btn flat dense size="sm" icon="refresh" :loading="loading" @click="loadReport" />
      </div>
    </div>

    <!-- Fraîcheur des données legacy (copie figée) -->
    <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) ; renégociations et résiliations récentes non reflétées.</span>
    </q-banner>

    <!-- Sommaire -->
    <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:170px">
          <div class="text-caption text-grey-6">Total MRR net</div>
          <div class="text-h6 text-weight-bold text-primary">{{ formatMoney(totalNet) }}</div>
          <div class="text-caption text-grey-6">/ mois</div>
        </div>
      </div>
      <div class="col-auto">
        <div class="ops-card text-center" style="min-width:150px">
          <div class="text-caption text-grey-6">{{ dimLabel }}s</div>
          <div class="text-h6 text-weight-bold">{{ count }}</div>
        </div>
      </div>
      <div class="col-auto">
        <div class="ops-card text-center" style="min-width:150px">
          <div class="text-caption text-grey-6">Adresses</div>
          <div class="text-h6 text-weight-bold">{{ totalAddresses }}</div>
        </div>
      </div>
      <div class="col-auto" v-if="totalDiscounts < 0">
        <div class="ops-card text-center" style="min-width:150px">
          <div class="text-caption text-grey-6">Rabais / mois</div>
          <div class="text-h6 text-weight-bold text-positive">{{ formatMoney(totalDiscounts) }}</div>
        </div>
      </div>
    </div>

    <DataTable
      v-if="loaded"
      :rows="rows"
      :columns="columns"
      row-key="dim_key"
      flat bordered dense
      class="ops-table"
      :pagination="{ rowsPerPage: 50, sortBy: 'net', descending: true }"
      :filter="search">
      <template #top-right>
        <q-input v-model="search" dense outlined :placeholder="`Filtrer ${dimLabel.toLowerCase()}…`" clearable style="width:240px">
          <template #prepend><q-icon name="search" /></template>
        </q-input>
      </template>

      <template #body-cell-dim_label="props">
        <q-td :props="props" class="text-weight-medium">{{ props.value || '—' }}</q-td>
      </template>

      <template #body-cell-net="props">
        <q-td :props="props" style="min-width:220px">
          <div class="row items-center no-wrap">
            <div class="net-bar-track">
              <div class="net-bar-fill" :style="{ width: barWidth(props.row.net) }"></div>
            </div>
            <span class="text-weight-bold text-primary q-ml-sm" style="min-width:78px;text-align:right">{{ formatMoney(props.row.net) }}</span>
          </div>
        </q-td>
      </template>

      <template #body-cell-share="props">
        <q-td :props="props" class="text-right text-grey-7">{{ sharePct(props.row.net) }}</q-td>
      </template>

      <template #body-cell-discounts="props">
        <q-td :props="props" class="text-right">
          <span v-if="props.value < 0" class="text-positive">{{ formatMoney(props.value) }}</span>
          <span v-else class="text-grey-5">—</span>
        </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">Aucun résultat pour ces critères.</div>
    </div>
  </q-page>
</template>

<script setup>
import { ref, computed, watch, onMounted } from 'vue'
import { useQuasar } from 'quasar'
import { fetchRevenueExplorer, revenueExplorerCsvUrl } from 'src/api/reports'
import DataTable from 'src/components/shared/DataTable.vue'
import { formatMoney, formatDateLong as formatDate } from 'src/composables/useFormatters'

const $q = useQuasar()

const dimensionOptions = [
  { value: 'category', label: 'Catégorie', icon: 'category' },
  { value: 'zip', label: 'Code postal', icon: 'markunread_mailbox' },
  { value: 'city', label: 'Ville', icon: 'location_city' },
  { value: 'mrc', label: 'MRC', icon: 'map' },
  { value: 'segment', label: 'Segment', icon: 'groups' },
  { value: 'plan', label: 'Plan', icon: 'inventory_2' },
]
const typeOptions = [
  { value: 'all', label: 'Tous' }, { value: 'internet', label: 'Internet' },
  { value: 'tv', label: 'TV' }, { value: 'phone', label: 'Téléphonie' },
]
const segmentOptions = [
  { value: 'all', label: 'Tous' }, { value: 'residential', label: 'Résidentiel' },
  { value: 'commercial', label: 'Commercial' },
]

const dimension = ref('category')
const segment = ref('all')
const type = ref('all')
const active = ref(true)
const threshold = ref(0)

const loading = ref(false)
const loaded = ref(false)
const rows = ref([])
const total = ref(null)
const dataAsOf = ref(null)
const dimLabel = ref('Catégorie')
const search = ref('')

const params = computed(() => ({
  dimension: dimension.value, segment: segment.value, type: type.value,
  active: active.value, threshold: threshold.value || 0,
}))
const csvUrl = computed(() => revenueExplorerCsvUrl(params.value))

const columns = computed(() => [
  { name: 'dim_label', label: dimLabel.value, field: 'dim_label', align: 'left', sortable: true },
  { name: 'n_addresses', label: 'Adresses', field: 'n_addresses', align: 'center', sortable: true },
  { name: 'n_lines', label: 'Lignes', field: 'n_lines', align: 'center', sortable: true },
  { name: 'gross', label: 'Brut', field: 'gross', align: 'right', sortable: true, format: v => formatMoney(v) },
  { name: 'discounts', label: 'Rabais', field: 'discounts', align: 'right', sortable: true },
  { name: 'net', label: 'MRR net / mois', field: 'net', align: 'right', sortable: true },
  { name: 'share', label: 'Part', field: 'net', align: 'right', sortable: true },
])

const totalNet = computed(() => total.value ? Number(total.value.net || 0) : 0)
const totalDiscounts = computed(() => total.value ? Number(total.value.discounts || 0) : 0)
const totalAddresses = computed(() => total.value ? Number(total.value.n_addresses || 0) : 0)
const count = computed(() => rows.value.length)
const maxNet = computed(() => rows.value.reduce((m, r) => Math.max(m, Number(r.net || 0)), 0))

function barWidth (net) {
  const n = Number(net || 0)
  if (maxNet.value <= 0 || n <= 0) return '0%'
  return Math.round((n / maxNet.value) * 100) + '%'
}
function sharePct (net) {
  if (totalNet.value <= 0) return '—'
  return (Number(net || 0) / totalNet.value * 100).toFixed(1) + ' %'
}

const daysOld = computed(() => dataAsOf.value ? Math.floor((Date.now() - new Date(dataAsOf.value)) / 86400000) : 0)
const isStale = computed(() => daysOld.value > 7)
const staleClass = computed(() => isStale.value ? 'bg-orange-2 text-warning' : 'bg-blue-1 text-info')
// formatDate → composables/useFormatters (formatDateLong, source unique)

async function loadReport () {
  loading.value = true
  try {
    const data = await fetchRevenueExplorer(params.value)
    rows.value = data.rows || []
    total.value = data.total || null
    dataAsOf.value = data.data_as_of || null
    dimLabel.value = data.dimension_label || 'Groupe'
    loaded.value = true
  } catch (e) {
    $q.notify({ type: 'negative', message: 'Erreur de chargement : ' + e.message })
  } finally {
    loading.value = false
  }
}

// Explorer fluide : recharge (débounce) dès qu'un critère change.
let t = null
watch(params, () => { clearTimeout(t); t = setTimeout(loadReport, 300) })
onMounted(loadReport)
</script>

<style scoped>
.net-bar-track { flex: 1; height: 8px; background: var(--ops-bg, #f1f5f9); border-radius: 4px; overflow: hidden; min-width: 60px; }
.net-bar-fill { height: 100%; background: var(--ops-accent, #16a34a); border-radius: 4px; }
.no-spin :deep(input[type=number])::-webkit-outer-spin-button,
.no-spin :deep(input[type=number])::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.no-spin :deep(input[type=number]) { -moz-appearance: textfield; }
</style>
