<template>
  <q-page padding>
    <div class="row items-center q-mb-md">
      <q-btn flat dense round icon="arrow_back" :to="'/campaigns'" class="q-mr-sm">
        <q-tooltip>Retour aux campagnes</q-tooltip>
      </q-btn>
      <div class="text-h5">Inventaire des liens cadeaux</div>
      <q-space />
      <q-btn flat dense icon="refresh" label="Rafraîchir" @click="load" :loading="loading" />
    </div>

    <!-- Status counters strip — a glance at the inventory health -->
    <div class="row q-col-gutter-sm q-mb-md">
      <q-card flat bordered class="col-6 col-md-2" @click="filterStatus = null" style="cursor:pointer">
        <q-card-section class="text-center q-pa-sm">
          <div class="text-h5">{{ gifts.length }}</div>
          <div class="text-caption text-grey-7">Total</div>
        </q-card-section>
      </q-card>
      <q-card flat bordered class="col-6 col-md-2" @click="filterStatus = 'active'" style="cursor:pointer">
        <q-card-section class="text-center q-pa-sm">
          <div class="text-h5 text-positive">{{ counts.active }}</div>
          <div class="text-caption text-grey-7">Actifs</div>
        </q-card-section>
      </q-card>
      <q-card flat bordered class="col-6 col-md-2" @click="filterStatus = 'redeemed'" style="cursor:pointer">
        <q-card-section class="text-center q-pa-sm">
          <div class="text-h5 text-deep-purple-7">{{ counts.redeemed }}</div>
          <div class="text-caption text-grey-7">Cliqués</div>
        </q-card-section>
      </q-card>
      <q-card flat bordered class="col-6 col-md-2" @click="filterStatus = 'expired'" style="cursor:pointer">
        <q-card-section class="text-center q-pa-sm">
          <div class="text-h5 text-warning">{{ counts.expired }}</div>
          <div class="text-caption text-grey-7">Expirés</div>
        </q-card-section>
      </q-card>
      <q-card flat bordered class="col-6 col-md-2" @click="filterStatus = 'revoked'" style="cursor:pointer">
        <q-card-section class="text-center q-pa-sm">
          <div class="text-h5 text-grey-7">{{ counts.revoked }}</div>
          <div class="text-caption text-grey-7">Révoqués</div>
        </q-card-section>
      </q-card>
      <q-card flat bordered class="col-6 col-md-2" @click="filterStatus = 'reassignable'" style="cursor:pointer"
              :class="{ 'bg-amber-1': counts.reassignable > 0 }">
        <q-card-section class="text-center q-pa-sm">
          <div class="text-h5 text-warning">{{ counts.reassignable }}</div>
          <div class="text-caption text-grey-7">Réassignables</div>
        </q-card-section>
      </q-card>
    </div>

    <!-- Filter bar -->
    <q-card flat bordered class="q-mb-md">
      <q-card-section class="q-py-sm">
        <div class="row items-center q-col-gutter-sm">
          <q-input v-model="search" placeholder="Rechercher (nom, courriel, lien…)" outlined dense
                   class="col-12 col-md-4" clearable>
            <template v-slot:prepend><q-icon name="search" /></template>
          </q-input>
          <q-select v-model="filterStatus" :options="statusOptions" emit-value map-options
                    label="Statut" outlined dense clearable class="col-6 col-md-3" />
          <q-select v-model="filterCampaign" :options="campaignOptions" emit-value map-options
                    label="Campagne" outlined dense clearable class="col-6 col-md-3" />
          <q-space />
          <div class="text-caption text-grey-7 q-mr-sm">{{ filtered.length }} résultat(s)</div>
        </div>
      </q-card-section>
    </q-card>

    <DataTable
      :rows="filtered" :columns="columns" row-key="gift_token"
      flat bordered dense :pagination="{ rowsPerPage: 50, sortBy: 'expires', descending: false }"
      :rows-per-page-options="[25, 50, 100, 0]"
      :loading="loading"
    >
      <template v-slot:body-cell-status="props">
        <q-td :props="props">
          <q-chip dense size="sm" :color="statusColor(props.row.status)" text-color="white"
                  :icon="statusIcon(props.row.status)" :label="statusLabel(props.row.status)" />
        </q-td>
      </template>
      <template v-slot:body-cell-recipient="props">
        <q-td :props="props">
          <div>{{ props.row.firstname }} {{ props.row.lastname }}</div>
          <div class="text-caption text-grey-6">{{ props.row.email }}</div>
        </q-td>
      </template>
      <template v-slot:body-cell-campaign="props">
        <q-td :props="props">
          <a :href="`/ops/#/campaigns/${props.row.campaign_id}`" class="text-primary" style="text-decoration:none">
            {{ props.row.campaign_name || props.row.campaign_id }}
            <q-icon name="open_in_new" size="14px" />
          </a>
        </q-td>
      </template>
      <template v-slot:body-cell-gift_url="props">
        <q-td :props="props">
          <span style="font-family:monospace; font-size:0.78rem">{{ shorten(props.row.gift_url) }}</span>
          <q-btn flat dense round size="xs" icon="content_copy" @click="copy(props.row.gift_url)" class="q-ml-xs">
            <q-tooltip>Copier l'URL Giftbit (à coller dans une nouvelle campagne pour réassigner)</q-tooltip>
          </q-btn>
          <q-btn v-if="giftbitAdminUrl(props.row.gift_url)"
                 flat dense round size="xs" icon="open_in_new" color="primary"
                 :href="giftbitAdminUrl(props.row.gift_url)" target="_blank" class="q-ml-xs">
            <q-tooltip>Voir l'historique sur Giftbit (statut de redemption)</q-tooltip>
          </q-btn>
        </q-td>
      </template>
      <template v-slot:body-cell-expires="props">
        <q-td :props="props">
          <span v-if="props.row.gift_expires_at" :class="{ 'text-warning': props.row.status === 'expired' }">
            {{ formatDate(props.row.gift_expires_at) }}
          </span>
          <span v-else class="text-grey-5">—</span>
        </q-td>
      </template>
      <template v-slot:body-cell-clicks="props">
        <q-td :props="props" class="text-center">
          <span v-if="props.row.gift_redirected_count">
            {{ props.row.gift_redirected_count }}
            <q-tooltip v-if="props.row.gift_first_redirected_at">
              1er clic: {{ formatDate(props.row.gift_first_redirected_at) }}
            </q-tooltip>
          </span>
          <span v-else class="text-grey-5">0</span>
        </q-td>
      </template>
      <template v-slot:body-cell-actions="props">
        <q-td :props="props" class="text-right">
          <q-btn v-if="props.row.status === 'active'" flat dense color="negative" icon="block" size="sm"
                 @click="confirmRevoke(props.row)">
            <q-tooltip>Révoquer ce lien (libère le cadeau Giftbit pour réassignation)</q-tooltip>
          </q-btn>
          <q-btn v-if="props.row.status === 'expired' || props.row.status === 'revoked'"
                 flat dense color="warning" icon="autorenew" size="sm"
                 @click="copyForReassign(props.row.gift_url)">
            <q-tooltip>Copier l'URL pour réassigner à un autre destinataire</q-tooltip>
          </q-btn>
        </q-td>
      </template>
    </DataTable>
  </q-page>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import DataTable from 'src/components/shared/DataTable.vue'
