<script setup lang="ts">
import { computed, onUnmounted, reactive, ref, watch } from 'vue'
import { Handshake, Mic2, Send, X } from '@lucide/vue'

import { privacyContentToHtml } from '../../lib/privacyContent'
import { useAdminToast } from '../../composables/useAdminToast'
import { useAwardsStore } from '../../stores/awards'
import type { ShowactFormField } from '../../types/awards/showactForm'
import { DEFAULT_SHOWACT_SCHEMA } from '../../types/awards/showactForm'
import type { CreateShowactApplicationPayload } from '../../types/awards'
import HomeStarField from './HomeStarField.vue'

const props = defineProps<{ modalOpen?: boolean }>()
const emit = defineEmits<{ 'update:modalOpen': [boolean] }>()

const { showAdminToast } = useAdminToast()
const store = useAwardsStore()
const submitting = ref(false)
const localModalOpen = ref(false)
const showactInfoModalOpen = ref(false)

const fieldValues = reactive<Record<string, string>>({})
const fieldErrors = reactive<Record<string, string>>({})

const featureFlags = computed(() => store.overview.featureFlags)
const sponsors = computed(() =>
  featureFlags.value.sponsorsVisible ? store.publicSponsors.items.filter((item) => item.isVisible) : [],
)
const showactFooterLink = computed(() =>
  (store.overview.siteContent.footerLinks ?? []).find((link) => link.key === 'showacts') ?? null,
)
const showactInfoHtml = computed(() => privacyContentToHtml(showactFooterLink.value?.content || ''))
const showactHasInfo = computed(() =>
  Boolean(
    showactFooterLink.value?.content?.trim()
      || (showactFooterLink.value?.url && isSafePublicUrl(showactFooterLink.value.url))
      || featureFlags.value.showactApplicationDisabledMessage?.trim()
      || featureFlags.value.showactApplicationStartsAt
      || featureFlags.value.showactApplicationEndsAt,
  ),
)
const showactVisible = computed(() => featureFlags.value.showactApplicationsEnabled || showactHasInfo.value)
const showSection = computed(() => sponsors.value.length > 0 || showactVisible.value)
const showactDeadlineText = computed(() => {
  const deadline = featureFlags.value.showactApplicationEndsAt
  if (!deadline) return ''

  const parsed = new Date(`${deadline}T00:00:00`)
  if (Number.isNaN(parsed.getTime())) {
    return `Bewerbung bis ${deadline}`
  }

  return `Bewerbung bis ${parsed.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' })}`
})
const showactStatusText = computed(() => {
  if (featureFlags.value.showactApplicationsEnabled) {
    return 'Bewerbungen sind aktuell offen.'
  }

  return featureFlags.value.showactApplicationDisabledMessage?.trim()
    || 'Showact-Bewerbungen sind aktuell geschlossen.'
})
const showactPrimaryLabel = computed(() =>
  featureFlags.value.showactApplicationsEnabled ? 'Jetzt bewerben' : 'Mehr erfahren',
)
const showactPrimaryHref = computed(() =>
  !featureFlags.value.showactApplicationsEnabled && isSafePublicUrl(showactFooterLink.value?.url)
    ? showactFooterLink.value?.url ?? ''
    : '',
)
const showactPrimaryDisabled = computed(() =>
  !featureFlags.value.showactApplicationsEnabled
  && !showactInfoHtml.value
  && !showactPrimaryHref.value,
)
const showactPrimaryButtonStyle = computed(() =>
  showactPrimaryDisabled.value
    ? "display:inline-flex;align-items:center;gap:9px;height:44px;padding:0 20px;border-radius:14px;background:#c9b8da;border:none;color:#fff;font-family:'Outfit',sans-serif;font-weight:700;font-size:14px;cursor:not-allowed;box-shadow:none;transition:transform .15s,box-shadow .15s;flex-shrink:0;opacity:.86;"
    : "display:inline-flex;align-items:center;gap:9px;height:44px;padding:0 20px;border-radius:14px;background:#8b6cdb;border:none;color:#fff;font-family:'Outfit',sans-serif;font-weight:700;font-size:14px;cursor:pointer;box-shadow:0 4px 14px rgba(124,86,196,.25);transition:transform .15s,box-shadow .15s;flex-shrink:0;",
)

