<template>
  <div class="space-y-3">
    <article
      v-for="group in groups"
      :key="group.name"
      class="overflow-hidden rounded-2xl border bg-white/90 shadow-[0_14px_36px_rgba(124,91,180,0.08)] transition"
      :class="selectedGroupName === group.name ? 'border-violet-200 ring-2 ring-violet-100' : 'border-violet-100'"
    >
      <button
        type="button"
        class="grid w-full gap-3 border-b border-violet-100 bg-violet-50/45 px-4 py-4 text-left lg:grid-cols-[minmax(0,1fr)_auto] lg:items-center"
        @click="toggleGroup(group.name); $emit('select-group', group.name)"
      >
        <div class="min-w-0">
          <div class="flex min-w-0 flex-wrap items-center gap-2">
            <span class="grid h-8 w-8 shrink-0 place-items-center rounded-xl bg-white text-violet-700 shadow-sm">
              <FolderTree class="h-4 w-4" />
            </span>
            <h2 class="truncate text-lg font-bold text-slate-900">{{ group.name }}</h2>
            <span class="rounded-full bg-white px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.12em] text-violet-700">
              {{ group.totalCategories }} Unterkategorien
            </span>
          </div>
          <p class="mt-2 text-sm leading-6 text-slate-500">
            {{ group.completedCount }} gesetzt · {{ group.missingCount }} offen · {{ group.approvedClips }} Clips freigegeben
          </p>
        </div>

        <div class="flex flex-wrap items-center gap-2 lg:justify-end">
          <span class="rounded-full bg-emerald-50 px-3 py-1 text-xs font-semibold text-emerald-700">
            {{ group.completedCount }} gesetzt
          </span>
          <span class="rounded-full bg-sky-50 px-3 py-1 text-xs font-semibold text-sky-700">
            {{ group.missingCount }} offen
          </span>
          <span v-if="group.pendingReviewCount > 0" class="rounded-full bg-amber-50 px-3 py-1 text-xs font-semibold text-amber-700">
            {{ group.pendingReviewCount }} Reviews
          </span>
          <span v-if="group.emptyCount > 0" class="rounded-full bg-rose-50 px-3 py-1 text-xs font-semibold text-rose-700">
            {{ group.emptyCount }} leer
          </span>
          <span class="grid h-8 w-8 shrink-0 place-items-center rounded-xl border border-violet-100 bg-white text-violet-700">
            <ChevronDown class="h-4 w-4 transition" :class="isExpanded(group.name) ? 'rotate-180' : ''" />
          </span>
        </div>
      </button>

      <div v-if="isExpanded(group.name)" class="divide-y divide-violet-100 bg-violet-50/20">
        <article
          v-for="row in group.categories"
          :key="row.category.id"
          :id="`winner-category-${row.category.id}`"
          :data-category-id="row.category.id"
          class="bg-[linear-gradient(180deg,rgba(244,239,255,0.72),rgba(255,255,255,0.98))] px-4 py-4 transition"
          :class="focusedCategoryId === row.category.id ? 'bg-violet-50/80' : ''"
          @click="$emit('select-category', row.category.id)"
        >
          <div class="grid gap-3 xl:grid-cols-[minmax(260px,1fr)_auto] xl:items-center">
            <div class="min-w-0 flex-1">
              <div class="flex min-w-0 flex-wrap items-center gap-2">
                <span class="grid h-8 w-8 shrink-0 place-items-center rounded-xl bg-white text-violet-700 shadow-sm">
                  <GitBranch class="h-4 w-4" />
                </span>
                <p class="truncate text-lg font-bold text-slate-900">{{ row.category.name }}</p>
                <span
                  class="rounded-full px-2.5 py-1 text-[10px] font-bold uppercase tracking-[0.12em]"
                  :class="statusClass(row)"
                >
                  {{ statusLabel(row) }}
                </span>
              </div>
              <p class="mt-2 text-sm leading-6 text-slate-500">
                {{ row.existing?.candidateDisplayName || 'Noch kein Gewinner gesetzt' }}
              </p>
            </div>

            <div class="flex flex-wrap items-center gap-2 xl:justify-end">
              <span class="rounded-full bg-violet-100/70 px-3 py-1 text-xs font-semibold text-violet-700">
                {{ row.candidates.length }} Kandidaten
              </span>
              <span class="rounded-full bg-sky-100/70 px-3 py-1 text-xs font-semibold text-sky-700">
                {{ row.approvedClips }} Clips
              </span>
              <span v-if="row.hasPendingReviews" class="rounded-full bg-amber-100 px-3 py-1 text-xs font-semibold text-amber-700">
                {{ row.openReviews }} Reviews
              </span>
            </div>
          </div>

          <div class="mt-3 grid gap-3 xl:grid-cols-[minmax(0,1fr)_auto] xl:items-start">
            <div class="space-y-3" @click.stop>
              <NativeSelect
                :model-value="winnerSelections[row.category.id]"
                :disabled="row.isEmpty"
                :options="buildWinnerOptions(row)"
                @update:model-value="$emit('update:winner-selection', row.category.id, String($event ?? ''))"
              />

              <p
                v-if="winnerRuleNoticeFor(row.category.id)"
                class="flex flex-col gap-3 rounded-2xl border px-3 py-2 text-sm font-semibold sm:flex-row sm:items-center sm:justify-between"
                :class="winnerRuleNoticeFor(row.category.id)?.mode === 'block'
                  ? 'border-rose-100 bg-rose-50 text-rose-700'
                  : 'border-amber-100 bg-amber-50 text-amber-700'"
              >
                <span>
                  {{ winnerRuleNoticeFor(row.category.id)?.mode === 'block' ? 'Blockiert' : 'Warnung' }}:
                  {{ winnerRuleNoticeFor(row.category.id)?.message }}
                </span>
                <RouterLink
                  v-if="winnerSelections[row.category.id]"
                  class="inline-flex shrink-0 items-center justify-center rounded-full border border-current/20 bg-white/80 px-3 py-1.5 text-xs font-bold transition hover:bg-white"
                  :to="candidateDetailLink(row.category.id)"
                >
                  Kandidat bearbeiten
                </RouterLink>
              </p>

              <div
                v-if="selectedWinnerIdentitySummary(row.category.id)"
                class="grid gap-2 sm:grid-cols-4"
              >
                <div class="rounded-2xl border border-violet-100 bg-white/70 px-3 py-2">
                  <p class="text-[10px] font-semibold uppercase tracking-[0.14em] text-slate-500">Kandidaturen</p>
                  <strong class="mt-1 block text-sm text-violet-900">{{ selectedWinnerIdentitySummary(row.category.id)?.appearances }}</strong>
                </div>
                <div class="rounded-2xl border border-violet-100 bg-white/70 px-3 py-2">
                  <p class="text-[10px] font-semibold uppercase tracking-[0.14em] text-slate-500">Gewinner</p>
                  <strong class="mt-1 block text-sm text-violet-900">{{ selectedWinnerIdentitySummary(row.category.id)?.winnerPlacements }}</strong>
                </div>
                <div class="rounded-2xl border border-violet-100 bg-white/70 px-3 py-2">
                  <p class="text-[10px] font-semibold uppercase tracking-[0.14em] text-slate-500">Nominierungen</p>
                  <strong class="mt-1 block text-sm text-violet-900">{{ selectedWinnerIdentitySummary(row.category.id)?.nominationTally }}</strong>
                </div>
                <div class="rounded-2xl border border-violet-100 bg-white/70 px-3 py-2">
                  <p class="text-[10px] font-semibold uppercase tracking-[0.14em] text-slate-500">Clip</p>
                  <strong class="mt-1 block text-sm text-violet-900">{{ selectedWinnerIdentitySummary(row.category.id)?.hasClip ? 'vorhanden' : 'fehlt' }}</strong>
                </div>
              </div>
            </div>

            <div class="flex flex-wrap gap-2 xl:justify-end" @click.stop>
              <Button
                :disabled="savingResultForCategory === row.category.id || row.isEmpty || !winnerSelections[row.category.id] || winnerRuleNoticeFor(row.category.id)?.mode === 'block'"
                @click="$emit('save', row.category.id)"
              >
                {{ savingResultForCategory === row.category.id ? 'Speichert ...' : row.existing ? 'Aktualisieren' : 'Setzen' }}
              </Button>
              <Button
                v-if="row.existing"
                variant="secondary"
                class="gap-1.5"
                :disabled="deletingResultId === row.existing.id"
                @click="$emit('clear', row.existing.id)"
              >
                <Trash2 class="h-4 w-4" />
                {{ deletingResultId === row.existing.id ? 'Entfernt ...' : 'Entfernen' }}
              </Button>
            </div>
          </div>
        </article>
      </div>
    </article>

    <div v-if="groups.length === 0" class="rounded-2xl border border-dashed border-violet-200 bg-violet-50/50 px-4 py-12 text-center text-sm text-slate-500">
      Keine Hauptkategorien passen zu diesem Filter.
    </div>
  </div>
