<template>
  <section class="grid gap-6">
    <!-- Header -->
    <div class="card">
      <div class="card-header">
        <h1 class="card-title">Administration des réservations</h1>
        <p class="text-sm text-slate-500">Validez, refusez, modifiez les réservations et visualisez les plannings par cargobike.</p>
      </div>
      <div class="card-content">
        <div class="flex flex-wrap items-center gap-3">
          <button class="btn h-9 px-3" @click="refresh" :disabled="loading">{{ loading ? 'Rafraîchissement…' : 'Rafraîchir' }}</button>
          <span class="text-xs text-slate-500" v-if="lastLoaded">Dernier chargement: {{ formatDateTime(lastLoaded) }}</span>
          <span class="text-xs text-red-600" v-if="error">{{ error }}</span>
        </div>
      </div>
    </div>

    <!-- List of bookings -->
    <div class="card">
      <div class="card-header">
        <div class="flex items-center justify-between gap-4">
          <h2 class="card-title">Réservations</h2>
          <div class="flex items-center gap-2">
            <label class="text-xs text-slate-500">Filtrer</label>
            <select v-model="filter" class="input h-9 w-[160px]">
              <option value="all">Toutes</option>
              <option value="pending">En attente</option>
              <option value="accepted">Acceptées</option>
              <option value="ongoing">En cours</option>
              <option value="archived">Archivées</option>
              <option value="refused">Refusées</option>
            </select>
          </div>
        </div>
      </div>
      <div class="card-content">
        <div v-if="bookings.length === 0" class="text-sm text-slate-500">Aucune réservation pour le moment.</div>

        <div v-else class="grid gap-3">
          <div v-for="b in filtered" :key="b.id" class="rounded-lg border border-slate-200 p-3 grid gap-2">
            <div class="flex items-start justify-between gap-3">
              <div class="grid gap-1">
                <div class="flex items-center gap-2">
                  <span class="font-medium">#{{ b.id }}</span>
                  <StatusBadge :booking="b" :now="now" />
                </div>
                <div class="text-sm">
                  <span class="font-medium">Association:</span>
                  <span class="ml-1">{{ b.name }}</span>
                </div>
                <div class="text-xs text-slate-500">Email(s): {{ b.email }}</div>
                <div class="text-xs text-slate-600">
                  <span class="font-medium">Période:</span>
                  <span class="ml-1">{{ formatRange(b) }}</span>
                </div>
                <div class="text-xs text-slate-600">
                  <span class="font-medium">Cargobike(s):</span>
                  <span class="ml-1">{{ formatBikes(b) }}</span>
                </div>
              </div>

              <div class="grid gap-2 justify-items-end min-w-[220px]">
                <div class="flex flex-wrap gap-2 justify-end">
                  <button class="btn btn-secondary h-8 px-3" @click="startEdit(b)">Modifier</button>
                  <button class="btn btn-outline h-8 px-3" :disabled="b.status==='accepted'" @click="accept(b)" v-if="b.status!=='accepted'">Accepter</button>
                  <button class="btn btn-outline h-8 px-3" :disabled="b.status==='accepted'" @click="refuse(b)" v-if="b.status!=='accepted'">Refuser</button>
                  <button class="btn btn-outline h-8 px-3" v-if="b.status==='refused'" @click="restore(b)">Restaurer</button>
                  <button class="btn btn-outline h-8 px-3" @click="remove(b)">Supprimer</button>
                </div>
                <div class="text-xs text-slate-500">Créée le {{ formatDateTime(new Date(b.created_at)) }}</div>
              </div>
            </div>

            <!-- Inline edit row -->
            <div v-if="editingId === b.id" class="rounded-md bg-slate-50 p-3 border border-slate-200">
              <div class="grid sm:grid-cols-[1fr_auto] gap-3 items-end">
                <div class="grid gap-2">
                  <label class="label">Attribuer un cargobike</label>
                  <select v-model="editForm.bike_type" class="input h-9">
                    <option :value="null">— Non défini —</option>
                    <option v-for="t in bikes" :key="t" :value="t">{{ t }}</option>
                  </select>
                  <p class="helper text-xs text-slate-500">Astuce: pour un choix multiple, utilisez la page de réservation; ici on affecte un seul vélo.</p>
                </div>
                <div class="flex gap-2">
                  <button class="btn h-9 px-3" @click="saveEdit(b)">Enregistrer</button>
                  <button class="btn btn-secondary h-9 px-3" @click="cancelEdit">Annuler</button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- Calendar per cargobike -->
    <div class="card">
      <div class="card-header">
        <div class="flex flex-wrap items-center gap-3 justify-between">
          <h2 class="card-title">Calendrier par cargobike</h2>
          <div class="flex flex-wrap items-center gap-2">
            <label class="text-xs text-slate-500">Cargobike</label>
            <select v-model="selectedBike" class="input h-9 w-[160px]">
              <option value="all">Tous</option>
              <option v-for="t in bikes" :key="t" :value="t">{{ t }}</option>
            </select>
          </div>
        </div>
      </div>
      <div class="card-content grid gap-3">
        <div class="flex flex-wrap items-center gap-2">
          <button class="btn btn-outline h-8 px-3" @click="prevWeek">Semaine -</button>
          <button class="btn btn-outline h-8 px-3" @click="nextWeek">Semaine +</button>
          <button class="btn btn-secondary h-8 px-3" @click="goToday">Aujourd’hui</button>
          <div class="text-sm text-slate-600 ml-2">Semaine du {{ formatDate(weekStart) }} au {{ formatDate(weekEnd) }}</div>
        </div>

        <!-- Week grid -->
        <div class="overflow-auto border border-slate-200 rounded-md">
          <div class="min-w-[900px]">
            <!-- Header row: days -->
            <div class="grid" :style="gridTemplateDays">
              <div class="sticky left-0 bg-white z-10 border-b border-slate-200 p-2 text-xs text-slate-500">Heure</div>
              <div v-for="(d, idx) in weekDays" :key="idx" class="border-b border-l border-slate-200 p-2 text-xs font-medium text-slate-700">
                {{ weekdayShort(d) }} {{ d.getDate() }}/{{ (d.getMonth()+1).toString().padStart(2,'0') }}
              </div>
            </div>

            <!-- Body: hours + day columns -->
            <div class="grid" :style="gridTemplateDays">
              <!-- Hours rail -->
              <div class="sticky left-0 bg-white z-10 border-r border-slate-200">
                <div v-for="h in hours" :key="h" class="h-12 border-b border-slate-100 px-2 text-[11px] text-slate-500 flex items-start pt-1">
                  {{ h.toString().padStart(2,'0') }}:00
                </div>
              </div>

              <!-- Day columns -->
              <div v-for="(d, dayIdx) in weekDays" :key="dayIdx" class="relative border-l border-slate-200" :data-date="d.toISOString()">
                <!-- Hour lines -->
                <div v-for="h in hours" :key="h" class="h-12 border-b border-slate-100"></div>
                <!-- Events -->
                <div v-for="(ev, idx) in dayEvents[dayIdx]" :key="idx" class="absolute rounded-md text-[11px] leading-tight px-2 py-1 text-white shadow"
                     :class="ev.status === 'pending' ? 'bg-amber-500' : 'bg-blue-600'"
                     :style="eventStyle(ev)">
                  <div class="font-medium truncate">{{ ev.name }}</div>
                  <div class="opacity-90 truncate">{{ ev.timeLabel }}</div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="text-xs text-slate-500">Les réservations refusées ne sont pas affichées dans le calendrier.</div>
      </div>
    </div>
  </section>
