<template>
  <IonPage>
    <IonHeader>
      <IonToolbar color="primary">
        <IonButtons slot="start">
          <IonBackButton default-href="/" />
        </IonButtons>
        <IonTitle>New Reservation</IonTitle>
      </IonToolbar>
    </IonHeader>

    <IonContent class="ion-padding">
      <!-- Step 1: Pick a date and select a slot -->
      <template v-if="step === 1">
        <h3 class="section-title">Select Date</h3>

        <!-- Horizontal date strip -->
        <div class="date-strip">
          <button
            v-for="d in dateOptions"
            :key="d.iso"
            class="date-chip"
            :class="{ active: selectedDate === d.iso }"
            @click="selectedDate = d.iso"
          >
            <span class="day-name">{{ d.dayName }}</span>
            <span class="day-num">{{ d.dayNum }}</span>
            <span class="month">{{ d.month }}</span>
          </button>
        </div>

        <h3 class="section-title ion-margin-top">Available Slots</h3>

        <div v-if="loadingSlots" class="ion-text-center ion-padding">
          <IonSpinner name="crescent" />
        </div>

        <p v-else-if="availableByBoat.length === 0" class="empty-text">
          No available slots for this date.
        </p>

        <template v-else>
          <IonCard
            v-for="entry in availableByBoat"
            :key="entry.boat.id"
            class="boat-card"
          >
            <IonCardHeader>
              <IonCardTitle>{{ entry.boat.display_name || entry.boat.name }}</IonCardTitle>
              <IonCardSubtitle v-if="entry.boat.class">{{ entry.boat.class }}</IonCardSubtitle>
            </IonCardHeader>
            <IonCardContent>
              <div v-if="!entry.certified" class="cert-warning">
                <IonIcon :icon="warningOutline" color="warning" />
                <span>You are not certified for this boat.</span>
              </div>
              <div class="slot-chips">
                <button
                  v-for="slot in entry.slots"
                  :key="slot.id"
                  class="slot-chip"
                  :disabled="!entry.certified"
                  @click="selectSlot(entry.boat, slot)"
                >
                  {{ formatSlotTime(slot.start_time) }}–{{ formatSlotTime(slot.end_time) }}
                </button>
              </div>
            </IonCardContent>
          </IonCard>
        </template>
      </template>

      <!-- Step 2: Confirm details -->
      <template v-else>
        <IonCard>
          <IonCardHeader>
            <IonCardTitle>{{ selectedBoat?.display_name || selectedBoat?.name }}</IonCardTitle>
            <IonCardSubtitle v-if="selectedBoat?.class">{{ selectedBoat.class }}</IonCardSubtitle>
          </IonCardHeader>
          <IonCardContent>
            <div class="time-summary">
              <div class="time-row">
                <IonIcon :icon="timeOutline" />
                <span>{{ formatFull(selectedSlot!.start_time) }} – {{ formatSlotTime(selectedSlot!.end_time) }}</span>
              </div>
            </div>
          </IonCardContent>
        </IonCard>

        <IonList lines="full" class="ion-margin-top">
          <IonItem>
            <IonLabel position="stacked">Reason</IonLabel>
            <IonSelect v-model="form.reason" placeholder="Select reason" interface="action-sheet">
              <IonSelectOption v-for="r in reasonOptions" :key="r" :value="r">{{ r }}</IonSelectOption>
            </IonSelect>
          </IonItem>
          <IonItem>
            <IonLabel position="stacked">Additional Comments (optional)</IonLabel>
            <IonTextarea v-model="form.comment" :rows="3" placeholder="Any notes..." />
          </IonItem>
        </IonList>

        <div class="form-actions">
          <IonButton fill="outline" @click="step = 1">Back</IonButton>
          <IonButton
            :disabled="!form.reason || submitting"
            @click="submitReservation"
          >
            <IonSpinner v-if="submitting" name="crescent" slot="start" />
            Confirm Booking
          </IonButton>
        </div>

        <IonToast
          v-model:is-open="toast.show"
          :message="toast.message"
          :color="toast.color"
          :duration="3000"
          position="bottom"
        />
      </template>
    </IonContent>
  </IonPage>
</template>