import { useQuasar } from 'quasar'
import { listGifts, revokeGift } from 'src/api/campaigns'

const $q = useQuasar()
const gifts = ref([])
const loading = ref(true)
const search = ref('')
const filterStatus = ref(null)
const filterCampaign = ref(null)

const columns = [
  { name: 'status', label: 'Statut', field: 'status', align: 'left', sortable: true },
  { name: 'recipient', label: 'Destinataire', field: r => `${r.firstname} ${r.lastname}`.trim(), align: 'left', sortable: true },
  { name: 'campaign', label: 'Campagne', field: 'campaign_name', align: 'left', sortable: true },
  { name: 'gift_url', label: 'Lien Giftbit', field: 'gift_url', align: 'left' },
  { name: 'expires', label: 'Expire le', field: 'gift_expires_at', align: 'left', sortable: true },
  { name: 'clicks', label: 'Clics', field: 'gift_redirected_count', align: 'center', sortable: true },
  { name: 'actions', label: '', field: '', align: 'right' },
]

const statusOptions = [
  { label: '🟢 Actif', value: 'active' },
  { label: '🟣 Cliqué', value: 'redeemed' },
  { label: '🟠 Expiré', value: 'expired' },
  { label: '⚫ Révoqué', value: 'revoked' },
  { label: '🟡 Réassignable (expiré + révoqué)', value: 'reassignable' },
  { label: '⏳ Non envoyé', value: 'pending' },
]

const campaignOptions = computed(() => {
  const seen = new Map()
  for (const g of gifts.value) {
    if (!seen.has(g.campaign_id)) seen.set(g.campaign_id, g.campaign_name || g.campaign_id)
  }
  return [...seen.entries()].map(([value, label]) => ({ value, label }))
})

const counts = computed(() => {
  const c = { active: 0, redeemed: 0, expired: 0, revoked: 0, pending: 0, reassignable: 0 }
  for (const g of gifts.value) {
    c[g.status] = (c[g.status] || 0) + 1
    // Reassignable = expired or revoked AND not yet redeemed (i.e. the
    // underlying Giftbit gift is presumably still unredeemed).
    if ((g.status === 'expired' || g.status === 'revoked') && !g.gift_link_clicked) c.reassignable++
  }
  return c
})