const showactSchema = computed((): ShowactFormField[] => {
  const json = featureFlags.value.showactFormSchemaJson ?? '[]'
  try {
    const parsed = JSON.parse(json)
    if (Array.isArray(parsed) && parsed.length > 0) return parsed as ShowactFormField[]
  } catch {
    // ignore
  }
  return DEFAULT_SHOWACT_SCHEMA
})

function resetForm() {
  for (const key of Object.keys(fieldValues)) {
    delete fieldValues[key]
  }
  for (const key of Object.keys(fieldErrors)) {
    delete fieldErrors[key]
  }
}

function closeModal() {
  localModalOpen.value = false
  emit('update:modalOpen', false)
}

function openShowactPrimaryAction() {
  if (featureFlags.value.showactApplicationsEnabled) {
    localModalOpen.value = true
    return
  }

  if (showactInfoHtml.value) {
    showactInfoModalOpen.value = true
    return
  }

  const fallbackUrl = showactPrimaryHref.value
  if (fallbackUrl && typeof window !== 'undefined') {
    window.open(fallbackUrl, '_blank', 'noopener,noreferrer')
  }
}

function closeShowactInfoModal() {
  showactInfoModalOpen.value = false
  emit('update:modalOpen', false)
}

function getChoiceValues(fieldId: string): string[] {
  const raw = fieldValues[fieldId] ?? ''
  return raw ? raw.split(',').map((v) => v.trim()).filter(Boolean) : []
}

function getMultiselectValues(fieldId: string): string[] {
  return getChoiceValues(fieldId)
}

function getCheckboxValues(fieldId: string): string[] {
  return getChoiceValues(fieldId)
}

function otherFieldId(fieldId: string) {
  return `${fieldId}__other`
}

function getOtherValue(fieldId: string) {
  return (fieldValues[otherFieldId(fieldId)] ?? '').trim()
}

function setChoiceValues(fieldId: string, values: string[]) {
  fieldValues[fieldId] = values.join(', ')
  delete fieldErrors[fieldId]
}

function setMultiselectValue(fieldId: string, option: string, checked: boolean) {
  const current = getMultiselectValues(fieldId)
  if (checked) {
    if (!current.includes(option)) current.push(option)
  } else {
    const idx = current.indexOf(option)
    if (idx !== -1) current.splice(idx, 1)
  }
  setChoiceValues(fieldId, current)
}

function setCheckboxOptionValue(field: ShowactFormField, option: string, checked: boolean) {
  const current = getCheckboxValues(field.id)
  if (checked) {
    if (!current.includes(option)) current.push(option)
  } else {
    const next = current.filter((value) => value !== option)
    setChoiceValues(field.id, next)
    return
  }

  setChoiceValues(field.id, current)
}

function updateOtherValue(field: ShowactFormField, value: string) {
  fieldValues[otherFieldId(field.id)] = value
  delete fieldErrors[field.id]
}

function validateField(field: ShowactFormField): string {
  const value = (fieldValues[field.id] ?? '').trim()
  const otherValue = field.allowOther ? getOtherValue(field.id) : ''

  if (field.required && !value && !otherValue) {
    if (field.type === 'checkbox') {
      return `Bitte waehle bei „${field.label}" mindestens eine Checkbox aus.`
    }

    if (field.type === 'radio' || field.type === 'select' || field.type === 'multiselect') {
      return `Bitte waehle bei „${field.label}" eine Antwort aus.`
    }

    return `Bitte fuell das Feld „${field.label}" aus.`
  }

  if (!value) {
    return ''
  }

  if (field.type === 'email') {
    const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
    if (!emailPattern.test(value)) {
      return `Bitte gib bei „${field.label}" eine gueltige E-Mail-Adresse ein.`
    }
  }

  if (field.type === 'url') {
    try {
      const url = new URL(value)
      if (!['http:', 'https:'].includes(url.protocol)) {
        return `Bitte gib bei „${field.label}" einen gueltigen Link mit http oder https ein.`
      }
    } catch {
      return `Bitte gib bei „${field.label}" einen gueltigen Link ein.`
    }
  }

  return ''
}

function updateFieldError(field: ShowactFormField) {
  const message = validateField(field)
  if (message) {
    fieldErrors[field.id] = message
    return
  }

  delete fieldErrors[field.id]
}

function resolveFieldValue(field?: ShowactFormField | null, source: Record<string, string> = fieldValues) {
  if (!field) {
    return ''
  }

  return (source[field.id] ?? '').trim()
}

function findFieldByMatcher(matcher: (field: ShowactFormField) => boolean) {
  return showactSchema.value.find(matcher) ?? null
}

