<template>
  <Card class="overflow-hidden">
    <div class="border-b border-violet-100 p-5">
      <div class="flex flex-wrap items-end justify-between gap-4">
        <div>
          <p class="text-xs font-semibold uppercase tracking-[0.24em] text-violet-500">Kategoriegesundheit</p>
          <h2 class="mt-1 text-xl font-bold text-slate-900">Status aller Kategorien</h2>
          <p class="mt-1 text-sm text-slate-500">Kompakter Überblick pro Status und Gruppe.</p>
        </div>
        <div class="flex items-center gap-2">
          <label class="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-500">Gruppe</label>
          <select
            :value="props.groupFilter"
            class="h-10 min-w-[180px] rounded-xl border border-violet-200 bg-white px-3 text-sm font-medium text-slate-700 outline-none transition focus:border-violet-400 focus:ring-4 focus:ring-violet-100"
            @change="onGroupChange"
          >
            <option
              v-for="group in props.groupOptions"
              :key="group"
              :value="group"
            >
              {{ group }}
            </option>
          </select>
        </div>
      </div>

        <div class="mt-4 grid gap-2 sm:grid-cols-2 xl:grid-cols-4">
        <button
          v-for="status in summaryCards"
          :key="status.key"
          type="button"
          class="rounded-[18px] border px-4 py-3 text-left transition hover:translate-y-[-1px]"
          :class="props.healthFilter === status.key ? status.activeClass : status.cardClass"
          @click="emit('update:healthFilter', status.key)"
        >
          <div class="flex items-start justify-between gap-3">
            <div>
              <p class="text-xs font-semibold uppercase tracking-[0.16em] opacity-80">{{ status.label }}</p>
              <strong class="mt-1.5 block text-2xl leading-none">{{ status.value }}</strong>
            </div>
            <span class="mt-1 h-2.5 w-2.5 rounded-full" :class="status.dotClass" />
          </div>
          <p class="mt-2 text-xs leading-5 opacity-85">{{ status.note }}</p>
        </button>
      </div>

      <div class="mt-3 flex flex-wrap items-center justify-between gap-3">
        <div class="flex flex-wrap gap-1.5">
          <button
            v-for="opt in props.healthStatusOptions"
            :key="opt.key"
            type="button"
            class="flex h-9 items-center gap-1.5 rounded-xl border px-3 text-xs font-semibold transition"
            :class="props.healthFilter === opt.key ? 'border-violet-200 bg-violet-100 text-violet-800' : 'border-violet-100 bg-white text-slate-600 hover:bg-violet-50'"
            @click="emit('update:healthFilter', opt.key)"
          >
            <span v-if="opt.dot" class="h-2 w-2 rounded-full" :class="opt.dot" />
            {{ opt.label }}
          </button>
        </div>

        <div class="flex flex-wrap gap-1.5">
          <button
            type="button"
            class="flex h-9 items-center rounded-xl border border-violet-100 bg-white px-3 text-xs font-semibold text-slate-600 transition hover:bg-violet-50"
            @click="openAllGroups"
          >
            Alle öffnen
          </button>
          <button
            type="button"
            class="flex h-9 items-center rounded-xl border border-violet-100 bg-white px-3 text-xs font-semibold text-slate-600 transition hover:bg-violet-50"
            @click="openProblemGroups"
          >
            Nur Problemgruppen
          </button>
        </div>
      </div>
    </div>

    <div v-if="groupedHealth.length > 0" class="space-y-4 bg-[linear-gradient(180deg,#fff,rgba(245,243,255,0.45))] p-4">
      <section
        v-for="group in groupedHealth"
        :key="group.name"
        class="rounded-[22px] border border-violet-100 bg-white/90 shadow-[0_10px_24px_rgba(139,108,219,0.07)]"
      >
        <button
          type="button"
          class="flex w-full flex-wrap items-start justify-between gap-3 px-4 py-3.5 text-left transition hover:bg-violet-50/40"
          @click="toggleGroup(group.name)"
        >
          <div class="flex min-w-0 items-start gap-3">
            <span class="mt-1 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-violet-200 bg-white text-violet-700">
              <ChevronRight class="h-3.5 w-3.5 transition" :class="isGroupOpen(group.name) ? 'rotate-90' : ''" />
            </span>
            <div class="min-w-0">
              <h3 class="text-base font-bold text-slate-900">{{ group.name }}</h3>
              <p class="mt-1 text-xs text-slate-500">{{ group.categories.length }} Kategorien in diesem Bereich</p>
            </div>
          </div>
          <div class="flex flex-wrap justify-end gap-2">
            <span class="rounded-full border border-slate-200 bg-slate-50 px-3 py-1 text-xs font-semibold text-slate-600">{{ group.categories.length }} Gesamt</span>
            <span v-if="group.emptyCount > 0" class="rounded-full border border-rose-200 bg-rose-50 px-3 py-1 text-xs font-semibold text-rose-700">{{ group.emptyCount }} leer</span>
            <span v-if="group.reviewCount > 0" class="rounded-full border border-amber-200 bg-amber-50 px-3 py-1 text-xs font-semibold text-amber-700">{{ group.reviewCount }} Review offen</span>
            <span v-if="group.winnerCount > 0" class="rounded-full border border-emerald-200 bg-emerald-50 px-3 py-1 text-xs font-semibold text-emerald-700">{{ group.winnerCount }} Gewinner</span>
          </div>
        </button>

        <div
          v-if="isGroupOpen(group.name)"
          class="grid gap-2.5 border-t border-violet-100 p-3 lg:grid-cols-2"
        >
          <RouterLink
            v-for="category in group.categories"
            :key="category.id"
            :to="`/admin/categories?group=${encodeURIComponent(category.groupName || 'Ohne Gruppe')}`"
            class="rounded-[18px] border p-3 transition hover:border-violet-200 hover:bg-violet-50/40"
            :class="category.cardClass"
          >
            <div class="flex items-start justify-between gap-3">
              <div class="min-w-0">
                <div class="flex items-center gap-2">
                  <span class="h-2.5 w-2.5 shrink-0 rounded-full" :class="category.statusDot" />
                  <strong class="truncate text-sm text-slate-900">{{ category.name }}</strong>
                </div>
                <p class="mt-1 text-xs text-slate-500">{{ category.groupName || 'Ohne Gruppe' }}</p>
              </div>
              <span class="inline-flex items-center gap-1.5 rounded-full border px-3 py-1 text-[11px] font-bold" :class="category.statusClass">
                {{ category.status }}
              </span>
            </div>

            <div class="mt-3 grid grid-cols-2 gap-2 text-sm">
              <div class="rounded-2xl border border-slate-100 bg-white/70 px-3 py-2">
                <p class="text-[11px] font-semibold uppercase tracking-[0.14em] text-slate-500">Kandidaten</p>
                <strong class="mt-1 block text-base text-slate-900">{{ category.candidates }}</strong>
              </div>
              <div class="rounded-2xl border border-slate-100 bg-white/70 px-3 py-2">
                <p class="text-[11px] font-semibold uppercase tracking-[0.14em] text-slate-500">Reviews</p>
                <strong class="mt-1 block text-base" :class="category.reviews > 0 ? 'text-amber-700' : 'text-slate-900'">{{ category.reviews }}</strong>
              </div>
              <div class="rounded-2xl border border-slate-100 bg-white/70 px-3 py-2">
                <p class="text-[11px] font-semibold uppercase tracking-[0.14em] text-slate-500">Votes</p>
                <strong class="mt-1 block text-base text-slate-900">{{ category.votes.toLocaleString('de-DE') }}</strong>
              </div>
              <div class="rounded-2xl border border-slate-100 bg-white/70 px-3 py-2">
                <p class="text-[11px] font-semibold uppercase tracking-[0.14em] text-slate-500">Anteil</p>
                <strong class="mt-1 block text-base text-violet-700">{{ category.votePct }}%</strong>
              </div>
            </div>
          </RouterLink>
        </div>
      </section>
    </div>

    <div v-else class="px-5 py-12 text-center text-sm text-slate-500">
      Keine Kategorien für diesen Filter.
    </div>

    <div class="flex items-center gap-2 border-t border-violet-100 bg-emerald-50/60 px-5 py-3 text-sm text-emerald-800">
      <CheckCircle2 class="h-4 w-4 shrink-0 text-emerald-500" />
      Analytics nutzt dieselben Admin-Daten wie Dashboard, Jahre und Kategorien.
      <RouterLink to="/admin/categories" class="ml-auto flex items-center gap-1 text-xs font-semibold text-violet-600 hover:text-violet-800">
        Kategorien bearbeiten <ExternalLink class="h-3 w-3" />
      </RouterLink>
    </div>
  </Card>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { CheckCircle2, ChevronRight, ExternalLink } from '@lucide/vue'