</template>

<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { api } from '@/services/api'

const bookings = ref([])
const bikes = ref([])
const loading = ref(false)
const error = ref('')
const lastLoaded = ref(null)
const now = ref(new Date())

// Filter for the list
const filter = ref('all')

// Editing state
const editingId = ref(null)
const editForm = reactive({ bike_type: null })

// Calendar state
const selectedBike = ref('all')
const calendarAnchor = ref(new Date())

onMounted(async () => {
  await Promise.all([loadBikes(), loadBookings()])
  if (!selectedBike.value && bikes.value.length) selectedBike.value = bikes.value[0]
  // Tick 'now' every minute for live status
  setInterval(() => { now.value = new Date() }, 60 * 1000)
})

async function loadBikes() {
  try {
    bikes.value = await api.getBikes()
  } catch (e) {
    error.value = `Erreur chargement vélos: ${e?.message || e}`
  }
}

async function loadBookings() {
  loading.value = true
  error.value = ''
  try {
    bookings.value = await api.listBookings()
    lastLoaded.value = new Date()
  } catch (e) {
    error.value = `Impossible de charger les réservations. ${e?.message || ''}`
  } finally {
    loading.value = false
  }
}

function refresh() { return loadBookings() }

function getSingleBikeType(b) {
  const val = b?.bike_type
  return typeof val === 'number' && Number.isFinite(val) ? val : null
}

