<script setup lang="ts">
import { computed, ref, watch } from 'vue'

import HomeCategoryProgressRail from './HomeCategoryProgressRail.vue'
import HomeNominationReviewPane from './HomeNominationReviewPane.vue'
import HomeNominationWizardPane from './HomeNominationWizardPane.vue'
import HomeSelectDropdown from './HomeSelectDropdown.vue'
import HomeStarField from './HomeStarField.vue'
import HomeVotingPickerPane from './HomeVotingPickerPane.vue'
import HomeWizardFooter from './HomeWizardFooter.vue'
import type { HomeCategoryListItem, HomeNomineeListItem, HomeSelectionOption } from './homeModalTypes'
import type { HomeNominationSubmitContext } from './homeLandingTypes'

const props = defineProps<{
  modalOpen: boolean
  submitted: boolean
  notSubmitted: boolean
  formError: string
  successTitle: string
  successText: string
  closeModal: () => void
  stop: (event: Event) => void
  isShow: boolean
  isPicker: boolean
  isVote: boolean
  isClip: boolean
  nominationPhase: boolean
  publicStreamUrl: string
  formatShowDate: () => string
  submitReminder: () => void
  pickerTitle: string
  pickerSubtitle: string
  catList: HomeCategoryListItem[]
  activeCatName: string
  noms: HomeNomineeListItem[]
  voteCount: number
  totalCats: number
  canSubmitVote: boolean
  savedVoteActive: boolean
  activeCatIndex: number
  submitVote: () => Promise<void> | void
  submitNomination: (context: HomeNominationSubmitContext) => Promise<void> | void
  submitting: boolean
  onClipCatChange: (event: Event) => void
  catOptions: HomeSelectionOption[]
  clipNomOptions: HomeSelectionOption[]
  clipDsgvo: boolean
  clipDsgvoChange: () => void
  onOpenPrivacy: () => void
  canSubmitClip: boolean
  clipSubmitStyle: string
  submitClip: () => Promise<void> | void
}>()

const nominationCatValue = ref(0)
const clipCatValue = ref(0)
const clipNomQuery = ref('')
const nominationDrafts = ref<Record<number, string[]>>({})
const nominationReviewMode = ref(false)

watch(
  () => props.catOptions,
  (options) => {
    syncNominationDrafts(options)
    nominationCatValue.value = resolveOptionValue(nominationCatValue.value, options)
    const nextClipCat = resolveOptionValue(clipCatValue.value, options)
    if (nextClipCat !== clipCatValue.value) {
      clipCatValue.value = nextClipCat
      notifyClipCategoryChange(nextClipCat)
    }
  },
  { immediate: true },
)

watch(
  () => props.modalOpen,
  (isOpen) => {
    if (!isOpen) {
      nominationReviewMode.value = false
      nominationCatValue.value = 0
    }
  },
)

function resolveOptionValue(value: number, options: HomeSelectionOption[]) {
  return options.some((option) => option.id === value) ? value : options[0]?.id ?? 0
}

function handleClipCategoryChange(value: number) {
  clipCatValue.value = value
  clipNomQuery.value = ''
  notifyClipCategoryChange(value)
}

function notifyClipCategoryChange(value: number) {
  props.onClipCatChange({ target: { value: String(value) } } as unknown as Event)
}

function syncNominationDrafts(options: HomeSelectionOption[]) {
  const nextDrafts: Record<number, string[]> = {}
  for (const option of options) {
    const existing = nominationDrafts.value[option.id] ?? []
    const limit = nominationLinkLimitFor(option.id)
    nextDrafts[option.id] = createNominationLinkSlots(existing, limit)
  }
  nominationDrafts.value = nextDrafts
}

function nominationLinksFor(categoryIndex: number) {
  return nominationDrafts.value[categoryIndex] ?? createNominationLinkSlots([], nominationLinkLimitFor(categoryIndex))
}

function compactNominationCategory(categoryIndex: number) {
  const limit = nominationLinkLimitFor(categoryIndex)
  const links = nominationLinksFor(categoryIndex)
  const compactedLinks = links.map((link) => link.trim()).filter(Boolean).slice(0, limit)
  nominationDrafts.value = {
    ...nominationDrafts.value,
    [categoryIndex]: createNominationLinkSlots(compactedLinks, limit),
  }
}

function onNominationLinkInput(index: number, value: string) {
  const links = [...nominationLinksFor(nominationCatValue.value)]
  links[index] = value
  nominationDrafts.value = {
    ...nominationDrafts.value,
    [nominationCatValue.value]: links,
  }
}

