import { computed, ref, watch } from 'vue'
import { AlertTriangle, CheckCircle2, Trophy, Vote } from '@lucide/vue'
import { useRoute } from 'vue-router'

import { useAwardsStore } from '../../stores/awards'
import type {
  AdminVotingCandidateRank,
  AdminVotingCategoryWorkspaceItem,
} from '../../types/awards'
import { buildAdminReadinessScope } from './adminReadinessPhase'

const allFilter = 'all'

export interface AdminVotingWorkspaceRow extends AdminVotingCategoryWorkspaceItem {
  statusKey: 'winner' | 'issues' | 'ready' | 'empty' | 'idle'
  statusLabel: string
  statusTone: string
  topCandidate: AdminVotingCandidateRank | null
  topFour: AdminVotingCandidateRank[]
  showMissingClipWarning: boolean
  showOpenReviewWarning: boolean
  showTopVoteTieWarning: boolean
  showRuleConflictWarning: boolean
  isProblem: boolean
}

export interface AdminVotingGroupSummary {
  name: string
  sortOrder: number
  totalCategories: number
  votedCategories: number
  totalVotes: number
  readyCount: number
  problemCount: number
  winnerSetCount: number
  categories: AdminVotingWorkspaceRow[]
}

export function useAdminVotingManager() {
  const store = useAwardsStore()
  const route = useRoute()

  const query = ref('')
  const statusFilter = ref(allFilter)
  const problemOnly = ref(false)
  const selectedGroupName = ref<string | null>(null)
  const focusedCategoryId = ref<number | null>(null)

  const seasonDetail = computed(() => store.adminSeasonDetail)
  const seasonCandidates = computed(() => seasonDetail.value.candidates)
  const votingWorkspace = computed(() => seasonDetail.value.votingWorkspace)
  const readinessScope = computed(() => buildAdminReadinessScope(seasonDetail.value))

  const workspaceRows = computed<AdminVotingWorkspaceRow[]>(() =>
    votingWorkspace.value.categories
      .map((category) => {
        const topCandidate = category.leaderboard[0] ?? null
        const showMissingClipWarning = category.hasMissingClip && readinessScope.value.candidateWarningsActive
        const showOpenReviewWarning = category.hasOpenReviews && readinessScope.value.reviewWarningsActive
        const showTopVoteTieWarning = category.hasTopVoteTie && readinessScope.value.winnerWarningsActive
        const showRuleConflictWarning = category.hasRuleConflict && readinessScope.value.winnerWarningsActive
        const isProblem = showMissingClipWarning
          || showOpenReviewWarning
          || showTopVoteTieWarning
          || showRuleConflictWarning

        let statusKey: AdminVotingWorkspaceRow['statusKey'] = 'idle'
        let statusLabel = 'Leer'
        let statusTone = 'border-slate-200 bg-slate-50 text-slate-600'

        if (category.hasWinner) {
          statusKey = 'winner'
          statusLabel = 'Gewinner gesetzt'
          statusTone = 'border-emerald-100 bg-emerald-50 text-emerald-700'
        } else if (isProblem) {
          statusKey = 'issues'
          statusLabel = 'Prüfen'
          statusTone = 'border-amber-100 bg-amber-50 text-amber-700'
        } else if (category.winnerReady) {
          statusKey = 'ready'
          statusLabel = readinessScope.value.winnerWarningsActive ? 'Bereit' : 'Voting bereit'
          statusTone = 'border-sky-100 bg-sky-50 text-sky-700'
        } else if (category.candidateCount > 0) {
          statusKey = 'empty'
          statusLabel = readinessScope.value.phaseKey === 'nomination' ? 'Später' : 'Vorbereitung offen'
          statusTone = readinessScope.value.phaseKey === 'nomination'
            ? 'border-slate-200 bg-slate-50 text-slate-600'
            : 'border-violet-100 bg-violet-50 text-violet-700'
        }

        return {
          ...category,
          statusKey,
          statusLabel,
          statusTone,
          topCandidate,
          topFour: category.leaderboard.slice(0, 4),
          showMissingClipWarning,
          showOpenReviewWarning,
          showTopVoteTieWarning,
          showRuleConflictWarning,
          isProblem,
        }
      })
      .sort((left, right) =>
        left.sortOrder - right.sortOrder
        || left.groupName.localeCompare(right.groupName, 'de')
        || left.categoryName.localeCompare(right.categoryName, 'de')),
  )

  function rowMatchesFilters(row: AdminVotingWorkspaceRow) {
    if (problemOnly.value && !row.isProblem) {
      return false
    }

    if (statusFilter.value !== allFilter) {
      if (statusFilter.value === 'winner' && !row.hasWinner) return false
      if (statusFilter.value === 'ready' && !row.winnerReady) return false
      if (statusFilter.value === 'issues' && !row.isProblem) return false
      if (statusFilter.value === 'idle' && row.voteCount > 0) return false
    }

    const normalizedQuery = query.value.trim().toLowerCase()
    if (!normalizedQuery) {
      return true
    }

    return [
      row.groupName,
      row.categoryName,
      row.topCandidate?.displayName ?? '',
      ...row.leaderboard.map((candidate) => `${candidate.displayName} ${candidate.channelSlug} ${candidate.platform}`),
    ].some((value) => value.toLowerCase().includes(normalizedQuery))
  }

  const votingGroups = computed<AdminVotingGroupSummary[]>(() => {
    const grouped = new Map<string, AdminVotingWorkspaceRow[]>()
    for (const row of workspaceRows.value) {
      const key = row.groupName.trim() || 'Ohne Hauptkategorie'
      const current = grouped.get(key)
      if (current) current.push(row)
      else grouped.set(key, [row])
    }

    return [...grouped.entries()]
      .map(([name, rows]) => {
        const categories = rows.filter(rowMatchesFilters)
        if (categories.length === 0) return null

        return {
          name,
          sortOrder: Math.min(...rows.map((row) => row.sortOrder)),
          totalCategories: categories.length,
          votedCategories: categories.filter((row) => row.voteCount > 0).length,
          totalVotes: categories.reduce((sum, row) => sum + row.voteCount, 0),
          readyCount: categories.filter((row) => row.winnerReady).length,
          problemCount: categories.filter((row) => row.isProblem).length,
          winnerSetCount: categories.filter((row) => row.hasWinner).length,
          categories,
        } satisfies AdminVotingGroupSummary
      })
      .filter((group): group is AdminVotingGroupSummary => group !== null)
      .sort((left, right) => left.sortOrder - right.sortOrder || left.name.localeCompare(right.name, 'de'))
  })

  const selectedGroup = computed(() =>
    votingGroups.value.find((group) => group.name === selectedGroupName.value)
    ?? votingGroups.value[0]
    ?? null,
  )

  const selectedCategory = computed(() =>
    selectedGroup.value?.categories.find((row) => row.categoryId === focusedCategoryId.value)
    ?? selectedGroup.value?.categories[0]
    ?? null,
  )

  const summaryCards = computed(() => [
    {
      label: 'Gesamtvotes',
      value: votingWorkspace.value.summary.totalVotes.toLocaleString('de-DE'),
      note: 'Alle abgegebenen Vote-Eintraege der aktuellen Season.',
      icon: Vote,
      tone: 'border-violet-100 bg-violet-50 text-violet-800',
    },
    {
      label: 'Abgedeckt',
      value: `${votingWorkspace.value.summary.votedSubcategories}/${votingWorkspace.value.summary.totalSubcategories}`,
      note: 'Unterkategorien mit Votes',
      icon: CheckCircle2,
      tone: 'border-sky-100 bg-sky-50 text-sky-800',
    },
    {
      label: 'Vorbereitung',
      value: String(votingWorkspace.value.summary.readySubcategories),
      note: 'Unterkategorien sind für Gewinner vorbereitet',
      icon: Trophy,
      tone: 'border-emerald-100 bg-emerald-50 text-emerald-800',
    },
    {
      label: 'Sonderfaelle',
      value: String(workspaceRows.value.filter((row) => row.isProblem).length),
      note: readinessScope.value.winnerWarningsActive
        ? 'Clip, Tie oder Review brauchen Aufmerksamkeit'
        : readinessScope.value.phaseKey === 'voting'
          ? 'Reviews und Clip-Readiness, keine Gewinner-Warnung'
          : 'Für diese Phase bewusst reduziert',
      icon: AlertTriangle,
      tone: workspaceRows.value.some((row) => row.isProblem)
        ? 'border-amber-100 bg-amber-50 text-amber-800'
        : 'border-emerald-100 bg-emerald-50 text-emerald-800',
    },
  ])

  const statusFilters = computed(() => [
    { value: allFilter, label: 'Alle', count: workspaceRows.value.length },
    { value: 'issues', label: 'Prüfen', count: workspaceRows.value.filter((row) => row.isProblem).length },
    { value: 'ready', label: 'Bereit', count: workspaceRows.value.filter((row) => row.winnerReady).length },
    { value: 'winner', label: 'Gewinner gesetzt', count: workspaceRows.value.filter((row) => row.hasWinner).length },
    { value: 'idle', label: 'Noch ohne Votes', count: workspaceRows.value.filter((row) => row.voteCount === 0).length },
  ])

  function applyRouteFilters() {
    const rawQuery = Array.isArray(route.query.q) ? route.query.q[0] : route.query.q
    const rawStatus = Array.isArray(route.query.status) ? route.query.status[0] : route.query.status
    const rawGroup = Array.isArray(route.query.group) ? route.query.group[0] : route.query.group
    const rawCategoryId = Array.isArray(route.query.categoryId) ? route.query.categoryId[0] : route.query.categoryId
    const rawProblem = Array.isArray(route.query.problems) ? route.query.problems[0] : route.query.problems

    query.value = typeof rawQuery === 'string' ? rawQuery : ''
    statusFilter.value = statusFilters.value.some((option) => option.value === rawStatus) ? String(rawStatus) : allFilter
    problemOnly.value = rawProblem === '1' || rawProblem === 'true'
    selectedGroupName.value = typeof rawGroup === 'string' && rawGroup.trim() ? rawGroup : null

    const parsedCategoryId = Number(rawCategoryId)
    focusedCategoryId.value = Number.isFinite(parsedCategoryId) && parsedCategoryId > 0 ? parsedCategoryId : null
    if (!selectedGroupName.value && focusedCategoryId.value) {
      selectedGroupName.value = workspaceRows.value.find((row) => row.categoryId === focusedCategoryId.value)?.groupName ?? null
    }
  }

  watch(
    () => [route.query.q, route.query.status, route.query.group, route.query.categoryId, route.query.problems] as const,
    applyRouteFilters,
    { immediate: true },
  )

  watch(votingGroups, (groups) => {
    if (!groups.some((group) => group.name === selectedGroupName.value)) {
      selectedGroupName.value = groups[0]?.name ?? null
    }
  }, { immediate: true })

  watch(selectedGroup, (group) => {
    if (!group?.categories.some((row) => row.categoryId === focusedCategoryId.value)) {
      focusedCategoryId.value = group?.categories[0]?.categoryId ?? null
    }
  }, { immediate: true })

  function clearFilters() {
    query.value = ''
    statusFilter.value = allFilter
    problemOnly.value = false
  }

  function selectGroup(groupName: string) {
    selectedGroupName.value = groupName
    focusedCategoryId.value = votingGroups.value.find((group) => group.name === groupName)?.categories[0]?.categoryId ?? null
  }

  function focusCategory(categoryId: number) {
    focusedCategoryId.value = categoryId
    const match = workspaceRows.value.find((row) => row.categoryId === categoryId)
    if (match) {
      selectedGroupName.value = match.groupName
    }
  }

  return {
    problemOnly,
    query,
    statusFilter,
    statusFilters,
    summaryCards,
    seasonCandidates,
    votingGroups,
    selectedGroup,
    selectedGroupName,
    selectedCategory,
    focusedCategoryId,
    clearFilters,
    selectGroup,
    focusCategory,
  }
}