function getMultiBikeTypes(b) {
  if (typeof b?.bike_types === 'string' && b.bike_types.trim()) {
    return b.bike_types.split(',').map(s => Number(s.trim())).filter(n => Number.isFinite(n))
  }
  return []
}

function includesBike(b, bike) {
  if (bike === 'all') return true
  const single = getSingleBikeType(b)
  const multi = getMultiBikeTypes(b)
  if (single !== null) return single === bike
  if (multi.length) return multi.includes(bike)
  return false
}

function safeHHmm(timeStr) {
  if (!timeStr || typeof timeStr !== 'string') return ''
  const [h = '00', m = '00'] = timeStr.split(':')
  return `${String(h).padStart(2,'0')}:${String(m).padStart(2,'0')}`
}

function formatRange(b) {
  // Use raw times to avoid TZ issues; still compute if same day
  const s = parseDateTime(b.start_date, b.start_time)
  const e = parseDateTime(b.end_date, b.end_time, true)
  const sameDay = s.toDateString() === e.toDateString()
  const st = safeHHmm(b.start_time)
  const et = safeHHmm(b.end_time)
  if (sameDay) return `${formatDate(s)} ${st} → ${et}`
  return `${formatDate(s)} ${st} → ${formatDate(e)} ${et}`
}

function formatBikes(b) {
  const parts = []
  const single = getSingleBikeType(b)
  if (single !== null) parts.push(String(single))
  const multi = getMultiBikeTypes(b).map(n => String(n))
  parts.push(...multi)
  return parts.length ? parts.join(', ') : '—'
}

function parseDateTime(dateStr, timeStr, end = false) {
  // dateStr = 'YYYY-MM-DD', timeStr = 'HH:MM' or null
  const [y, m, d] = (dateStr || '').split('-').map(Number)
  let h = 0, min = 0
  if (timeStr && timeStr.includes(':')) {
    const [hh, mm] = timeStr.split(':').map(Number)
    h = hh; min = mm
  } else if (end) {
    h = 23; min = 59
  }
  return new Date(y, (m || 1) - 1, d || 1, h, min, 0, 0)
}

function formatDate(d) {
  const dd = String(d.getDate()).padStart(2, '0')
  const mm = String(d.getMonth() + 1).padStart(2, '0')
  const yyyy = d.getFullYear()
  return `${dd}/${mm}/${yyyy}`
}
function formatTime(d) {
  const h = String(d.getHours()).padStart(2, '0')
  const m = String(d.getMinutes()).padStart(2, '0')
  return `${h}:${m}`
}
function formatDateTime(d) { return `${formatDate(d)} ${formatTime(d)}` }

