import { computed, reactive, ref, watch } from 'vue'
import { CheckCircle2, Clock3, ListChecks, Trophy } from '@lucide/vue'

import { useAwardsStore } from '../../stores/awards'

const allFilter = 'all'

export function useAdminWinnersManager() {
  const store = useAwardsStore()
  const savingResultForCategory = ref<number | null>(null)
  const deletingResultId = ref<number | null>(null)
  const adminMessage = ref('')
  const adminError = ref('')
  const query = ref('')
  const statusFilter = ref(allFilter)
  const winnerSelections = reactive<Record<number, string>>({})

  const seasonDetail = computed(() => store.adminSeasonDetail)
  const resultMap = computed(() => new Map(seasonDetail.value.results.map((result) => [result.categoryId, result])))

  const resultRows = computed(() =>
    seasonDetail.value.categories
      .map((category) => {
        const candidates = seasonDetail.value.candidates
          .filter((candidate) => candidate.categoryId === category.id)
          .sort((a, b) => a.displayName.localeCompare(b.displayName))
        const existing = resultMap.value.get(category.id) ?? null
        const openReviews = seasonDetail.value.pendingNominations.filter((nomination) => nomination.categoryId === category.id).length
        const approvedClips = seasonDetail.value.clipSubmissions.filter((clip) => clip.categoryId === category.id && clip.status === 'approved').length

        return {
          category,
          candidates,
          existing,
          openReviews,
          approvedClips,
          hasPendingReviews: openReviews > 0,
          isEmpty: candidates.length === 0,
          isComplete: Boolean(existing),
        }
      })
      .sort((a, b) => a.category.sortOrder - b.category.sortOrder),
  )

  const completedCount = computed(() => resultRows.value.filter((row) => row.isComplete).length)
  const missingCount = computed(() => Math.max(0, resultRows.value.length - completedCount.value))
  const reviewWarningCount = computed(() => resultRows.value.filter((row) => row.hasPendingReviews).length)
  const emptyCount = computed(() => resultRows.value.filter((row) => row.isEmpty).length)
  const completionPct = computed(() => resultRows.value.length === 0 ? 0 : Math.round((completedCount.value / resultRows.value.length) * 100))

  const statusFilters = computed(() => [
    { value: allFilter, label: 'Alle', count: resultRows.value.length },
    { value: 'open', label: 'Offen', count: missingCount.value },
    { value: 'set', label: 'Gesetzt', count: completedCount.value },
    { value: 'review', label: 'Reviews offen', count: reviewWarningCount.value },
    { value: 'empty', label: 'Ohne Kandidaten', count: emptyCount.value },
  ])

  const visibleResultRows = computed(() => {
    const normalizedQuery = query.value.trim().toLowerCase()

    return resultRows.value.filter((row) => {
      const matchesStatus = statusFilter.value === allFilter
        || (statusFilter.value === 'open' && !row.isComplete)
        || (statusFilter.value === 'set' && row.isComplete)
        || (statusFilter.value === 'review' && row.hasPendingReviews)
        || (statusFilter.value === 'empty' && row.isEmpty)

      if (!matchesStatus) return false
      if (!normalizedQuery) return true

      return [
        row.category.name,
        row.category.groupName,
        row.existing?.candidateDisplayName ?? '',
        ...row.candidates.map((candidate) => `${candidate.displayName} ${candidate.channelSlug} ${candidate.platform}`),
      ].some((value) => value.toLowerCase().includes(normalizedQuery))
    })
  })

  const summaryCards = computed(() => [
    {
      label: 'Fortschritt',
      value: `${completionPct.value}%`,
      note: `${completedCount.value} von ${resultRows.value.length} Kategorien final.`,
      icon: Trophy,
      tone: 'border-violet-100 bg-violet-50 text-violet-800',
    },
    {
      label: 'Offen',
      value: String(missingCount.value),
      note: missingCount.value === 0 ? 'Keine Gewinner fehlen.' : 'Diese Kategorien brauchen eine Auswahl.',
      icon: ListChecks,
      tone: missingCount.value > 0 ? 'border-sky-100 bg-sky-50 text-sky-800' : 'border-emerald-100 bg-emerald-50 text-emerald-800',
    },
    {
      label: 'Reviews',
      value: String(reviewWarningCount.value),
      note: reviewWarningCount.value === 0 ? 'Keine Review-Warnungen.' : 'Vor finaler Freigabe pruefen.',
      icon: Clock3,
      tone: reviewWarningCount.value > 0 ? 'border-amber-100 bg-amber-50 text-amber-800' : 'border-emerald-100 bg-emerald-50 text-emerald-800',
    },
    {
      label: 'Gesetzt',
      value: String(completedCount.value),
      note: 'Speist Archiv und Gewinneransicht.',
      icon: CheckCircle2,
      tone: 'border-emerald-100 bg-emerald-50 text-emerald-800',
    },
  ])

  watch(resultRows, (rows) => {
    const knownCategoryIds = new Set(rows.map((row) => row.category.id))
    for (const key of Object.keys(winnerSelections)) {
      if (!knownCategoryIds.has(Number(key))) {
        delete winnerSelections[Number(key)]
      }
    }

    for (const row of rows) {
      winnerSelections[row.category.id] = row.existing?.candidateId ? String(row.existing.candidateId) : ''
    }
  }, { immediate: true })

  async function saveWinner(categoryId: number) {
    const candidateId = Number(winnerSelections[categoryId])
    if (!candidateId || !seasonDetail.value.id) return
    savingResultForCategory.value = categoryId
    adminMessage.value = ''
    adminError.value = ''
    try {
      await store.setAdminResult(seasonDetail.value.id, { categoryId, candidateId })
      adminMessage.value = 'Gewinner wurde gespeichert.'
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Gewinner konnte nicht gespeichert werden.'
    } finally {
      savingResultForCategory.value = null
    }
  }

  async function clearWinner(resultId: number) {
    if (!seasonDetail.value.id) return
    deletingResultId.value = resultId
    adminMessage.value = ''
    adminError.value = ''
    try {
      await store.deleteAdminResult(resultId, seasonDetail.value.id)
      adminMessage.value = 'Gewinner wurde entfernt.'
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Gewinner konnte nicht entfernt werden.'
    } finally {
      deletingResultId.value = null
    }
  }

  return {
    adminError,
    adminMessage,
    completionPct,
    deletingResultId,
    query,
    savingResultForCategory,
    statusFilter,
    statusFilters,
    summaryCards,
    visibleResultRows,
    winnerSelections,
    clearWinner,
    saveWinner,
  }
}