<script setup lang="ts">
import {
  IonPage, IonHeader, IonToolbar, IonTitle, IonContent, IonButtons,
  IonBackButton, IonCard, IonCardHeader, IonCardTitle, IonCardSubtitle,
  IonCardContent, IonList, IonItem, IonLabel, IonSelect, IonSelectOption,
  IonTextarea, IonButton, IonSpinner, IonIcon, IonToast,
} from '@ionic/vue'
import { timeOutline, warningOutline } from 'ionicons/icons'
import { useAuthStore } from '~/stores/auth'
import { toDateToronto } from '~/utils/toronto'
import type { Database } from '~/types/supabase'

type Boat = Database['public']['Tables']['boats']['Row']
type Interval = Database['public']['Tables']['intervals']['Row']

definePageMeta({ layout: false })

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const supabase = useSupabaseClient() as any
const auth = useAuthStore()
const router = useRouter()
const route = useRoute()

const step = ref<1 | 2>(1)
const loadingSlots = ref(false)
const submitting = ref(false)
const selectedDate = ref(todayIso())
const selectedBoat = ref<Boat | null>(null)
const selectedSlot = ref<Interval | null>(null)
const toast = reactive({ show: false, message: '', color: 'success' })

const form = reactive({ reason: '', comment: '' })
const reasonOptions = ['Open Sail', 'Private Sail', 'Racing', 'Training', 'Other']

// 14-day date strip starting today
const dateOptions = computed(() => {
  const out = []
  const base = new Date()
  for (let i = 0; i < 14; i++) {
    const d = new Date(base)
    d.setDate(base.getDate() + i)
    out.push({
      iso: toIso(d),
      dayName: d.toLocaleDateString('en-CA', { weekday: 'short' }),
      dayNum: d.getDate(),
      month: d.toLocaleDateString('en-CA', { month: 'short' }),
    })
  }
  return out
})

interface BoatSlotEntry {
  boat: Boat
  slots: Interval[]
  certified: boolean
}

const availableByBoat = ref<BoatSlotEntry[]>([])

// Pre-populate from schedule deep-link: ?boatId=&startTime=&endTime=
onMounted(async () => {
  const { boatId, startTime, endTime } = route.query as Record<string, string>
  if (boatId && startTime && endTime) {
    const { data: boat } = await supabase.from('boats').select('*').eq('id', boatId).single()
    if (boat) {
      selectedBoat.value = boat as Boat
      selectedSlot.value = {
        id: '',
        boat_id: boatId,
        start_time: startTime,
        end_time: endTime,
        user_id: null,
        created_at: '',
      }
      // Set the date strip to the slot's date so Back returns to correct day
      selectedDate.value = toDateToronto(new Date(startTime))
      step.value = 2
      return
    }
  }
  // Normal flow: load slots for today
  await loadSlots()
})

watch(selectedDate, loadSlots)

async function loadSlots() {
  loadingSlots.value = true
  availableByBoat.value = []

  const dayStart = selectedDate.value + 'T00:00:00Z'
  const dayEnd   = selectedDate.value + 'T23:59:59Z'

  // Load available intervals + boats (booking_available = true) for selected date
  const { data: intervals, error } = await supabase
    .from('intervals')
    .select('*, boats!inner(id, name, display_name, class, img_src, booking_available, required_certs, max_passengers, defects, year, icon_src, created_at)')
    .gte('start_time', dayStart)
    .lte('start_time', dayEnd)
    .eq('boats.booking_available', true)
    .order('start_time', { ascending: true })

  if (error) { loadingSlots.value = false; return }

  // Load booked slots via reservation_slots view (hides personal details)
  const { data: bookedSlots } = await supabase
    .from('reservation_slots')
    .select('boat_id, start_time, end_time')
    .gte('start_time', dayStart)
    .lte('start_time', dayEnd)

  const booked = new Set<string>()
  for (const r of (bookedSlots ?? []) as { boat_id: string; start_time: string; end_time: string }[]) {
    booked.add(`${r.boat_id}|${r.start_time}|${r.end_time}`)
  }

  const memberCerts: string[] = auth.member?.certifications ?? []

  // Group by boat, filtering out booked slots
  const byBoat = new Map<string, BoatSlotEntry>()
  for (const row of intervals ?? []) {
    const boat = (row as unknown as { boats: Boat }).boats
    const key = `${boat.id}|${row.start_time}|${row.end_time}`
    if (booked.has(key)) continue

    if (!byBoat.has(boat.id)) {
      byBoat.set(boat.id, {
        boat,
        slots: [],
        certified: boat.required_certs.length === 0 ||
          boat.required_certs.every(c => memberCerts.includes(c)),
      })
    }
    byBoat.get(boat.id)!.slots.push(row as Interval)
  }

  availableByBoat.value = Array.from(byBoat.values())
  loadingSlots.value = false
}

