import { computed, reactive, ref, watch } from 'vue'

import { SOCIAL_ICON_OPTIONS, socialIconOptionForValue } from '../../lib/socialIcons'
import { useAwardsStore } from '../../stores/awards'
import type { AdminCandidateItem } from '../../types/awards'

interface CandidateForm {
  categoryId: number
  displayName: string
  channelSlug: string
  platform: string
}

const pageSize = 10

export function useAdminCandidateManager() {
  const store = useAwardsStore()
  const saving = ref(false)
  const deleting = ref(false)
  const adminMessage = ref('')
  const adminError = ref('')
  const search = ref('')
  const categoryFilter = ref<number | null>(null)
  const page = ref(1)
  const modalOpen = ref(false)
  const editingId = ref<number | 'new' | null>(null)
  const candidateToDelete = ref<AdminCandidateItem | null>(null)
  const form = reactive<CandidateForm>({ categoryId: 0, displayName: '', channelSlug: '', platform: 'Twitch' })

  const seasonDetail = computed(() => store.adminSeasonDetail)
  const selectedSeasonId = computed(() => store.adminSelectedSeasonId)
  const categoryOptions = computed(() =>
    seasonDetail.value.categories.map((category) => ({ label: `${category.groupName} · ${category.name}`, value: category.id })),
  )
  const categoryFilterOptions = computed(() => [{ label: 'Alle Kategorien', value: null }, ...categoryOptions.value])
  const categoryLabelMap = computed<Record<number, string>>(() =>
    Object.fromEntries(seasonDetail.value.categories.map((category) => [category.id, `${category.groupName} · ${category.name}`])),
  )
  const duplicateCandidateKeys = computed(() => {
    const counts = new Map<string, number>()
    for (const candidate of seasonDetail.value.candidates) {
      const nameKey = createCandidateDuplicateKey(candidate, 'name')
      const slugKey = createCandidateDuplicateKey(candidate, 'slug')
      counts.set(nameKey, (counts.get(nameKey) ?? 0) + 1)
      if (candidate.channelSlug.trim()) {
        counts.set(slugKey, (counts.get(slugKey) ?? 0) + 1)
      }
    }
    return counts
  })
  const duplicateCandidateCount = computed(() =>
    seasonDetail.value.candidates.filter((candidate) => hasDuplicateCandidateKey(candidate, duplicateCandidateKeys.value)).length,
  )
  const filteredCandidates = computed(() => {
    const query = search.value.trim().toLowerCase()
    let list = seasonDetail.value.candidates

    if (categoryFilter.value) {
      list = list.filter((candidate) => candidate.categoryId === categoryFilter.value)
    }

    if (query) {
      list = list.filter((candidate) =>
        [candidate.displayName, candidate.channelSlug, candidate.platform, categoryLabelMap.value[candidate.categoryId] ?? '']
          .join(' ')
          .toLowerCase()
          .includes(query),
      )
    }

    return list
  })
  const totalPages = computed(() => Math.max(1, Math.ceil(filteredCandidates.value.length / pageSize)))
  const pagedCandidates = computed(() => {
    const start = (page.value - 1) * pageSize
    return filteredCandidates.value.slice(start, start + pageSize)
  })
  const rangeStart = computed(() => (filteredCandidates.value.length === 0 ? 0 : (page.value - 1) * pageSize + 1))
  const rangeEnd = computed(() => Math.min(page.value * pageSize, filteredCandidates.value.length))
  const modalTitle = computed(() => (editingId.value === 'new' ? 'Kandidat anlegen' : 'Kandidat bearbeiten'))
  const canSave = computed(() =>
    Boolean(selectedSeasonId.value && form.categoryId && form.displayName.trim() && form.channelSlug.trim() && form.platform.trim()),
  )
  const candidatePlatformOptions = computed(() => SOCIAL_ICON_OPTIONS.filter((option) => option.key !== 'website'))
  const selectedPlatformValue = computed(() => socialIconOptionForValue(form.platform)?.key ?? 'custom')

  watch([search, categoryFilter, () => seasonDetail.value.candidates.length], () => {
    page.value = 1
  })

  watch(totalPages, (max) => {
    if (page.value > max) {
      page.value = max
    }
  })

  function clearFilters() {
    search.value = ''
    categoryFilter.value = null
  }

  function openCreate() {
    adminMessage.value = ''
    adminError.value = ''
    editingId.value = 'new'
    form.categoryId = categoryFilter.value ?? seasonDetail.value.categories[0]?.id ?? 0
    form.displayName = ''
    form.channelSlug = ''
    form.platform = 'Twitch'
    modalOpen.value = true
  }

  function openEdit(candidate: AdminCandidateItem) {
    adminMessage.value = ''
    adminError.value = ''
    editingId.value = candidate.id
    form.categoryId = candidate.categoryId
    form.displayName = candidate.displayName
    form.channelSlug = candidate.channelSlug
    form.platform = candidate.platform
    modalOpen.value = true
  }

  function handlePlatformSelection(value: string) {
    if (value === 'custom') {
      if (socialIconOptionForValue(form.platform)) {
        form.platform = ''
      }
      return
    }

    const option = socialIconOptionForValue(value)
    form.platform = option?.label ?? value
  }

  async function saveModal() {
    if (!canSave.value || !selectedSeasonId.value) {
      return
    }

    saving.value = true
    adminError.value = ''

    try {
      if (editingId.value === 'new') {
        await store.createAdminCandidate(selectedSeasonId.value, { ...form })
        adminMessage.value = `„${form.displayName}" wurde angelegt.`
      } else if (typeof editingId.value === 'number') {
        await store.updateAdminCandidate(editingId.value, selectedSeasonId.value, { ...form })
        adminMessage.value = `„${form.displayName}" wurde gespeichert.`
      }
      modalOpen.value = false
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Speichern fehlgeschlagen.'
    } finally {
      saving.value = false
    }
  }

  async function confirmDelete() {
    if (!candidateToDelete.value || !selectedSeasonId.value) {
      return
    }

    deleting.value = true
    adminError.value = ''

    try {
      await store.deleteAdminCandidate(candidateToDelete.value.id, selectedSeasonId.value)
      adminMessage.value = `„${candidateToDelete.value.displayName}" wurde gelöscht.`
      candidateToDelete.value = null
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Löschen fehlgeschlagen.'
    } finally {
      deleting.value = false
    }
  }

  return {
    seasonDetail,
    saving,
    deleting,
    adminMessage,
    adminError,
    search,
    categoryFilter,
    page,
    categoryOptions,
    categoryFilterOptions,
    categoryLabelMap,
    duplicateCandidateKeys,
    duplicateCandidateCount,
    filteredCandidates,
    pagedCandidates,
    totalPages,
    rangeStart,
    rangeEnd,
    modalOpen,
    form,
    modalTitle,
    canSave,
    candidatePlatformOptions,
    selectedPlatformValue,
    candidateToDelete,
    clearFilters,
    openCreate,
    openEdit,
    handlePlatformSelection,
    saveModal,
    confirmDelete,
  }
}

function createCandidateDuplicateKey(candidate: AdminCandidateItem, field: 'name' | 'slug') {
  const value = field === 'name' ? candidate.displayName : candidate.channelSlug
  return `${candidate.categoryId}:${field}:${value.trim().toLowerCase()}`
}

function hasDuplicateCandidateKey(candidate: AdminCandidateItem, candidateKeys: Map<string, number>) {
  return (candidateKeys.get(createCandidateDuplicateKey(candidate, 'name')) ?? 0) > 1
    || (candidateKeys.get(createCandidateDuplicateKey(candidate, 'slug')) ?? 0) > 1
}