</template>

<script setup lang="ts">
import { ChevronDown, FolderTree, GitBranch, Trash2 } from '@lucide/vue'
import { nextTick, ref, watch } from 'vue'
import { RouterLink } from 'vue-router'

import type {
  AdminWinnerGroupSummary,
  AdminWinnerResultRow,
  WinnerIdentitySummary,
  WinnerRuleNotice,
} from './useAdminWinnersManager'
import Button from '../ui/Button.vue'
import NativeSelect from '../ui/NativeSelect.vue'

const props = defineProps<{
  groups: AdminWinnerGroupSummary[]
  selectedGroupName: string | null
  focusedCategoryId: number | null
  winnerSelections: Record<number, string>
  savingResultForCategory: number | null
  deletingResultId: number | null
  selectedWinnerIdentitySummary: (categoryId: number) => WinnerIdentitySummary | null
  winnerRuleNoticeFor: (categoryId: number) => WinnerRuleNotice | null
}>()

defineEmits<{
  'select-group': [groupName: string]
  'select-category': [categoryId: number]
  'update:winner-selection': [categoryId: number, value: string]
  save: [categoryId: number]
  clear: [resultId: number]
}>()

const expandedGroup = ref<string | null>(null)

watch(
  () => props.groups.map((group) => group.name),
  (groupNames) => {
    if (!expandedGroup.value || !groupNames.includes(expandedGroup.value)) {
      expandedGroup.value = groupNames[0] ?? null
    }
  },
  { immediate: true },
)

