<template>
  <IonPage>
    <IonHeader>
      <IonToolbar color="primary">
        <IonButtons slot="start">
          <IonMenuButton />
        </IonButtons>
        <IonTitle>Manage Boats</IonTitle>
        <IonButtons slot="end">
          <IonButton @click="openCreate">
            <IonIcon slot="icon-only" :icon="addOutline" />
          </IonButton>
        </IonButtons>
      </IonToolbar>
    </IonHeader>

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

      <p v-else-if="boats.length === 0" class="empty-text">No boats yet. Add one to get started.</p>

      <IonCard v-else v-for="boat in boats" :key="boat.id" class="boat-card">
        <div class="boat-card-inner">
          <div class="boat-thumb-wrap">
            <img
              v-if="boat.img_src"
              :src="boatImage.thumbnail(boat.img_src)"
              class="boat-thumb"
              alt=""
            />
            <div v-else class="boat-thumb-placeholder">
              <IonIcon :icon="boatOutline" />
            </div>
          </div>
          <div class="boat-info">
            <div class="boat-name">{{ boat.display_name || boat.name }}</div>
            <div class="boat-meta">
              <span v-if="boat.class">{{ boat.class }}</span>
              <span v-if="boat.year">{{ boat.year }}</span>
              <span>{{ boat.max_passengers }} pax</span>
            </div>
            <div class="cert-chips" v-if="boat.required_certs.length">
              <span v-for="c in boat.required_certs" :key="c" class="cert-chip">{{ c }}</span>
            </div>
            <IonBadge :color="boat.booking_available ? 'success' : 'medium'" class="avail-badge">
              {{ boat.booking_available ? 'Available' : 'Out of service' }}
            </IonBadge>
          </div>
          <div class="boat-actions">
            <IonButton fill="clear" @click="openEdit(boat)">
              <IonIcon slot="icon-only" :icon="pencilOutline" />
            </IonButton>
            <IonButton fill="clear" color="danger" @click="confirmDelete(boat)">
              <IonIcon slot="icon-only" :icon="trashOutline" />
            </IonButton>
          </div>
        </div>
      </IonCard>

      <!-- Create / Edit modal -->
      <IonModal :is-open="showModal" @did-dismiss="closeModal">
        <IonHeader>
          <IonToolbar>
            <IonTitle>{{ editing ? 'Edit Boat' : 'New Boat' }}</IonTitle>
            <IonButtons slot="end">
              <IonButton @click="closeModal">Cancel</IonButton>
            </IonButtons>
          </IonToolbar>
        </IonHeader>
        <IonContent class="ion-padding">

          <!-- Image upload section -->
          <div class="image-section">
            <div class="image-preview-wrap" @click="triggerFileInput">
              <img v-if="imagePreviewUrl" :src="imagePreviewUrl" class="image-preview" alt="Boat preview" />
              <div v-else-if="form.img_src" class="image-preview-wrap">
                <img :src="boatImage.medium(form.img_src)" class="image-preview" alt="Current boat image" />
              </div>
              <div v-else class="image-placeholder">
                <IonIcon :icon="cameraOutline" class="camera-icon" />
                <span>Tap to upload photo</span>
              </div>
              <div v-if="imagePreviewUrl || form.img_src" class="image-overlay">
                <IonIcon :icon="cameraOutline" />
              </div>
            </div>
            <input
              ref="fileInputRef"
              type="file"
              accept="image/jpeg,image/png,image/webp"
              class="hidden-file-input"
              @change="onFileSelected"
            />
            <p v-if="pendingFile" class="image-hint">{{ pendingFile.name }} — will upload on save</p>
          </div>

          <IonList lines="full">
            <IonItem>
              <IonLabel position="stacked">Name <span class="required">*</span></IonLabel>
              <IonInput v-model="form.name" placeholder="e.g. J27-1" />
            </IonItem>
            <IonItem>
              <IonLabel position="stacked">Display Name</IonLabel>
              <IonInput v-model="form.display_name" placeholder="e.g. Blue Heron" />
            </IonItem>
            <IonItem>
              <IonLabel position="stacked">Class</IonLabel>
              <IonInput v-model="form.class" placeholder="e.g. J/27" />
            </IonItem>
            <IonItem>
              <IonLabel position="stacked">Year</IonLabel>
              <IonInput v-model.number="form.year" type="number" placeholder="e.g. 1988" />
            </IonItem>
            <IonItem>
              <IonLabel position="stacked">Max Passengers</IonLabel>
              <IonInput v-model.number="form.max_passengers" type="number" :min="1" :max="20" />
            </IonItem>
            <IonItem>
              <IonLabel>
                <h3>Available for Booking</h3>
              </IonLabel>
              <IonToggle v-model="form.booking_available" slot="end" color="success" />
            </IonItem>
          </IonList>

          <!-- Required certifications -->
          <h4 class="section-title ion-margin-top">Required Certifications</h4>
          <div class="cert-edit-area">
            <div class="cert-chips-edit" v-if="form.required_certs.length">
              <span v-for="(c, i) in form.required_certs" :key="i" class="cert-chip-edit">
                {{ c }}
                <button class="cert-remove" @click="removeCert(i)">×</button>
              </span>
            </div>
            <p v-else class="empty-text-sm">No certifications required.</p>
            <div class="cert-add-row">
              <IonInput
                v-model="newCert"
                placeholder="Add cert code (e.g. j27)"
                class="cert-input"
                @keyup.enter="addCert"
              />
              <IonButton @click="addCert" :disabled="!newCert.trim()" fill="outline">
                <IonIcon slot="icon-only" :icon="addOutline" />
              </IonButton>
            </div>
          </div>

          <IonButton
            expand="block"
            class="ion-margin-top"
            :disabled="!form.name.trim() || saving"
            @click="saveBoat"
          >
            <IonSpinner v-if="saving" name="crescent" slot="start" />
            {{ saving ? 'Saving…' : 'Save Boat' }}
          </IonButton>
        </IonContent>
      </IonModal>

      <IonAlert
        :is-open="deleteAlert.show"
        header="Delete Boat"
        :message="`Delete '${deleteAlert.name}'? All slots and reservations for this boat will also be deleted.`"
        :buttons="[
          { text: 'Cancel', role: 'cancel', handler: () => { deleteAlert.show = false } },
          { text: 'Delete', role: 'destructive', handler: deleteBoat },
        ]"
        @did-dismiss="deleteAlert.show = false"
      />

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