function fieldHaystack(field: ShowactFormField) {
  return `${field.id} ${field.label}`.toLowerCase()
}

function fieldMatches(field: ShowactFormField, needles: string[]) {
  const haystack = fieldHaystack(field)
  return needles.some((needle) => haystack.includes(needle))
}

function findFieldByIdOrLabel(ids: string[], labels: string[], type?: ShowactFormField['type']) {
  return findFieldByMatcher((field) => {
    if (type && field.type !== type) return false
    const id = field.id.toLowerCase()
    const label = field.label.toLowerCase()
    return ids.some((needle) => id.includes(needle)) || labels.some((needle) => label.includes(needle))
  })
}

function buildShowactPayload(fieldResponsesJson: string, responses: Record<string, string>): CreateShowactApplicationPayload {
  const artistField = findFieldByMatcher((field) => field.isArtistName)
  const emailField = findFieldByMatcher((field) => field.type === 'email')
  const discordField = findFieldByMatcher((field) => fieldMatches(field, ['discord']))
  const platformField = findFieldByMatcher((field) => {
    if (field.type !== 'url') return false
    return fieldMatches(field, ['platform', 'kanal', 'profil', 'channel'])
  })
  const referenceField = findFieldByMatcher((field) => {
    if (field.type !== 'url') return false
    return fieldMatches(field, ['referenz', 'reference'])
  })
  const performanceField = findFieldByIdOrLabel(
    ['performance_type', 'showact_type', 'show_type', 'showact_roles', 'roles'],
    ['showact-art', 'showact art', 'art des showacts', 'performance', 'wofür möchtest', 'wofuer moechtest', 'bewerben'],
  )
  const descriptionField = findFieldByIdOrLabel(
    ['description', 'beschreibung', 'show_description'],
    ['beschreibung', 'idee', 'was moechtest', 'was möchtest', 'zeigen'],
    'textarea',
  )
  const technicalNotesField = findFieldByIdOrLabel(
    ['technical_notes', 'technik', 'technical', 'setup', 'timing'],
    ['technik', 'technical', 'setup', 'timing'],
  )

  const textareaSummary = showactSchema.value
    .filter((field) => field.type === 'textarea')
    .map((field) => resolveFieldValue(field, responses))
    .filter(Boolean)
    .join('\n\n')
  const description = resolveFieldValue(descriptionField, responses) || textareaSummary || 'Strukturierte Showact-Bewerbung'

  return {
    artistName: resolveFieldValue(artistField, responses),
    contactEmail: resolveFieldValue(emailField, responses),
    contactDiscord: resolveFieldValue(discordField, responses),
    platformUrl: resolveFieldValue(platformField, responses),
    performanceType: resolveFieldValue(performanceField, responses),
    description,
    technicalNotes: resolveFieldValue(technicalNotesField, responses),
    referenceUrl: resolveFieldValue(referenceField, responses),
    fieldResponsesJson,
  }
}

async function submitShowact() {
  for (const field of showactSchema.value) {
    const message = validateField(field)
    if (message) {
      fieldErrors[field.id] = message
      showAdminToast(message, 'error')
      return
    }
  }
  const responses = { ...fieldValues }
  for (const field of showactSchema.value) {
    if (!field.allowOther) {
      continue
    }

    const otherValue = getOtherValue(field.id)
    delete responses[otherFieldId(field.id)]
    if (otherValue) {
      const current = getMultiselectValues(field.id)
      responses[field.id] = [...current, `Andere: ${otherValue}`].join(', ')
    }
  }
  const fieldResponsesJson = JSON.stringify(responses)
  submitting.value = true
  try {
    await store.submitShowactApplication(buildShowactPayload(fieldResponsesJson, responses))
    showAdminToast('Bewerbung ist angekommen. Das Team meldet sich, wenn es passt.', 'success')
    resetForm()
    closeModal()
  } catch (error) {
    showAdminToast(error instanceof Error ? error.message : 'Bewerbung konnte nicht gesendet werden.', 'error')
  } finally {
    submitting.value = false
  }
}

const inputStyle = 'padding:13px 16px;border-radius:12px;border:1.5px solid #e6dcf6;background:#fbf9ff;font-family:\'Outfit\',sans-serif;font-size:15px;color:#3f3556;outline:none;transition:border-color .15s;'
const labelStyle = 'font-family:\'Outfit\',sans-serif;font-size:13px;font-weight:600;color:#5f44ad;'
const errorStyle = 'font-family:\'Outfit\',sans-serif;font-size:12px;font-weight:600;color:#d14b72;line-height:1.45;'