import { RouterLink } from 'vue-router'

import Card from '../ui/Card.vue'

interface HealthOption {
  key: string
  label: string
  dot?: string
}

interface HealthCategory {
  id: number
  name: string
  groupName: string
  candidates: number
  reviews: number
  hasWinner: boolean
  votes: number
  votePct: number
  status: string
  statusClass: string
  statusDot: string
  cardClass: string
}

const props = defineProps<{
  filteredHealth: HealthCategory[]
  healthSummary: {
    leer: number
    reviewOffen: number
    bereit: number
    gewinner: number
    total: number
  }
  groupOptions: string[]
  groupFilter: string
  healthFilter: string
  healthStatusOptions: HealthOption[]
  candidateWarningsActive: boolean
  reviewWarningsActive: boolean
}>()

const emit = defineEmits<{
  'update:groupFilter': [value: string]
  'update:healthFilter': [value: string]
}>()

const openGroups = ref<string[]>([])

function onGroupChange(event: Event) {
  const target = event.target as HTMLSelectElement | null
  if (target) {
    emit('update:groupFilter', target.value)
  }
}

const groupedHealth = computed(() => {
  const groups = new Map<string, HealthCategory[]>()
  for (const category of props.filteredHealth) {
    const key = category.groupName || 'Ohne Gruppe'
    if (!groups.has(key)) {
      groups.set(key, [])
    }
    groups.get(key)!.push(category)
  }

  return [...groups.entries()].map(([name, categories]) => ({
    name,
    categories,
    emptyCount: props.candidateWarningsActive ? categories.filter((item) => item.status === 'Leer').length : 0,
    reviewCount: props.reviewWarningsActive ? categories.filter((item) => item.status === 'Review offen').length : 0,
    winnerCount: categories.filter((item) => item.status === 'Gewinner gesetzt').length,
  }))
})

