<template>
  <div class="space-y-4">
    <section class="space-y-3">
      <div class="flex items-center justify-between">
        <h3 class="text-sm font-semibold">
          Champs personnalisés
        </h3>
        <button type="button" class="btn btn-outline btn-xs" @click="addField">
          <IconLucidePlus class="w-3 h-3 mr-2" aria-hidden="true" />
          Ajouter
        </button>
      </div>

      <p v-if="!localFields.length" class="text-xs text-gray-500">
        Aucun champ personnalisé n'a encore été défini.
      </p>

      <div v-else class="space-y-2">
        <div
          v-for="(field, index) in localFields"
          :key="`custom-field-${index}`"
          class="border border-base-200 rounded-md p-3 space-y-2"
        >
          <div class="flex items-start justify-between gap-2">
            <div class="flex-1 space-y-2">
              <div class="grid grid-cols-1 md:grid-cols-2 gap-2">
                <input
                  v-model="field.name"
                  type="text"
                  class="input input-bordered input-xs"
                  placeholder="Nom du champ"
                >
                <select v-model="field.type" class="select select-bordered select-xs">
                  <option value="text">
                    Texte
                  </option>
                  <option value="number">
                    Nombre
                  </option>
                  <option value="select">
                    Liste
                  </option>
                  <option value="boolean">
                    Oui/Non
                  </option>
                  <option value="date">
                    Date
                  </option>
                </select>
              </div>

              <div class="flex items-center gap-2 text-xs">
                <input v-model="field.required" type="checkbox" class="checkbox checkbox-xs">
                Obligatoire
              </div>

              <textarea
                v-if="field.type === 'select'"
                v-model="field.optionsText"
                class="textarea textarea-bordered textarea-xs h-20"
                placeholder="Option 1&#10;Option 2"
              />
            </div>
            <button
              type="button"
              class="btn btn-error btn-xs btn-square"
              @click="removeField(index)"
            >
              <IconLucideTrash class="w-4 h-4" aria-hidden="true" />
            </button>
          </div>
        </div>
      </div>
    </section>
  </div>
</template>

<script setup>
import { computed, reactive, watch } from 'vue'
import IconLucidePlus from '~icons/lucide/plus'
import IconLucideTrash from '~icons/lucide/trash'

const props = defineProps({
  modelValue: {
    type: Object,
    default: () => ({ customFields: [] })
  }
})

const emit = defineEmits(['update:modelValue'])

const ensureArray = value => (Array.isArray(value) ? value : [])

const clone = (input, fallback = {}) => {
  try {
    return JSON.parse(JSON.stringify(input ?? fallback))
  } catch (error) {
    return JSON.parse(JSON.stringify(fallback))
  }
}

const extractRest = (structure = {}) => {
  if (!structure || typeof structure !== 'object') {
    return {}
  }
  return Object.fromEntries(
    Object.entries(structure).filter(([key]) => key !== 'customFields')
  )
}

const toEditorField = (input = {}) => ({
  name: typeof input.name === 'string' ? input.name : '',
  type: typeof input.type === 'string' && input.type ? input.type : 'text',
  required: Boolean(input.required),
  optionsText: Array.isArray(input.options)
    ? input.options.join('\n')
    : typeof input.optionsText === 'string'
      ? input.optionsText
      : ''
})

const hydrateFields = (structure = {}) => ensureArray(structure.customFields).map(toEditorField)

const localState = reactive({
  fields: hydrateFields(props.modelValue)
})

const extraState = reactive({
  rest: clone(extractRest(props.modelValue))
})

const localFields = computed({
  get: () => localState.fields,
  set: (value) => {
    localState.fields = ensureArray(value).map(toEditorField)
  }
})

const normalizeFields = (fields) => {
  return ensureArray(fields)
    .map((field) => {
      const name = typeof field.name === 'string' ? field.name.trim() : ''
      if (!name) {
        return null
      }

      const type = field.type || 'text'
      const required = Boolean(field.required)
      let options
      if (type === 'select') {
        const raw = typeof field.optionsText === 'string' ? field.optionsText : ''
        const parsed = raw
          .split(/\r?\n/)
          .map(option => option.trim())
          .filter(option => option.length > 0)
        options = parsed.length > 0 ? parsed : undefined
      }

      const normalized = { name, type, required }
      if (options) {
        normalized.options = options
      }
      return normalized
    })
    .filter(Boolean)
}

let lastEmitted = JSON.stringify({
  ...clone(extraState.rest, {}),
  customFields: normalizeFields(props.modelValue?.customFields)
})

const emitUpdate = () => {
  const customFields = normalizeFields(localFields.value)
  const payload = {
    ...clone(extraState.rest, {}),
    customFields
  }
  const serialized = JSON.stringify(payload)
  if (serialized !== lastEmitted) {
    lastEmitted = serialized
    emit('update:modelValue', payload)
  }
}

watch(
  () => props.modelValue,
  (value) => {
    localFields.value = hydrateFields(value)
    extraState.rest = clone(extractRest(value), {})
    lastEmitted = JSON.stringify({
      ...clone(extraState.rest, {}),
      customFields: normalizeFields(value?.customFields)
    })
  },
  { deep: true }
)

watch(localFields, emitUpdate, { deep: true })

const addField = () => {
  localFields.value = [...localFields.value, toEditorField()]
}

const removeField = (index) => {
  localFields.value = localFields.value.filter((_, i) => i !== index)
}
</script>