function startEdit(b) {
  editingId.value = b.id
  const bt = getSingleBikeType(b)
  editForm.bike_type = bt !== null ? bt : null
}
function cancelEdit() { editingId.value = null }
async function saveEdit(b) {
  try {
    const payload = { bike_type: editForm.bike_type, bike_types: null }
    await api.updateBooking(b.id, payload)
    editingId.value = null
    await loadBookings()
  } catch (e) {
    alert('Échec de la mise à jour.')
  }
}

// UI status helper for filtering
function uiStatus(b) {
  if (b.status === 'refused') return 'refused'
  const s = parseDateTime(b.start_date, b.start_time)
  const e = parseDateTime(b.end_date, b.end_time, true)
  const n = now.value
  if (b.status === 'accepted') {
    if (n < s) return 'accepted'
    if (n >= s && n <= e) return 'ongoing'
    if (n > e) return 'archived'
  }
  return 'pending'
}

// The filtered list used by the template
const filtered = computed(() => {
  if (filter.value === 'all') return bookings.value
  if (filter.value === 'archived') return bookings.value.filter(b => uiStatus(b) === 'archived' || b.status === 'refused')
  if (filter.value === 'refused') return bookings.value.filter(b => b.status === 'refused')
  return bookings.value.filter(b => uiStatus(b) === filter.value)
})

// Calendar computed
const hours = Array.from({ length: 17 }, (_, i) => i + 6) // 06:00 -> 22:00
const weekStart = computed(() => {
  const d = new Date(calendarAnchor.value)
  const day = d.getDay() || 7 // 1..7, Monday=1
  const start = new Date(d)
  start.setDate(d.getDate() - (day - 1))
  start.setHours(0,0,0,0)
  return start
})
const weekDays = computed(() => Array.from({ length: 7 }, (_, i) => new Date(weekStart.value.getFullYear(), weekStart.value.getMonth(), weekStart.value.getDate() + i)))
const weekEnd = computed(() => {
  const end = new Date(weekStart.value)
  end.setDate(end.getDate() + 6)
  return end
})
function weekdayShort(d) {
  return ['Lun','Mar','Mer','Jeu','Ven','Sam','Dim'][((d.getDay()||7)-1)]
}

function prevWeek() { const d = new Date(calendarAnchor.value); d.setDate(d.getDate() - 7); calendarAnchor.value = d }
function nextWeek() { const d = new Date(calendarAnchor.value); d.setDate(d.getDate() + 7); calendarAnchor.value = d }
function goToday() { calendarAnchor.value = new Date() }

const gridTemplateDays = computed(() => ({ gridTemplateColumns: `80px repeat(7, minmax(0, 1fr))` }))