<script setup lang="ts">
import {
  IonPage, IonHeader, IonToolbar, IonTitle, IonContent, IonButtons,
  IonMenuButton, IonButton, IonIcon, IonCard, IonBadge,
  IonList, IonItem, IonLabel, IonInput, IonToggle, IonSpinner,
  IonModal, IonAlert, IonToast, onIonViewWillEnter,
} from '@ionic/vue'
import { addOutline, pencilOutline, trashOutline, boatOutline, cameraOutline } from 'ionicons/icons'
import type { Database } from '~/types/supabase'

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

definePageMeta({ layout: false, middleware: ['auth'] })

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const supabase = useSupabaseClient() as any
const boatImage = useBoatImage()

const loading = ref(true)
const saving = ref(false)
const showModal = ref(false)
const editing = ref<Boat | null>(null)
const boats = ref<Boat[]>([])
const toast = reactive({ show: false, message: '', color: 'success' })
const deleteAlert = reactive({ show: false, id: '', name: '' })

const fileInputRef = ref<HTMLInputElement | null>(null)
const pendingFile = ref<File | null>(null)
const imagePreviewUrl = ref<string>('')
const newCert = ref('')

const form = reactive({
  name: '',
  display_name: '',
  class: '',
  year: null as number | null,
  max_passengers: 6,
  booking_available: true,
  required_certs: [] as string[],
  img_src: null as string | null,
})

const user = useSupabaseUser()
watch(user, (val) => { if (val) fetchBoats() }, { immediate: true })
onIonViewWillEnter(() => { if (user.value) fetchBoats() })

async function fetchBoats() {
  loading.value = true
  const { data } = await supabase.from('boats').select('*').order('name')
  boats.value = data ?? []
  loading.value = false
}

function openCreate() {
  editing.value = null
  resetForm()
  showModal.value = true
}

function openEdit(boat: Boat) {
  editing.value = boat
  form.name = boat.name
  form.display_name = boat.display_name ?? ''
  form.class = boat.class ?? ''
  form.year = boat.year ?? null
  form.max_passengers = boat.max_passengers
  form.booking_available = boat.booking_available
  form.required_certs = [...boat.required_certs]
  form.img_src = boat.img_src
  pendingFile.value = null
  imagePreviewUrl.value = ''
  showModal.value = true
}

function closeModal() {
  showModal.value = false
  editing.value = null
  resetForm()
}

function resetForm() {
  form.name = ''
  form.display_name = ''
  form.class = ''
  form.year = null
  form.max_passengers = 6
  form.booking_available = true
  form.required_certs = []
  form.img_src = null
  pendingFile.value = null
  if (imagePreviewUrl.value) URL.revokeObjectURL(imagePreviewUrl.value)
  imagePreviewUrl.value = ''
  newCert.value = ''
}

function triggerFileInput() {
  fileInputRef.value?.click()
}

function onFileSelected(event: Event) {
  const file = (event.target as HTMLInputElement).files?.[0]
  if (!file) return
  pendingFile.value = file
  if (imagePreviewUrl.value) URL.revokeObjectURL(imagePreviewUrl.value)
  imagePreviewUrl.value = URL.createObjectURL(file)
}

function addCert() {
  const c = newCert.value.trim().toLowerCase()
  if (c && !form.required_certs.includes(c)) {
    form.required_certs.push(c)
  }
  newCert.value = ''
}

function removeCert(index: number) {
  form.required_certs.splice(index, 1)
}

