[id].vue
<template>
  <div class="max-w-3xl mx-auto p-6">
    <h1 class="text-2xl font-bold mb-4">Form Pemesanan</h1>

    <!-- Error umum -->
    <div v-if="error" class="bg-red-100 text-red-600 p-3 rounded mb-4">
      {{ error }}
    </div>

    <!-- Loading -->
    <div v-else-if="loading">Memuat data template...</div>

    <!-- Form -->
    <div v-else>
      <div class="mb-4">
        <p class="text-green-600 font-bold text-lg">Rp {{ Number(template.harga).toLocaleString('id-ID') }}</p>
        <img v-if="template.thumbnail" :src="template.thumbnail" alt="Preview Template" class="w-64 h-40 object-cover rounded" />
      </div>

      <!-- Fitur dinamis -->
      <div class="mt-4">
        <h3 class="font-medium mb-2">Isi Data Fitur:</h3>

        <div v-for="fitur in template.fiturs" :key="fitur.id" class="mb-4">
          <label class="block font-medium mb-1">{{ fitur.deskripsi }}</label>

          <!-- Jika fitur adalah galeri -->
          <div v-if="isGallery(fitur.deskripsi)">
            <input
              type="file"
              :multiple="true"
              :accept="acceptedImageTypes"
              @change="handleGalleryChange($event, fitur.id, parseGalleryMax(fitur.deskripsi))"
              class="w-full"
              :ref="`fileInput_${fitur.id}`"
            />
            <p class="text-sm text-gray-500 mt-1">
              Maks. {{ parseGalleryMax(fitur.deskripsi) || defaultGalleryMax }} file.
              (Terpilih: {{ (files[`fitur_${fitur.id}`] || []).length }})
            </p>
            <p v-if="fileErrors[`fitur_${fitur.id}`]" class="text-sm text-red-600 mt-1">
              {{ fileErrors[`fitur_${fitur.id}`] }}
            </p>
            <!-- Preview gambar yang dipilih -->
            <div v-if="files[`fitur_${fitur.id}`] && files[`fitur_${fitur.id}`].length > 0" class="mt-2 flex flex-wrap gap-2">
              <div v-for="(file, index) in files[`fitur_${fitur.id}`]" :key="index" class="relative">
                <img :src="getFilePreview(file)" alt="Preview" class="w-20 h-20 object-cover rounded border" />
                <button
                  @click="removeFile(`fitur_${fitur.id}`, index)"
                  class="absolute -top-2 -right-2 bg-red-500 text-white rounded-full w-5 h-5 text-xs flex items-center justify-center"
                  type="button"
                >
                  ×
                </button>
              </div>
            </div>
          </div>

          <!-- Jika fitur adalah tanggal -->
          <input
            v-else-if="fitur.deskripsi.toLowerCase().includes('tanggal')"
            type="date"
            v-model="formFields[fieldNameById(fitur.id)]"
            class="w-full border rounded px-3 py-2"
          />

          <!-- default text -->
          <input
            v-else
            type="text"
            v-model="formFields[fieldNameById(fitur.id)]"
            placeholder="Isi data..."
            class="w-full border rounded px-3 py-2"
          />
        </div>
      </div>

      <!-- Data Pemesan -->
      <div class="mt-6">
        <label class="block font-medium">Nama Pemesan *</label>
        <input v-model="baseForm.nama_pemesan" type="text" class="w-full border rounded px-3 py-2 mb-3" required />

        <label class="block font-medium">Email *</label>
        <input v-model="baseForm.email" type="email" class="w-full border rounded px-3 py-2 mb-3" required />

        <label class="block font-medium">Nomor HP *</label>
        <input v-model="baseForm.no_hp" type="text" class="w-full border rounded px-3 py-2 mb-3" required />

        <label class="block font-medium">Catatan</label>
        <textarea v-model="baseForm.catatan" class="w-full border rounded px-3 py-2 mb-3"></textarea>
      </div>

      <!-- Submit -->
      <button @click="submitForm" class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 disabled:opacity-50" :disabled="isSubmitting">
        {{ isSubmitting ? 'Mengirim...' : 'Kirim Pesanan' }}
      </button>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'