function onFocus(event: FocusEvent) {
  ;(event.target as HTMLElement).style.borderColor = '#8b6cdb'
}
function onBlur(event: FocusEvent) {
  ;(event.target as HTMLElement).style.borderColor = '#e6dcf6'
}

function handleFieldBlur(field: ShowactFormField, event: FocusEvent) {
  onBlur(event)
  updateFieldError(field)
}

function resolveTextInputType(field: ShowactFormField) {
  if (field.type === 'email' || field.type === 'url') {
    return 'text'
  }

  return 'text'
}

function resolveInputMode(field: ShowactFormField) {
  if (field.type === 'email') return 'email'
  if (field.type === 'url') return 'url'
  return 'text'
}

function resolveAutoComplete(field: ShowactFormField) {
  if (field.type === 'email') return 'email'
  if (field.type === 'url') return 'url'
  return 'off'
}

function isSafePublicUrl(value: string | null | undefined) {
  if (!value) return false

  try {
    const url = new URL(value)
    return url.protocol === 'http:' || url.protocol === 'https:'
  } catch {
    return false
  }
}

watch(
  () => props.modalOpen,
  (next) => {
    if (!next) {
      localModalOpen.value = false
      showactInfoModalOpen.value = false
      return
    }

    if (featureFlags.value.showactApplicationsEnabled) {
      localModalOpen.value = true
      showactInfoModalOpen.value = false
      return
    }

    localModalOpen.value = false
    showactInfoModalOpen.value = true
  },
  { immediate: true },
)

watch([localModalOpen, showactInfoModalOpen], ([form, info]) => {
  document.body.style.overflow = form || info ? 'hidden' : ''
})

onUnmounted(() => {
  document.body.style.overflow = ''
})
</script>