function selectSlot(boat: Boat, slot: Interval) {
  selectedBoat.value = boat
  selectedSlot.value = slot
  form.reason = ''
  form.comment = ''
  step.value = 2
}

async function submitReservation() {
  if (!auth.user || !selectedBoat.value || !selectedSlot.value) return
  submitting.value = true

  const { data: sessionData } = await supabase.auth.getSession()
  const accessToken = sessionData.session?.access_token ?? ''

  const response = await supabase.functions.invoke('create-reservation', {
    body: {
      boat_id:    selectedBoat.value.id,
      start_time: selectedSlot.value.start_time,
      end_time:   selectedSlot.value.end_time,
      reason:     form.reason,
      comment:    form.comment,
    },
    headers: { Authorization: `Bearer ${accessToken}` },
  })

  submitting.value = false

  if (response.error || (response.data as { error?: { code: string; message: string } })?.error) {
    const apiError = (response.data as { error?: { code: string; message: string } })?.error
    const codeMessages: Record<string, string> = {
      cert_required:         'You are not certified for this boat.',
      slot_taken:            'This slot was just booked by someone else.',
      booking_limit_weekly:  apiError?.message ?? 'Weekly booking limit reached.',
      booking_limit_weekend: apiError?.message ?? 'Weekend booking limit reached.',
      boat_unavailable:      'This boat is currently out of service.',
    }
    toast.message = (apiError?.code && codeMessages[apiError.code]) || apiError?.message || 'Failed to create reservation.'
    toast.color = 'danger'
    toast.show = true
    return
  }

  toast.message = 'Reservation created!'
  toast.color = 'success'
  toast.show = true
  setTimeout(() => router.push('/'), 1500)
}

function todayIso() {
  return toIso(new Date())
}

function toIso(d: Date) {
  return d.toISOString().slice(0, 10)
}

function formatSlotTime(iso: string) {
  return new Date(iso).toLocaleTimeString('en-CA', { hour: '2-digit', minute: '2-digit', hour12: false })
}

function formatFull(iso: string) {
  return new Date(iso).toLocaleDateString('en-CA', { weekday: 'short', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })
}
</script>

<style scoped>
.section-title {
  font-size: 1rem;
  font-weight: 600;
  margin: 0 0 0.5rem;
}

.date-strip {
  display: flex;
  gap: 0.5rem;
  overflow-x: auto;
  padding-bottom: 0.5rem;
  scrollbar-width: none;
}
.date-strip::-webkit-scrollbar { display: none; }

.date-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 52px;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--ion-color-light-shade);
  border-radius: 0.5rem;
  background: var(--ion-color-light);
  cursor: pointer;
  font-size: 0.75rem;
  gap: 2px;
  flex-shrink: 0;
}
.date-chip.active {
  background: var(--ion-color-primary);
  color: white;
  border-color: var(--ion-color-primary);
}
.day-name { font-weight: 600; text-transform: uppercase; font-size: 0.65rem; }
.day-num { font-size: 1.1rem; font-weight: 700; }
.month { font-size: 0.65rem; }

.boat-card { margin: 0 0 1rem; }

.cert-warning {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--ion-color-warning-shade);
  font-size: 0.85rem;
  margin-bottom: 0.5rem;
}

.slot-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.slot-chip {
  padding: 0.4rem 0.75rem;
  border-radius: 1rem;
  border: 1px solid var(--ion-color-primary);
  background: transparent;
  color: var(--ion-color-primary);
  font-size: 0.85rem;
  cursor: pointer;
  font-weight: 500;
}
.slot-chip:disabled {
  border-color: var(--ion-color-medium);
  color: var(--ion-color-medium);
  cursor: not-allowed;
}
.slot-chip:not(:disabled):hover {
  background: var(--ion-color-primary);
  color: white;
}

.time-summary { display: flex; flex-direction: column; gap: 0.4rem; }
.time-row { display: flex; align-items: center; gap: 0.5rem; font-size: 0.95rem; }

.empty-text { color: var(--ion-color-medium); text-align: center; padding: 2rem 0; }

.form-actions {
  display: flex;
  gap: 0.75rem;
  justify-content: flex-end;
  margin-top: 1.5rem;
}
</style>