async function saveBoat() {
  saving.value = true

  const payload = {
    name: form.name.trim(),
    display_name: form.display_name.trim() || null,
    class: form.class.trim() || null,
    year: form.year || null,
    max_passengers: form.max_passengers,
    booking_available: form.booking_available,
    required_certs: form.required_certs,
  }

  let boatId = editing.value?.id
  let error

  if (editing.value) {
    ;({ error } = await supabase.from('boats').update(payload).eq('id', boatId))
  } else {
    const { data, error: insertError } = await supabase
      .from('boats').insert(payload).select('id').single()
    error = insertError
    boatId = data?.id
  }

  if (error) {
    saving.value = false
    showToast('Save failed: ' + error.message, 'danger')
    return
  }

  // Upload image if a new file was selected
  if (pendingFile.value && boatId) {
    const ext = pendingFile.value.name.split('.').pop() ?? 'jpg'
    const path = `boats/${boatId}/original.${ext}`
    const { error: uploadError } = await supabase.storage
      .from('boat-images')
      .upload(path, pendingFile.value, { upsert: true, contentType: pendingFile.value.type })

    if (uploadError) {
      saving.value = false
      showToast('Boat saved but image upload failed: ' + uploadError.message, 'warning')
      await fetchBoats()
      closeModal()
      return
    }

    await supabase.from('boats').update({ img_src: path }).eq('id', boatId)
  }

  saving.value = false
  closeModal()
  await fetchBoats()
  showToast(editing.value ? 'Boat updated' : 'Boat created', 'success')
}

function confirmDelete(boat: Boat) {
  deleteAlert.id = boat.id
  deleteAlert.name = boat.display_name || boat.name
  deleteAlert.show = true
}

async function deleteBoat() {
  deleteAlert.show = false
  const { error } = await supabase.from('boats').delete().eq('id', deleteAlert.id)
  if (error) { showToast('Delete failed: ' + error.message, 'danger'); return }
  await fetchBoats()
  showToast('Boat deleted', 'success')
}

function showToast(message: string, color: string) {
  toast.message = message
  toast.color = color
  toast.show = true
}
</script>

<style scoped>
.boat-card { margin: 0 0 0.75rem; }
.boat-card-inner {
  display: flex;
  align-items: flex-start;
  padding: 0.75rem;
  gap: 0.75rem;
}
.boat-thumb-wrap { flex-shrink: 0; }
.boat-thumb {
  width: 72px;
  height: 72px;
  object-fit: cover;
  border-radius: 0.5rem;
}
.boat-thumb-placeholder {
  width: 72px;
  height: 72px;
  border-radius: 0.5rem;
  background: var(--ion-color-light);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  color: var(--ion-color-medium);
}
.boat-info { flex: 1; min-width: 0; }
.boat-name { font-weight: 600; font-size: 1rem; }
.boat-meta {
  display: flex;
  gap: 0.5rem;
  font-size: 0.8rem;
  color: var(--ion-color-medium);
  margin: 0.2rem 0;
}
.cert-chips { display: flex; flex-wrap: wrap; gap: 0.3rem; margin: 0.3rem 0; }
.cert-chip {
  font-size: 0.72rem;
  padding: 0.15rem 0.5rem;
  border-radius: 1rem;
  background: var(--ion-color-primary-tint);
  color: var(--ion-color-primary-shade);
  font-weight: 500;
}
.avail-badge { font-size: 0.7rem; }
.boat-actions { display: flex; flex-direction: column; flex-shrink: 0; }

/* Modal image section */
.image-section { margin-bottom: 1rem; }
.image-preview-wrap {
  position: relative;
  width: 100%;
  height: 200px;
  border-radius: 0.75rem;
  overflow: hidden;
  background: var(--ion-color-light);
  cursor: pointer;
}
.image-preview {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.image-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  gap: 0.5rem;
  color: var(--ion-color-medium);
  font-size: 0.9rem;
}
.camera-icon { font-size: 2.5rem; }
.image-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 2rem;
  opacity: 0;
  transition: opacity 0.2s;
}
.image-preview-wrap:hover .image-overlay { opacity: 1; }
.hidden-file-input { display: none; }
.image-hint { font-size: 0.78rem; color: var(--ion-color-medium); margin: 0.25rem 0 0; }

.required { color: var(--ion-color-danger); }
.section-title { font-size: 0.95rem; font-weight: 600; margin: 0 0 0.5rem; }

/* Cert editor */
.cert-edit-area { margin-bottom: 0.75rem; }
.cert-chips-edit { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 0.5rem; }
.cert-chip-edit {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.2rem 0.6rem;
  border-radius: 1rem;
  background: var(--ion-color-primary-tint);
  color: var(--ion-color-primary-shade);
  font-size: 0.82rem;
  font-weight: 500;
}
.cert-remove {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  line-height: 1;
  font-size: 1rem;
  color: var(--ion-color-primary-shade);
}
.cert-add-row { display: flex; gap: 0.5rem; align-items: center; }
.cert-input { flex: 1; }
.empty-text { color: var(--ion-color-medium); text-align: center; padding: 2rem 0; }
.empty-text-sm { color: var(--ion-color-medium); font-size: 0.85rem; margin: 0.25rem 0; }
</style>