const dayEvents = computed(() => {
  const map = Array.from({ length: 7 }, () => [])
  if (!selectedBike.value) return map

  const startOfWeek = new Date(weekStart.value)
  const endOfWeek = new Date(weekStart.value)
  endOfWeek.setDate(endOfWeek.getDate() + 7)

  const relevant = bookings.value.filter(b => b.status !== 'refused' && includesBike(b, selectedBike.value))

  for (const b of relevant) {
    const s = parseDateTime(b.start_date, b.start_time)
    const e = parseDateTime(b.end_date, b.end_time, true)
    // Skip if no overlap with the week
    if (e <= startOfWeek || s >= endOfWeek) continue

    for (let i = 0; i < 7; i++) {
      const day = new Date(weekStart.value)
      day.setDate(day.getDate() + i)
      const dayStart = new Date(day)
      dayStart.setHours(0,0,0,0)
      const dayEnd = new Date(day)
      dayEnd.setHours(23,59,59,999)

      const segStart = new Date(Math.max(s.getTime(), dayStart.getTime()))
      const segEnd = new Date(Math.min(e.getTime(), dayEnd.getTime()))
      if (segEnd <= segStart) continue

      const startMin = segStart.getHours() * 60 + segStart.getMinutes()
      const endMin = segEnd.getHours() * 60 + segEnd.getMinutes()

      // Restrict to visible hour range
      const visStart = 6 * 60
      const visEnd = 22 * 60
      const topMin = Math.max(startMin, visStart)
      const botMin = Math.min(endMin, visEnd)
      if (botMin <= visStart || topMin >= visEnd) continue

      const ev = {
        dayIdx: i,
        topMin,
        bottomMin: botMin,
        status: b.status,
        name: b.name,
        timeLabel: `${String(segStart.getHours()).padStart(2,'0')}:${String(segStart.getMinutes()).padStart(2,'0')} → ${String(segEnd.getHours()).padStart(2,'0')}:${String(segEnd.getMinutes()).padStart(2,'0')}`
      }
      map[i].push(ev)
    }
  }

  // Layout: simple column assignment to avoid overlap
  for (let i = 0; i < 7; i++) {
    const events = map[i].sort((a,b) => a.topMin - b.topMin)
    const cols = [] // each col is last bottomMin
    for (const ev of events) {
      let placed = false
      for (let c = 0; c < cols.length; c++) {
        if (ev.topMin >= cols[c]) { ev.col = c; cols[c] = ev.bottomMin; placed = true; break }
      }
      if (!placed) { ev.col = cols.length; cols.push(ev.bottomMin) }
    }
    const count = Math.max(1, cols.length)
    for (const ev of events) ev.colCount = count
  }

  return map
})

function eventStyle(ev) {
  const pxPerMin = 12 / 15 // 48px per hour → 0.8px per minute; Wait: 12*4=48; yes 0.8
  const top = (ev.topMin - 6*60) * pxPerMin
  const height = Math.max(18, (ev.bottomMin - ev.topMin) * pxPerMin)
  const widthPct = 100 / ev.colCount
  const leftPct = ev.col * widthPct
  return {
    top: top + 'px',
    height: height + 'px',
    left: leftPct + '%',
    width: `calc(${widthPct}% - 4px)`,
    marginLeft: '2px',
    marginRight: '2px',
  }
}
</script>

<!-- Status badge as a small sub-component to fix wrapping (whitespace-nowrap) -->
<script>
export default {
  name: 'AdminPage',
  components: {
    StatusBadge: {
      props: { booking: { type: Object, required: true }, now: { type: Object, required: true } },
      methods: {
        parse(dateStr, timeStr, end = false) {
          const [y,m,d] = (dateStr||'').split('-').map(Number)
          let h=0,min=0; if (timeStr && timeStr.includes(':')) { const [hh,mm]=timeStr.split(':').map(Number); h=hh; min=mm } else if (end) { h=23; min=59 }
          return new Date(y, (m||1)-1, d||1, h, min, 0, 0)
        },
      },
      computed: {
        ui() {
          const b = this.booking
          if (b.status === 'refused') return { key: 'archived', label: 'Archivé', cls: 'bg-slate-200 text-slate-700' }
          const s = this.parse(b.start_date, b.start_time)
          const e = this.parse(b.end_date, b.end_time, true)
          const n = this.now
          if (b.status === 'accepted') {
            if (n < s) return { key: 'accepted', label: 'Accepté', cls: 'bg-emerald-100 text-emerald-700' }
            if (n >= s && n <= e) return { key: 'ongoing', label: 'En cours', cls: 'bg-blue-100 text-blue-700' }
            if (n > e) return { key: 'archived', label: 'Archivé', cls: 'bg-slate-200 text-slate-700' }
          }
          return { key: 'pending', label: 'En attente', cls: 'bg-amber-100 text-amber-800' }
        }
      },
      template: `<span class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium whitespace-nowrap" :class="ui.cls">{{ ui.label }}</span>`
    }
  }
}
</script>

<style scoped>
/***** simple card/inputs if not present *****/
/* This page reuses utility classes from BookingPage (btn, input, card). */
</style>