watch(
  groupedHealth,
  (groups) => {
    const availableNames = new Set(groups.map((group) => group.name))
    const preserved = openGroups.value.filter((name) => availableNames.has(name))
    const autoOpen = groups
      .filter((group) => group.emptyCount > 0 || group.reviewCount > 0)
      .map((group) => group.name)

    openGroups.value = [...new Set([...(preserved.length > 0 ? preserved : autoOpen), ...(preserved.length === 0 && autoOpen.length === 0 && groups[0] ? [groups[0].name] : [])])]
  },
  { immediate: true },
)

function isGroupOpen(name: string) {
  return openGroups.value.includes(name)
}

function toggleGroup(name: string) {
  openGroups.value = isGroupOpen(name)
    ? openGroups.value.filter((entry) => entry !== name)
    : [...openGroups.value, name]
}

function openAllGroups() {
  openGroups.value = groupedHealth.value.map((group) => group.name)
}

function openProblemGroups() {
  const problemGroups = groupedHealth.value
    .filter((group) => group.emptyCount > 0 || group.reviewCount > 0)
    .map((group) => group.name)

  openGroups.value = problemGroups.length > 0
    ? problemGroups
    : groupedHealth.value.slice(0, 1).map((group) => group.name)
}

const summaryCards = computed(() => [
  {
    key: 'Leer',
    label: 'Leer',
    value: props.healthSummary.leer,
    note: props.healthSummary.leer === 0
      ? 'Keine Lücken in der Kandidatenbasis.'
      : props.candidateWarningsActive
        ? 'Diese Kategorien brauchen zuerst Kandidaten.'
        : 'Noch normaler Vorbereitungsstand.',
    dotClass: props.candidateWarningsActive ? 'bg-rose-400' : 'bg-violet-400',
    cardClass: props.candidateWarningsActive ? 'border-rose-100 bg-rose-50/70 text-rose-800' : 'border-violet-100 bg-violet-50/70 text-violet-800',
    activeClass: props.candidateWarningsActive ? 'border-rose-200 bg-rose-100 text-rose-900 shadow-[0_12px_28px_rgba(244,63,94,0.12)]' : 'border-violet-200 bg-violet-100 text-violet-900 shadow-[0_12px_28px_rgba(139,92,246,0.12)]',
  },
  {
    key: 'Review offen',
    label: 'Review offen',
    value: props.healthSummary.reviewOffen,
    note: props.healthSummary.reviewOffen === 0
      ? 'Keine offenen Review-Staus.'
      : props.reviewWarningsActive
        ? 'Hier blockiert noch Nominationsarbeit.'
        : 'Nominierungen laufen noch; Review folgt später.',
    dotClass: props.reviewWarningsActive ? 'bg-amber-400' : 'bg-violet-400',
    cardClass: props.reviewWarningsActive ? 'border-amber-100 bg-amber-50/70 text-amber-800' : 'border-violet-100 bg-violet-50/70 text-violet-800',
    activeClass: props.reviewWarningsActive ? 'border-amber-200 bg-amber-100 text-amber-900 shadow-[0_12px_28px_rgba(245,158,11,0.12)]' : 'border-violet-200 bg-violet-100 text-violet-900 shadow-[0_12px_28px_rgba(139,92,246,0.12)]',
  },
  {
    key: 'Bereit',
    label: 'Bereit',
    value: props.healthSummary.bereit,
    note: 'Kandidatenbasis steht, aber finale Winner-Setzung fehlt noch.',
    dotClass: 'bg-sky-400',
    cardClass: 'border-sky-100 bg-sky-50/70 text-sky-800',
    activeClass: 'border-sky-200 bg-sky-100 text-sky-900 shadow-[0_12px_28px_rgba(56,189,248,0.12)]',
  },
  {
    key: 'Gewinner gesetzt',
    label: 'Gewinner',
    value: props.healthSummary.gewinner,
    note: 'Diese Kategorien sind inhaltlich am weitesten abgeschlossen.',
    dotClass: 'bg-emerald-400',
    cardClass: 'border-emerald-100 bg-emerald-50/70 text-emerald-800',
    activeClass: 'border-emerald-200 bg-emerald-100 text-emerald-900 shadow-[0_12px_28px_rgba(16,185,129,0.12)]',
  },
])
</script>