const route = useRoute()
const templateId = route.query.template_id

const template = ref({ fiturs: [] })
const loading = ref(true)
const error = ref(null)
const isSubmitting = ref(false)

// base form fields (pemesan)
const baseForm = ref({
  nama_pemesan: '',
  email: '',
  no_hp: '',
  catatan: ''
})

// formFields menyimpan nilai text/date untuk tiap fitur keyed by fieldNameById(fitur.id)
const formFields = ref({}) // { "fitur_1": "Budi", "fitur_2": "2025-09-20", ... }

// files menyimpan File[] per fitur.id
const files = ref({}) // { "fitur_3": [File, File], ... }
const fileErrors = ref({}) // error message per gallery field

const defaultGalleryMax = 10
const acceptedImageTypes = 'image/*'

/** ---------- helper ---------- **/
const slugify = (text) =>
  text.toString().toLowerCase().trim().replace(/\s+/g, '_').replace(/[^\w\-]/g, '')

// fieldName derived from description (used for backend field name logic)
const fieldName = (deskripsi) => slugify(deskripsi)

// fieldNameById used to link formFields stored by fitur.id
const fieldNameById = (id) => `fitur_${id}`

// cek apakah deskripsi adalah gallery
const isGallery = (deskripsi) => deskripsi.toLowerCase().includes('galeri') || deskripsi.toLowerCase().includes('gallery')

// parse number from "Galeri 3" -> 3. Returns null if not found
const parseGalleryMax = (deskripsi) => {
  const m = deskripsi.match(/(\d+)/)
  return m ? parseInt(m[1], 10) : null
}

// create preview URL for file
const getFilePreview = (file) => {
  return URL.createObjectURL(file)
}

// remove file from selection
const removeFile = (fiturKey, index) => {
  if (files.value[fiturKey]) {
    files.value[fiturKey].splice(index, 1)
  }
}

/** ---------- fetch template ---------- **/
onMounted(async () => {
  try {
    const res = await fetch(`http://localhost:8000/api/templates/${templateId}`)
    if (!res.ok) throw new Error('Gagal memuat data template')
    const data = await res.json()
    // backend might wrap as {template:..., fiturs:...} or return template object directly.
    // normalize: if data.template exists, use it, else assume data is template
    const tpl = data.template ?? data
    template.value = tpl

    // setup empty formFields and files for each fitur
    tpl.fiturs?.forEach(f => {
      formFields.value[fieldNameById(f.id)] = ''
      // gallery init
      if (isGallery(f.deskripsi)) {
        files.value[fieldNameById(f.id)] = []
        fileErrors.value[fieldNameById(f.id)] = ''
      }
    })
  } catch (err) {
    console.error(err)
    error.value = err.message || 'Gagal memuat template'
  } finally {
    loading.value = false
  }
})

/** ---------- handle gallery selection ---------- **/
function handleGalleryChange(event, fiturId, maxAllowed) {
  const selected = Array.from(event.target.files || [])
  const allowed = maxAllowed || defaultGalleryMax
  const fiturKey = fieldNameById(fiturId)

  // reset error
  fileErrors.value[fiturKey] = ''

  // client-side validation for file count
  if (selected.length > allowed) {
    fileErrors.value[fiturKey] = `Jumlah file melebihi batas (${allowed}). Pilih maksimal ${allowed} file.`
    files.value[fiturKey] = []
    event.target.value = '' // reset input
    return
  }

  // optional: validate file types and sizes (e.g., < 10MB)
  const tooLarge = selected.find(f => f.size > 10 * 1024 * 1024) // 10MB
  if (tooLarge) {
    fileErrors.value[fiturKey] = 'Satu atau lebih file melebihi 10MB.'
    files.value[fiturKey] = []
    event.target.value = ''
    return
  }

  // validate image types
  const invalidType = selected.find(f => !f.type.startsWith('image/'))
  if (invalidType) {
    fileErrors.value[fiturKey] = 'File harus berupa gambar (JPG, PNG, GIF, dll).'
    files.value[fiturKey] = []
    event.target.value = ''
    return
  }

  // all good
  files.value[fiturKey] = selected
}