const filtered = computed(() => {
  let rows = gifts.value
  if (filterStatus.value === 'reassignable') {
    rows = rows.filter(g => (g.status === 'expired' || g.status === 'revoked') && !g.gift_link_clicked)
  } else if (filterStatus.value) {
    rows = rows.filter(g => g.status === filterStatus.value)
  }
  if (filterCampaign.value) rows = rows.filter(g => g.campaign_id === filterCampaign.value)
  if (search.value) {
    const q = search.value.toLowerCase()
    rows = rows.filter(g =>
      (g.firstname || '').toLowerCase().includes(q) ||
      (g.lastname || '').toLowerCase().includes(q) ||
      (g.email || '').toLowerCase().includes(q) ||
      (g.gift_url || '').toLowerCase().includes(q) ||
      (g.gift_token || '').toLowerCase().includes(q),
    )
  }
  return rows
})

function statusColor (s) {
  return {
    active:   'positive',
    redeemed: 'deep-purple-7',
    expired:  'orange-9',
    revoked:  'grey-7',
    pending:  'grey-5',
  }[s] || 'grey-5'
}
function statusIcon (s) {
  return {
    active:   'check_circle',
    redeemed: 'redeem',
    expired:  'schedule',
    revoked:  'block',
    pending:  'hourglass_empty',
  }[s] || ''
}
function statusLabel (s) {
  return {
    active:   'Actif',
    redeemed: 'Cliqué',
    expired:  'Expiré',
    revoked:  'Révoqué',
    pending:  'En attente',
  }[s] || s
}

function shorten (u) {
  if (!u) return ''
  return u.replace(/^https?:\/\//, '').slice(0, 36) + (u.length > 40 ? '…' : '')
}

// Build a deep link into Giftbit's admin panel for a given shortlink so
// operators can confirm redemption status manually until task #25 wires
// the /gifts/{uuid} API polling. The trailing path segment of the
// shortlink URL is what Giftbit's reward search uses as the lookup key.
//   "http://gft.link/4kpZMApLK4B"
//     → "https://app.giftbit.com/app/rewards?search=4kpZMApLK4B"
function giftbitAdminUrl (giftUrl) {
  if (!giftUrl) return null
  // Last non-empty path segment (strip trailing slashes if any)
  const segments = giftUrl.replace(/\/+$/, '').split('/')
  const code = segments[segments.length - 1]
  if (!code || code.length < 4) return null
  return `https://app.giftbit.com/app/rewards?search=${encodeURIComponent(code)}`
}
function formatDate (iso) {
  if (!iso) return ''
  return new Date(iso).toLocaleString('fr-CA', { dateStyle: 'medium', timeStyle: 'short' })
}

async function copy (text, customMsg) {
  try {
    await navigator.clipboard.writeText(text)
    $q.notify({ type: 'positive', message: customMsg || 'Copié dans le presse-papier', timeout: 2500 })
  } catch {
    $q.notify({ type: 'negative', message: 'Copie impossible — sélectionne et copie manuellement' })
  }
}
function copyForReassign (url) {
  // Separate helper so the toast message can live in JS where quote-escaping
  // is trivial (the Vue attribute parser doesn't accept embedded quotes).
  copy(url, `Lien Giftbit copié — colle-le dans "Ajouter manuellement" d'une nouvelle campagne pour réassigner ce cadeau`)
}

function confirmRevoke (row) {
  $q.dialog({
    title: 'Révoquer ce lien ?',
    message: `Le destinataire <strong>${row.firstname} ${row.lastname}</strong> ne pourra plus utiliser son lien après cette action. L'URL Giftbit (<code>${shorten(row.gift_url)}</code>) restera valide chez Giftbit et pourra être réassignée à un autre destinataire via une nouvelle campagne.`,
    html: true,
    cancel: { label: 'Annuler', flat: true },
    ok: { label: 'Révoquer', color: 'negative', unelevated: true },
    persistent: true,
  }).onOk(async () => {
    try {
      await revokeGift(row.campaign_id, row.row_index)
      row.status = 'revoked'
      row.gift_revoked = true
      $q.notify({ type: 'positive', message: 'Lien révoqué' })
    } catch (e) {
      $q.notify({ type: 'negative', message: 'Erreur: ' + e.message })
    }
  })
}

async function load () {
  loading.value = true
  try {
    gifts.value = await listGifts()
  } catch (e) {
    $q.notify({ type: 'negative', message: 'Chargement échoué: ' + e.message })
  } finally {
    loading.value = false
  }
}
// Ancrage profond depuis la fiche client : ?q=<gift_token|courriel> pré-filtre le tableau sur la bonne récompense.
const route = useRoute()
onMounted(() => {
  if (route.query.q) search.value = String(route.query.q)
  if (route.query.status) filterStatus.value = String(route.query.status)
  load()
})
</script>