<template>
  <section v-if="showSection" class="mx-auto w-full max-w-[1200px] space-y-5 px-6 pb-6 -mt-10">
    <!-- Sponsor-Kacheln -->
    <div v-if="sponsors.length > 0" class="rounded-[24px] border border-white/70 bg-white/78 p-5 shadow-[0_18px_46px_rgba(105,78,160,0.13)] backdrop-blur">
      <div class="flex items-center gap-3">
        <span class="grid h-11 w-11 place-items-center rounded-2xl bg-sky-100 text-sky-700">
          <Handshake class="h-5 w-5" />
        </span>
        <div>
          <p class="text-xs font-bold uppercase tracking-[0.2em] text-sky-600">Partner</p>
          <h2 class="text-xl font-black text-[#3f3556]">Sponsoren</h2>
        </div>
      </div>
      <div class="mt-5 grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
        <a
          v-for="sponsor in sponsors"
          :key="sponsor.id"
          :href="sponsor.websiteUrl || undefined"
          :target="sponsor.websiteUrl ? '_blank' : undefined"
          rel="noreferrer"
          class="group min-h-[136px] rounded-[20px] border border-violet-100 bg-white p-4 transition hover:-translate-y-0.5 hover:border-violet-200 hover:shadow-[0_18px_36px_rgba(105,78,160,0.12)]"
        >
          <div class="flex items-start gap-3">
            <div class="grid h-12 w-12 shrink-0 place-items-center overflow-hidden rounded-2xl border border-violet-100 bg-violet-50 text-sm font-black text-violet-700">
              <img v-if="sponsor.logoUrl" :src="sponsor.logoUrl" :alt="sponsor.name" class="h-full w-full object-contain p-1" loading="lazy" />
              <span v-else>{{ sponsor.name.slice(0, 2).toUpperCase() }}</span>
            </div>
            <div class="min-w-0">
              <p class="truncate text-sm font-black text-[#3f3556]">{{ sponsor.name }}</p>
              <p class="mt-1 text-xs font-bold uppercase tracking-[0.14em] text-sky-600">{{ sponsor.tier }}</p>
            </div>
          </div>
          <p v-if="sponsor.description" class="mt-3 line-clamp-3 text-sm leading-6 text-[#746b86]">{{ sponsor.description }}</p>
        </a>
      </div>
    </div>

    <!-- Showact-Banner -->
    <div
      v-if="showactVisible"
      class="flex flex-wrap items-center gap-5 rounded-[24px] border border-white/70 bg-white/78 px-6 py-5 backdrop-blur sm:flex-nowrap"
    >
      <span class="grid h-12 w-12 shrink-0 place-items-center rounded-2xl bg-violet-100 text-violet-700">
        <Mic2 class="h-6 w-6" />
      </span>
      <div class="min-w-0 flex-1">
        <p class="text-xs font-bold uppercase tracking-[0.2em] text-violet-500">Showacts</p>
        <h2 class="mt-0.5 text-xl font-black text-[#3f3556]">Als Showact auftreten</h2>
        <p class="mt-1 text-sm leading-6 text-[#746b86]">
          <template v-if="featureFlags.showactApplicationsEnabled">
            Hast du eine Idee für einen Beitrag? Bewirb dich jetzt und zeig der Community, was du kannst.
          </template>
          <template v-else>
            Showacts bleiben ein Teil der Award-Show. Aktuell ist das Bewerbungsfenster geschlossen, aber alle Infos bleiben hier erreichbar.
          </template>
          <span v-if="showactDeadlineText" class="font-semibold text-violet-700">{{ showactDeadlineText }}</span>
          <span v-else class="font-semibold text-violet-700">{{ showactStatusText }}</span>
        </p>
      </div>
      <a
        v-if="showactPrimaryHref"
        :href="showactPrimaryHref"
        target="_blank"
        rel="noopener noreferrer"
        referrerpolicy="no-referrer"
        style="display:inline-flex;align-items:center;gap:9px;height:44px;padding:0 20px;border-radius:14px;background:#8b6cdb;border:none;color:#fff;font-family:'Outfit',sans-serif;font-weight:700;font-size:14px;cursor:pointer;box-shadow:0 4px 14px rgba(124,86,196,.25);transition:transform .15s,box-shadow .15s;flex-shrink:0;text-decoration:none;"
      >
        <Send class="h-4 w-4" />
        {{ showactPrimaryLabel }}
      </a>
      <button
        v-else
        type="button"
        :disabled="showactPrimaryDisabled"
        :style="showactPrimaryButtonStyle"
        @click="openShowactPrimaryAction"
      >
        <Send class="h-4 w-4" />
        {{ showactPrimaryLabel }}
      </button>
    </div>
  </section>

  <!-- Bewerbungs-Modal im Landing-Page-Stil -->
  <Teleport to="body">
    <div
      v-if="localModalOpen"
      style="position:fixed;inset:0;z-index:200;display:flex;align-items:center;justify-content:center;padding:24px;background:rgba(40,24,70,.5);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);"
      @click.self="closeModal"
    >
      <div
        style="position:relative;width:100%;max-width:720px;max-height:88vh;overflow:hidden;display:flex;flex-direction:column;background:#fff;border-radius:24px;box-shadow:0 40px 90px rgba(40,24,70,.4);"
        @click.stop
      >
        <!-- Schliessen-Button -->
        <button
          aria-label="Schliessen"
          style="position:absolute;top:18px;right:18px;z-index:5;display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:50%;border:none;background:rgba(255,255,255,.14);color:rgba(255,255,255,.8);font-size:18px;cursor:pointer;"
          @click="closeModal"
        >
          <X :size="18" />
        </button>

        <!-- Header mit Sternanimation -->
        <div style="position:relative;overflow:hidden;padding:30px 36px 26px;border-bottom:1px solid rgba(255,255,255,.12);background:linear-gradient(135deg,#2a1842,#3a2168);flex:none;">
          <HomeStarField :count="13" variant="header" />
          <div style="position:relative;z-index:1;">
            <div style="display:inline-flex;align-items:center;gap:7px;padding:6px 14px;border-radius:999px;background:rgba(201,177,255,.12);border:1px solid rgba(201,177,255,.34);color:#c9b1ff;font-size:11px;font-weight:700;letter-spacing:2px;text-transform:uppercase;margin-bottom:12px;">✦ Showacts</div>
            <h3 style="font-family:'Fredoka',sans-serif;font-weight:700;font-size:clamp(26px,3vw,34px);line-height:1.1;margin:0 0 8px;color:#fff6fb;">Showact-Bewerbung</h3>
            <p style="font-size:15px;line-height:1.55;color:#d8c9eb;margin:0;">Fuell das Formular aus und schick deine Bewerbung ab.</p>
          </div>
        </div>

        <!-- Dynamisches Formular -->
        <div style="overflow-y:auto;padding:28px 36px 32px;flex:1;">
          <form novalidate @submit.prevent="submitShowact">
            <template v-for="field in showactSchema" :key="field.id">
              <!-- text / email / url -->
              <label v-if="field.type === 'text' || field.type === 'email' || field.type === 'url'" style="display:flex;flex-direction:column;gap:6px;margin-bottom:14px;">
                <span :style="labelStyle">{{ field.label }}{{ field.required ? ' *' : '' }}</span>
                <span v-if="field.helpText" style="font-family:'Outfit',sans-serif;font-size:12px;line-height:1.45;color:#8a819d;">{{ field.helpText }}</span>
                <input
                  v-model="fieldValues[field.id]"
                  :type="resolveTextInputType(field)"
                  :inputmode="resolveInputMode(field)"
                  :autocomplete="resolveAutoComplete(field)"
                  :maxlength="field.maxLength"
                  :placeholder="field.placeholder"
                  :aria-invalid="fieldErrors[field.id] ? 'true' : 'false'"
                  :style="inputStyle + (fieldErrors[field.id] ? 'border-color:#d14b72;background:#fff7fa;' : '')"
                  @focus="onFocus"
                  @blur="handleFieldBlur(field, $event)"
                  @input="delete fieldErrors[field.id]"
                />
                <span v-if="fieldErrors[field.id]" :style="errorStyle">{{ fieldErrors[field.id] }}</span>
              </label>

              <!-- textarea -->
              <label v-else-if="field.type === 'textarea'" style="display:flex;flex-direction:column;gap:6px;margin-bottom:14px;">
                <span :style="labelStyle">{{ field.label }}{{ field.required ? ' *' : '' }}</span>
                <span v-if="field.helpText" style="font-family:'Outfit',sans-serif;font-size:12px;line-height:1.45;color:#8a819d;">{{ field.helpText }}</span>
                <textarea
                  v-model="fieldValues[field.id]"
                  rows="4"
                  :maxlength="field.maxLength"
                  :placeholder="field.placeholder"
                  :aria-invalid="fieldErrors[field.id] ? 'true' : 'false'"
                  :style="inputStyle + 'resize:vertical;line-height:1.55;' + (fieldErrors[field.id] ? 'border-color:#d14b72;background:#fff7fa;' : '')"
                  @focus="onFocus"
                  @blur="handleFieldBlur(field, $event)"
                  @input="delete fieldErrors[field.id]"
                />
                <span v-if="fieldErrors[field.id]" :style="errorStyle">{{ fieldErrors[field.id] }}</span>
              </label>

              <!-- select -->
              <label v-else-if="field.type === 'select'" style="display:flex;flex-direction:column;gap:6px;margin-bottom:14px;">
                <span :style="labelStyle">{{ field.label }}{{ field.required ? ' *' : '' }}</span>
                <span v-if="field.helpText" style="font-family:'Outfit',sans-serif;font-size:12px;line-height:1.45;color:#8a819d;">{{ field.helpText }}</span>
                <select
                  v-model="fieldValues[field.id]"
                  :aria-invalid="fieldErrors[field.id] ? 'true' : 'false'"
                  :style="inputStyle + (fieldErrors[field.id] ? 'border-color:#d14b72;background:#fff7fa;' : '')"
                  @focus="onFocus"
                  @blur="handleFieldBlur(field, $event)"
                  @change="delete fieldErrors[field.id]"
                >
                  <option value="">{{ field.placeholder || '— Bitte wählen —' }}</option>
                  <option v-for="opt in field.options" :key="opt" :value="opt">{{ opt }}</option>
                </select>
                <span v-if="fieldErrors[field.id]" :style="errorStyle">{{ fieldErrors[field.id] }}</span>
              </label>

              <!-- radio -->
              <div v-else-if="field.type === 'radio'" style="display:flex;flex-direction:column;gap:6px;margin-bottom:14px;">
                <span :style="labelStyle">{{ field.label }}{{ field.required ? ' *' : '' }}</span>
                <span v-if="field.helpText" style="font-family:'Outfit',sans-serif;font-size:12px;line-height:1.45;color:#8a819d;">{{ field.helpText }}</span>
                <div :style="'display:flex;flex-direction:column;gap:8px;padding:10px 14px;border-radius:12px;border:1.5px solid #e6dcf6;background:#fbf9ff;' + (fieldErrors[field.id] ? 'border-color:#d14b72;background:#fff7fa;' : '')">
                  <label
                    v-for="opt in field.options"
                    :key="opt"
                    style="display:flex;align-items:center;gap:9px;font-family:'Outfit',sans-serif;font-size:14px;color:#3f3556;cursor:pointer;"
                  >
                    <input
                      v-model="fieldValues[field.id]"
                      type="radio"
                      :name="field.id"
                      :value="opt"
                      style="width:17px;height:17px;accent-color:#7c56c4;"
                      @change="delete fieldErrors[field.id]"
                    />
                    {{ opt }}
                  </label>
                </div>
                <span v-if="fieldErrors[field.id]" :style="errorStyle">{{ fieldErrors[field.id] }}</span>
              </div>

              <!-- multiselect (checkboxes) -->
              <div v-else-if="field.type === 'multiselect'" style="display:flex;flex-direction:column;gap:6px;margin-bottom:14px;">
                <span :style="labelStyle">{{ field.label }}{{ field.required ? ' *' : '' }}</span>
                <span v-if="field.helpText" style="font-family:'Outfit',sans-serif;font-size:12px;line-height:1.45;color:#8a819d;">{{ field.helpText }}</span>
                <div
                  class="home-showact-choice-group"
                  :class="{ 'home-showact-choice-group--invalid': Boolean(fieldErrors[field.id]) }"
                >
                  <label
                    v-for="opt in field.options"
                    :key="opt"
                    class="home-showact-choice-option"
                  >
                    <input
                      type="checkbox"
                      :checked="getMultiselectValues(field.id).includes(opt)"
                      class="home-showact-choice-input"
                      @change="setMultiselectValue(field.id, opt, ($event.target as HTMLInputElement).checked); updateFieldError(field)"
                    />
                    <span>{{ opt }}</span>
                  </label>
                  <label
                    v-if="field.allowOther"
                    class="home-showact-choice-option home-showact-choice-option--other"
                  >
                    <span class="home-showact-choice-faux-input" aria-hidden="true"></span>
                    <span>Andere:</span>
                    <input
                      :value="getOtherValue(field.id)"
                      type="text"
                      placeholder="Eigene Antwort"
                      class="home-showact-choice-other-input"
                      @input="updateOtherValue(field, ($event.target as HTMLInputElement).value)"
                    />
                  </label>
                  <span v-if="field.options.length === 0" class="home-showact-choice-empty">Keine Optionen konfiguriert.</span>
                </div>
                <span v-if="fieldErrors[field.id]" :style="errorStyle">{{ fieldErrors[field.id] }}</span>
              </div>

              <!-- checkbox group -->
              <div v-else-if="field.type === 'checkbox'" style="display:flex;flex-direction:column;gap:6px;margin-bottom:14px;">
                <span :style="labelStyle">{{ field.label }}{{ field.required ? ' *' : '' }}</span>
                <span v-if="field.helpText" style="font-family:'Outfit',sans-serif;font-size:12px;line-height:1.45;color:#8a819d;">{{ field.helpText }}</span>
                <div
                  class="home-showact-choice-group"
                  :class="{ 'home-showact-choice-group--invalid': Boolean(fieldErrors[field.id]) }"
                >
                  <label
                    v-for="opt in field.options"
                    :key="opt"
                    class="home-showact-choice-option"
                  >
                    <input
                      type="checkbox"
                      :checked="getCheckboxValues(field.id).includes(opt)"
                      class="home-showact-choice-input"
                      @change="setCheckboxOptionValue(field, opt, ($event.target as HTMLInputElement).checked); updateFieldError(field)"
                    />
                    <span>{{ opt }}</span>
                  </label>
                  <span v-if="field.options.length === 0" class="home-showact-choice-empty">Keine Checkboxen konfiguriert.</span>
                </div>
                <span v-if="fieldErrors[field.id]" :style="errorStyle">{{ fieldErrors[field.id] }}</span>
              </div>
            </template>

            <div style="display:flex;justify-content:flex-end;margin-top:6px;">
              <button
                type="submit"
                :disabled="submitting"
                style="display:inline-flex;align-items:center;gap:8px;padding:14px 28px;border-radius:13px;border:none;background:linear-gradient(135deg,#8b6cdb,#7355c8);color:#fff;font-family:'Outfit',sans-serif;font-weight:600;font-size:15px;cursor:pointer;box-shadow:0 10px 24px rgba(124,86,196,.3);transition:transform .15s,opacity .15s;"
                @mouseover="($event.currentTarget as HTMLButtonElement).style.transform='translateY(-2px)'"
                @mouseleave="($event.currentTarget as HTMLButtonElement).style.transform='translateY(0)'"
              >
                <Send :size="16" />
                {{ submitting ? 'Sendet ...' : 'Bewerbung senden' }}
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>
  </Teleport>

  <Teleport to="body">
    <div
      v-if="showactInfoModalOpen"
      style="position:fixed;inset:0;z-index:205;display:flex;align-items:center;justify-content:center;padding:24px;background:rgba(40,24,70,.5);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);"
      @click.self="closeShowactInfoModal"
    >
      <div
        style="position:relative;width:100%;max-width:720px;max-height:88vh;overflow:hidden;display:flex;flex-direction:column;background:#fff;border-radius:24px;box-shadow:0 40px 90px rgba(40,24,70,.4);"
        @click.stop
      >
        <button
          aria-label="Schliessen"
          style="position:absolute;top:18px;right:18px;z-index:5;display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:50%;border:none;background:#f1ecfb;color:#8b6cdb;font-size:18px;cursor:pointer;"
          @click="closeShowactInfoModal"
        >
          <X :size="18" />
        </button>
        <div style="padding:30px 36px 20px;border-bottom:1px solid #f1ecfb;background:linear-gradient(135deg,#2a1842,#3a2168);">
          <p style="margin:0 0 8px;font-size:11px;font-weight:700;letter-spacing:2px;text-transform:uppercase;color:#c9b1ff;">Showacts</p>
          <h3 style="margin:0;font-family:'Fredoka',sans-serif;font-weight:700;font-size:30px;line-height:1.1;color:#fff6fb;">Infos zur Award-Show</h3>
        </div>
        <div style="overflow-y:auto;padding:28px 36px 32px;flex:1;font-family:'Outfit',sans-serif;font-size:14px;line-height:1.7;color:#6f6685;">
          <div v-if="showactInfoHtml" class="home-showact-info-content" v-html="showactInfoHtml" />
          <p v-else style="margin:0;padding:14px 16px;border-radius:16px;border:1px solid #fde68a;background:#fffbeb;color:#92400e;font-weight:600;">
            Für Showacts ist aktuell noch kein Landingpage-Inhalt hinterlegt.
          </p>
        </div>
      </div>
    </div>
  </Teleport>