/** ---------- submit ---------- **/
const submitForm = async () => {
  if (isSubmitting.value) return
  
  error.value = null
  isSubmitting.value = true

  // client basic check: required base fields
  if (!baseForm.value.nama_pemesan || !baseForm.value.no_hp || !baseForm.value.email) {
    error.value = 'Nama pemesan, No HP, dan Email wajib diisi.'
    isSubmitting.value = false
    return
  }

  // validate email format
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
  if (!emailRegex.test(baseForm.value.email)) {
    error.value = 'Format email tidak valid.'
    isSubmitting.value = false
    return
  }

  try {
    // use FormData because there may be files
    const fd = new FormData()
    fd.append('template_id', templateId)
    fd.append('nama_pemesan', baseForm.value.nama_pemesan)
    fd.append('email', baseForm.value.email)
    fd.append('no_hp', baseForm.value.no_hp)
    fd.append('catatan', baseForm.value.catatan || '')

    // append feature values (text/date) and files
    template.value.fiturs?.forEach(fitur => {
      const fiturKey = fieldNameById(fitur.id)
      const fieldNameForBackend = fieldName(fitur.deskripsi)

      // for gallery fields, append files
      if (isGallery(fitur.deskripsi)) {
        const fileArray = files.value[fiturKey] || []
        console.log(`Appending ${fileArray.length} files for ${fieldNameForBackend}`)
        
        if (fileArray.length > 0) {
          // append files with proper array notation for Laravel
          fileArray.forEach((file, index) => {
            fd.append(`${fieldNameForBackend}[]`, file)
            console.log(`Added file ${index}:`, file.name, file.type, file.size)
          })
        }
      } else {
        // for text/date fields
        const value = formFields.value[fiturKey]
        if (value !== undefined && value !== null && String(value).trim() !== '') {
          fd.append(fieldNameForBackend, value)
        }
      }
    })

    // Debug: log FormData contents
    console.log('FormData contents:')
    for (let pair of fd.entries()) {
      console.log(pair[0] + ':', pair[1])
    }

    // fetch POST (do NOT set Content-Type — browser sets multipart boundary)
    const res = await fetch('http://localhost:8000/api/form', {
      method: 'POST',
      body: fd,
    })

    const data = await res.json()
    console.log('Response:', data)

    if (!res.ok) {
      if (data.errors) {
        // flatten errors object from Laravel
        const errorMessages = Object.entries(data.errors).map(([field, messages]) => {
          return `${field}: ${Array.isArray(messages) ? messages.join(', ') : messages}`
        })
        error.value = errorMessages.join(' | ')
      } else {
        error.value = data.message || 'Gagal mengirim form'
      }
      return
    }

    alert('Pesanan berhasil dikirim!')
    // reset inputs
    resetForm()
    
  } catch (err) {
    console.error('Submit error:', err)
    error.value = 'Terjadi kesalahan saat mengirim form.'
  } finally {
    isSubmitting.value = false
  }
}

// reset form function
const resetForm = () => {
  baseForm.value = { nama_pemesan: '', email: '', no_hp: '', catatan: '' }
  // reset feature fields and files
  template.value.fiturs?.forEach(f => {
    const fiturKey = fieldNameById(f.id)
    formFields.value[fiturKey] = ''
    if (isGallery(f.deskripsi)) {
      files.value[fiturKey] = []
      fileErrors.value[fiturKey] = ''
    }
  })
  
  // reset file inputs
  document.querySelectorAll('input[type="file"]').forEach(input => {
    input.value = ''
  })
}
</script>

<style scoped>
/* Custom styling if needed */
</style>