watch(
  () => props.selectedGroupName,
  (groupName) => {
    if (groupName) {
      expandedGroup.value = groupName
    }
  },
)

watch(
  () => props.focusedCategoryId,
  async (categoryId) => {
    if (!categoryId) return

    const matchingGroup = props.groups.find((group) =>
      group.categories.some((row) => row.category.id === categoryId),
    )

    if (matchingGroup) {
      expandedGroup.value = matchingGroup.name
    }

    await nextTick()
    const target = document.querySelector<HTMLElement>(`[data-category-id="${categoryId}"]`)
    target?.scrollIntoView({ behavior: 'smooth', block: 'center' })
  },
  { immediate: true },
)

function isExpanded(groupName: string) {
  return expandedGroup.value === groupName
}

function toggleGroup(groupName: string) {
  expandedGroup.value = groupName
}

function buildWinnerOptions(row: AdminWinnerResultRow) {
  const rankByCandidateId = new Map(row.topVotingRanks.map((rank) => [rank.candidateId, rank]))
  const sortedCandidates = [...row.candidates].sort((left, right) => {
    const leftRank = rankByCandidateId.get(left.id)?.rank ?? Number.POSITIVE_INFINITY
    const rightRank = rankByCandidateId.get(right.id)?.rank ?? Number.POSITIVE_INFINITY
    return leftRank - rightRank || left.displayName.localeCompare(right.displayName, 'de')
  })

  return [
    { label: 'Bitte Gewinner wählen', value: '' },
    ...sortedCandidates.map((candidate) => {
      const rank = rankByCandidateId.get(candidate.id)
      return {
        label: `${candidate.displayName} · ${candidate.channelSlug} · ${candidate.platform} · ${candidate.clipCompilationUrl ? 'Clip gepflegt' : 'kein Clip'}`,
        value: `${candidate.id}`,
        meta: rank ? `#${rank.rank} · ${rank.votes.toLocaleString('de-DE')} Votes` : undefined,
      }
    }),
  ]
}

function candidateDetailLink(categoryId: number) {
  const candidateId = props.winnerSelections[categoryId]
  return `/admin/candidates?candidateId=${candidateId}&categoryId=${categoryId}`
}

function statusLabel(row: AdminWinnerResultRow) {
  if (row.isEmpty) return row.isEmptyWarning ? 'Leer' : 'Später'
  if (row.hasPendingReviews) return row.isComplete ? 'Gesetzt + Review' : 'Review'
  if (row.isComplete) return 'Gesetzt'
  return 'Offen'
}

function statusClass(row: AdminWinnerResultRow) {
  if (row.isEmptyWarning) return 'bg-rose-100 text-rose-700'
  if (row.isEmpty) return 'bg-violet-100 text-violet-700'
  if (row.hasPendingReviews) return 'bg-amber-100 text-amber-700'
  if (row.isComplete) return 'bg-emerald-100 text-emerald-700'
  return 'bg-sky-100 text-sky-700'
}
</script>