function nominationFieldErrors(categoryIndex: number) {
  const links = nominationLinksFor(categoryIndex)
  return links.map((link, index) => {
    const value = link.trim()
    if (!value) return ''
    if (!isHttpUrl(value)) return 'Bitte gib einen gueltigen http(s)-Link ein.'
    const normalized = normalizeUrlForCompare(value)
    const duplicateIndex = links.findIndex((candidate, candidateIndex) =>
      candidateIndex !== index && normalizeUrlForCompare(candidate) === normalized,
    )
    return duplicateIndex >= 0 ? 'Dieser Link ist in dieser Kategorie schon eingetragen.' : ''
  })
}

const activeNominationCategory = computed(() =>
  props.catOptions.find((option) => option.id === nominationCatValue.value) ?? props.catOptions[0] ?? null,
)
const activeNominationLinks = computed(() => nominationLinksFor(nominationCatValue.value))
const activeNominationErrors = computed(() => nominationFieldErrors(nominationCatValue.value))
const nominationReviewItems = computed(() =>
  props.catOptions
    .map((option) => ({
      categoryIndex: option.id,
      categoryName: option.name || stripCategoryIcon(option.label),
      links: nominationLinksFor(option.id).map((link) => link.trim()).filter(Boolean),
    }))
    .filter((item) => item.links.length > 0),
)
const nominationTotalLinks = computed(() =>
  nominationReviewItems.value.reduce((sum, item) => sum + item.links.length, 0),
)
const nominationHasErrors = computed(() =>
  props.catOptions.some((option) => nominationFieldErrors(option.id).some(Boolean)),
)
const nominationRailItems = computed(() => props.catOptions.map((option) => {
  const errors = nominationFieldErrors(option.id)
  const linkCount = nominationLinksFor(option.id).map((link) => link.trim()).filter(Boolean).length
  const isActive = option.id === nominationCatValue.value
  return {
    id: option.id,
    name: option.name || stripCategoryIcon(option.label),
    groupName: option.groupName,
    icon: option.icon || option.label.trim().split(' ')[0] || '✦',
    status: errors.some(Boolean) ? 'Fehler' : linkCount === 0 ? 'Leer' : `${linkCount} Link${linkCount === 1 ? '' : 's'}`,
    tone: errors.some(Boolean) ? 'error' as const : linkCount > 0 ? 'done' as const : isActive ? 'active' as const : 'empty' as const,
  }
}))
const nominationProgressText = computed(() =>
  `${nominationReviewItems.value.length} / ${props.catOptions.length} Kategorien ausgefüllt`,
)
const nominationHelperText = computed(() =>
  nominationTotalLinks.value > 0
    ? `${nominationTotalLinks.value} Link${nominationTotalLinks.value === 1 ? '' : 's'} bereit. Leere Kategorien werden übersprungen.`
    : 'Leere Kategorien kannst du einfach überspringen.',
)
const isLastNominationCategory = computed(() => {
  const activeIndex = props.catOptions.findIndex((option) => option.id === nominationCatValue.value)
  return activeIndex >= props.catOptions.length - 1
})

function selectNominationCategory(id: string | number) {
  compactNominationCategory(nominationCatValue.value)
  nominationCatValue.value = Number(id)
  nominationReviewMode.value = false
}

function goToPreviousNominationCategory() {
  const activeIndex = props.catOptions.findIndex((option) => option.id === nominationCatValue.value)
  const previous = props.catOptions[Math.max(0, activeIndex - 1)]
  if (previous) selectNominationCategory(previous.id)
}

function goToNextNominationCategory() {
  const activeIndex = props.catOptions.findIndex((option) => option.id === nominationCatValue.value)
  const next = props.catOptions[Math.min(props.catOptions.length - 1, activeIndex + 1)]
  if (next) selectNominationCategory(next.id)
}

function openNominationReview() {
  compactNominationCategory(nominationCatValue.value)
  nominationReviewMode.value = true
}

function closeNominationReview() {
  nominationReviewMode.value = false
}

function editNominationCategory(categoryIndex: number) {
  nominationCatValue.value = categoryIndex
  nominationReviewMode.value = false
}

async function submitNominationDrafts() {
  if (nominationHasErrors.value || nominationTotalLinks.value === 0 || props.submitting) return
  await props.submitNomination({
    entries: nominationReviewItems.value.map((item) => ({
      categoryIndex: item.categoryIndex,
      streamUrls: item.links,
    })),
  })
}

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

function normalizeUrlForCompare(value: string) {
  return value.trim().replace(/\/+$/, '').toLowerCase()
}