</template>

<style scoped>
.home-showact-info-content :deep(p) {
  margin: 0 0 14px;
}

.home-showact-info-content :deep(p:last-child),
.home-showact-info-content :deep(ul:last-child),
.home-showact-info-content :deep(ol:last-child) {
  margin-bottom: 0;
}

.home-showact-info-content :deep(ul),
.home-showact-info-content :deep(ol) {
  margin: 0 0 14px 20px;
  padding-left: 16px;
}

.home-showact-info-content :deep(li) {
  margin: 3px 0;
}

.home-showact-choice-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 14px;
  border: 1.5px solid #e6dcf6;
  border-radius: 14px;
  background: #fbf9ff;
  transition: border-color .15s ease, background .15s ease;
}

.home-showact-choice-group--invalid {
  border-color: #d14b72;
  background: #fff7fa;
}

.home-showact-choice-option {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 12px;
  border: 1px solid rgba(139, 108, 219, 0.12);
  background: rgba(255, 255, 255, 0.86);
  color: #3f3556;
  font-family: 'Outfit', sans-serif;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.5;
  cursor: pointer;
}

.home-showact-choice-option--other {
  align-items: center;
}

.home-showact-choice-input {
  width: 16px;
  height: 16px;
  margin-top: 2px;
  accent-color: #7c56c4;
  flex: none;
}

.home-showact-choice-faux-input {
  width: 16px;
  height: 16px;
  margin-top: 1px;
  border-radius: 4px;
  border: 1.5px solid #d8c9eb;
  background: #fff;
  flex: none;
}

.home-showact-choice-other-input {
  min-width: 0;
  flex: 1;
  border: 0;
  border-bottom: 1.5px solid #d8c9eb;
  background: transparent;
  padding: 4px 2px;
  color: #3f3556;
  font-family: 'Outfit', sans-serif;
  font-size: 14px;
  outline: none;
}

.home-showact-choice-empty {
  color: #9ca3af;
  font-size: 13px;
  font-weight: 600;
}

@media (max-width: 560px) {
  .home-showact-grid {
    grid-template-columns: 1fr !important;
  }

  .home-showact-choice-option--other {
    align-items: flex-start;
    flex-direction: column;
  }
}
</style>