function nominationLinkLimitFor(categoryIndex: number) {
  const rawLimit = props.catOptions.find((option) => option.id === categoryIndex)?.maxNomineesPerUser
  const limit = typeof rawLimit === 'number' && Number.isFinite(rawLimit) ? rawLimit : 3
  return Math.max(1, Math.min(10, Math.round(limit)))
}

function createNominationLinkSlots(existing: string[], limit: number) {
  return Array.from({ length: limit }, (_, index) => existing[index] ?? '')
}

function stripCategoryIcon(value: string) {
  return value.replace(/^\S+\s+/, '')
}
</script>

<template>
  <template v-if="props.modalOpen">
    <div class="home-modal-overlay" @click="props.closeModal" 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);">
      <div class="home-modal" :class="{ 'home-modal--wide': props.isPicker, 'home-modal--voting': props.isPicker && props.notSubmitted }" @click="props.stop" style="position:relative;width:100%;max-width:680px;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);">
        <button @click="props.closeModal" 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(139,108,219,.12);color:#8b6cdb;font-size:20px;cursor:pointer;" style-hover="background:rgba(139,108,219,.2);">✕</button>

        <template v-if="props.submitted">
          <div class="home-modal__success" style="padding:56px 40px;text-align:center;">
            <div style="width:72px;height:72px;margin:0 auto 22px;border-radius:50%;background:linear-gradient(135deg,#2bbd6e,#1f9d5a);display:flex;align-items:center;justify-content:center;box-shadow:0 14px 32px rgba(31,157,90,.32);">
              <svg width="34" height="34" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6L9 17l-5-5"/></svg>
            </div>
            <h3 style="font-family:'Fredoka',sans-serif;font-weight:700;font-size:28px;line-height:1.14;margin:0 0 12px;color:#3f3556;">{{ props.successTitle }}</h3>
            <p style="font-size:16px;line-height:1.6;color:#7d7491;max-width:420px;margin:0 auto 28px;">{{ props.successText }}</p>
            <button @click="props.closeModal" style="padding:14px 32px;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);" style-hover="transform:translateY(-2px);">Schliessen</button>
          </div>
        </template>

        <template v-if="props.notSubmitted">
          <template v-if="props.isShow">
            <div class="home-modal__show" style="padding:38px 40px 40px;">
              <div style="display:inline-flex;align-items:center;gap:8px;padding:5px 14px;border-radius:999px;background:#f3eefb;color:#a98ddb;font-size:11px;font-weight:700;letter-spacing:1px;text-transform:uppercase;margin-bottom:18px;">Award-Show</div>
              <h3 style="font-family:'Fredoka',sans-serif;font-weight:700;font-size:28px;line-height:1.14;margin:0 0 10px;color:#3f3556;">Sei live dabei ✦</h3>
              <p style="font-size:15.5px;line-height:1.6;color:#7d7491;margin:0 0 24px;">Die große Live-Show findet am <strong style="color:#5f44ad;">{{ props.formatShowDate() }}</strong> statt. Aktiviere eine Erinnerung, damit du nichts verpasst.</p>
              <div class="home-modal__reminder-form" style="display:flex;gap:10px;margin-bottom:14px;">
                <input data-dc-ref="emailRef" type="email" placeholder="deine@email.de" style="flex:1;padding:14px 16px;border-radius:12px;border:1.5px solid #e6dcf6;background:#fbf9ff;font-family:'Outfit',sans-serif;font-size:15px;color:#3f3556;outline:none;" style-focus="border-color:#8b6cdb;" />
                <button @click="props.submitReminder" style="flex:none;padding:14px 24px;border-radius:12px;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 22px rgba(124,86,196,.3);" style-hover="transform:translateY(-2px);">Erinnern</button>
              </div>
              <a :href="props.publicStreamUrl" target="_blank" rel="noopener" style="display:flex;align-items:center;justify-content:center;gap:9px;padding:14px;border-radius:12px;background:#f1ecfb;color:#7a3fd0;text-decoration:none;font-family:'Outfit',sans-serif;font-weight:600;font-size:15px;" style-hover="background:#e8e0f9;"><svg width="17" height="17" viewBox="0 0 24 24" fill="#9146FF"><path d="M4 2L2.4 6v14.5h5V23h2.7l2.5-2.5h4L21.6 16V2H4zm15.3 13.1l-2.9 2.9h-4.4l-2.5 2.5v-2.5H6.7V3.7h12.6v11.4z"/><path d="M11.1 7.1h1.7v5h-1.7zM15.7 7.1h1.7v5h-1.7z"/></svg>Zum Award-Stream</a>
            </div>
          </template>

          <template v-if="props.isPicker">
            <template v-if="props.nominationPhase && !props.isVote">
              <div class="home-modal__nomination-submit home-wizard-shell">
                <div class="home-modal__picker-header" style="padding:30px 36px 22px;border-bottom:1px solid #f1ecfb;flex:none;">
                  <HomeStarField :count="13" variant="header" />
                  <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;">✦ Nominierungsphase</div>
                  <div class="home-wizard-header-row">
                    <div>
                      <h3 style="font-family:'Fredoka',sans-serif;font-weight:700;font-size:clamp(30px,3vw,36px);line-height:1.08;margin:0 0 14px;color:#3f3556;">Streamer nominieren</h3>
                      <p style="font-size:16px;line-height:1.5;color:#8a8398;margin:0;">Reiche pro Kategorie die erlaubte Anzahl an Stream- oder Kanal-Links ein.</p>
                    </div>
                  </div>
                </div>
                <div class="home-wizard-layout">
                  <HomeCategoryProgressRail
                    label="Kategorien"
                    :items="nominationRailItems"
                    :active-id="nominationCatValue"
                    :on-select="selectNominationCategory"
                  />
                  <main class="home-wizard-content">
                    <HomeNominationReviewPane
                      v-if="nominationReviewMode"
                      :items="nominationReviewItems"
                      :total-links="nominationTotalLinks"
                      :total-categories="props.catOptions.length"
                      :on-edit-category="editNominationCategory"
                    />
                    <HomeNominationWizardPane
                      v-else
                      :category-name="activeNominationCategory ? activeNominationCategory.name || stripCategoryIcon(activeNominationCategory.label) : 'Kategorie'"
                      :links="activeNominationLinks"
                      :errors="activeNominationErrors"
                      :on-link-input="onNominationLinkInput"
                    />
                  </main>
                </div>
                <HomeWizardFooter
                  :progress-text="nominationProgressText"
                  :helper-text="nominationHelperText"
                  :actions="nominationReviewMode
                    ? [
                      { label: 'Zurück', tone: 'secondary', onClick: closeNominationReview },
                      { label: props.submitting ? 'Speichert ...' : 'Nominierungen einreichen', disabled: props.submitting || nominationHasErrors || nominationTotalLinks === 0, onClick: submitNominationDrafts },
                    ]
                    : [
                      { label: 'Zurück', tone: 'secondary', disabled: nominationCatValue === props.catOptions[0]?.id, onClick: goToPreviousNominationCategory },
                      { label: isLastNominationCategory ? 'Nominierungen prüfen' : 'Weiter', disabled: nominationHasErrors, onClick: isLastNominationCategory ? openNominationReview : goToNextNominationCategory },
                    ]"
                />
              </div>
            </template>
            <template v-else>
              <div class="home-vote-shell">
                <div class="home-modal__picker-header" style="padding:30px 36px 22px;border-bottom:1px solid #f1ecfb;">
                  <HomeStarField :count="13" variant="header" />
                  <div style="position:relative;z-index:1;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;">{{ props.isVote ? '★ Votingphase' : '✦ Nominierungen' }}</div>
                  <h3 style="position:relative;z-index:1;font-family:'Fredoka',sans-serif;font-weight:700;font-size:clamp(30px,3vw,36px);line-height:1.08;margin:0 0 14px;color:#3f3556;">{{ props.pickerTitle }}</h3>
                  <p style="position:relative;z-index:1;font-size:16px;line-height:1.5;color:#8a8398;margin:0;">{{ props.pickerSubtitle }}</p>
                </div>
                <HomeVotingPickerPane
                  :cat-list="props.catList"
                  :active-cat-index="props.activeCatIndex"
                  :active-cat-name="props.activeCatName"
                  :noms="props.noms"
                  :vote-count="props.voteCount"
                  :total-cats="props.totalCats"
                  :can-submit-vote="props.canSubmitVote"
                  :saved-vote-active="props.savedVoteActive"
                  :submit-vote="props.submitVote"
                  :submitting="props.submitting"
                  :readonly-mode="!props.isVote"
                />
              </div>
            </template>
          </template>

          <template v-if="props.isClip">
            <div class="home-modal__clip" style="display:flex;flex-direction:column;max-height:calc(88vh - 80px);">
              <div class="home-modal__clip-header" style="padding:30px 40px 24px;border-bottom:1px solid #f1ecfb;flex:none;">
                <div style="display:inline-flex;align-items:center;gap:7px;padding:4px 12px;border-radius:999px;background:rgba(247,108,173,.12);color:#c7508a;font-size:11px;font-weight:700;letter-spacing:1px;text-transform:uppercase;margin-bottom:14px;">✦ Nominierungsphase</div>
                <h3 style="font-family:'Fredoka',sans-serif;font-weight:700;font-size:26px;line-height:1.14;margin:0 0 6px;color:#3f3556;">Clip einreichen</h3>
                <p style="font-size:14px;line-height:1.5;color:#8a8398;margin:0;">Die besten Clips werden in der Award-Show präsentiert.</p>
              </div>
              <div class="home-modal__clip-body" style="padding:24px 40px 32px;overflow-y:auto;display:flex;flex-direction:column;gap:16px;">
                <div>
                  <label style="display:block;font-size:13px;font-weight:700;color:#5f44ad;margin-bottom:6px;">Clip-Link <span style="color:#e11d48;">*</span></label>
                  <input data-dc-ref="clipUrlRef" type="url" placeholder="https://plattform.de/dein-clip" style="width:100%;padding:12px 14px;border-radius:11px;border:1.5px solid #e6dcf6;background:#fbf9ff;font-family:'Outfit',sans-serif;font-size:14.5px;color:#3f3556;outline:none;box-sizing:border-box;" style-focus="border-color:#8b6cdb;" />
                </div>
                <div class="home-modal__clip-grid" style="display:grid;grid-template-columns:1fr 1fr;gap:12px;">
                  <div>
                    <label style="display:block;font-size:13px;font-weight:700;color:#5f44ad;margin-bottom:6px;">Kategorie</label>
                    <HomeSelectDropdown
                      v-model="clipCatValue"
                      label="Kategorie für Clip auswählen"
                      :options="props.catOptions"
                      @change="handleClipCategoryChange"
                    />
                  </div>
                  <div>
                    <label style="display:block;font-size:13px;font-weight:700;color:#5f44ad;margin-bottom:6px;">Für welche:n VTuber?</label>
                    <input
                      v-model="clipNomQuery"
                      data-dc-ref="clipNomSearchRef"
                      type="text"
                      list="clip-nominee-options"
                      placeholder="Name suchen"
                      autocomplete="off"
                      style="width:100%;padding:12px 14px;border-radius:11px;border:1.5px solid #e6dcf6;background:#fbf9ff;font-family:'Outfit',sans-serif;font-size:14.5px;color:#3f3556;outline:none;box-sizing:border-box;"
                      style-focus="border-color:#8b6cdb;"
                    />
                    <datalist id="clip-nominee-options">
                      <option v-for="option in props.clipNomOptions" :key="option.id" :value="option.label" />
                    </datalist>
                  </div>
                </div>
                <div>
                  <label style="display:block;font-size:13px;font-weight:700;color:#5f44ad;margin-bottom:6px;">Beschreibung <span style="color:#a99fc0;font-weight:400;">(optional)</span></label>
                  <textarea data-dc-ref="clipDescRef" placeholder="Warum ist dieser Moment so besonders?" rows="3" style="width:100%;padding:12px 14px;border-radius:11px;border:1.5px solid #e6dcf6;background:#fbf9ff;font-family:'Outfit',sans-serif;font-size:14.5px;color:#3f3556;outline:none;resize:none;box-sizing:border-box;" style-focus="border-color:#8b6cdb;"></textarea>
                </div>
                <label style="display:flex;align-items:flex-start;gap:11px;cursor:pointer;padding:13px;border-radius:11px;background:#f9f6ff;border:1px solid #ede4fb;">
                  <input type="checkbox" :checked="props.clipDsgvo" @change="props.clipDsgvoChange" style="width:17px;height:17px;flex:none;margin-top:2px;accent-color:#8b6cdb;cursor:pointer;" />
                  <span style="font-size:13px;line-height:1.6;color:#6f6685;">Ich stimme der Verarbeitung meiner Daten gemäß der <button @click="props.onOpenPrivacy" style="background:none;border:none;padding:0;color:#8b6cdb;font-weight:600;cursor:pointer;font-size:inherit;font-family:inherit;">Datenschutzerklärung</button> zu.</span>
                </label>
                <button @click="props.submitClip" :disabled="props.submitting || !props.canSubmitClip" :style="props.clipSubmitStyle">
                  <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
                  {{ props.submitting ? 'Speichert ...' : 'Clip einreichen' }}
                </button>
              </div>
            </div>
          </template>
        </template>
      </div>
    </div>
  </template>
</template>
