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

import { useAwardsStore } from '../../stores/awards'
import type { AdminCategoryItem } from '../../types/awards'

type CategoryStatusFilter = 'all' | 'empty' | 'reviews' | 'thin'

interface CategoryForm {
  groupName: string
  name: string
  slug: string
  description: string
  sortOrder: number
  maxNomineesPerUser: number
}

export function useAdminCategoryManager() {
  const store = useAwardsStore()
  const selectedSeasonId = computed(() => store.adminSelectedSeasonId)
  const seasonDetail = computed(() => store.adminSeasonDetail)
  const query = ref('')
  const statusFilter = ref<CategoryStatusFilter>('all')
  const selectedCategoryId = ref<number | null>(null)
  const saving = ref<number | 'new' | null>(null)
  const adminMessage = ref('')
  const adminError = ref('')
  const categoryToDelete = ref<AdminCategoryItem | null>(null)
  const deleting = ref(false)

  const editForms = reactive<Record<number, CategoryForm>>({})
  const newCategoryForm = reactive(createEmptyCategoryForm())

  const categoriesWithState = computed(() =>
    seasonDetail.value.categories
      .map((category) => ({
        ...category,
        pending: seasonDetail.value.pendingNominations.filter((nomination) => nomination.categoryId === category.id).length,
        candidates: seasonDetail.value.candidates.filter((candidate) => candidate.categoryId === category.id).length,
      }))
      .sort((a, b) => a.sortOrder - b.sortOrder),
  )
  const filteredCategories = computed(() => {
    const search = query.value.trim().toLowerCase()
    return categoriesWithState.value.filter((category) => {
      const matchesStatus =
        statusFilter.value === 'all' ||
        (statusFilter.value === 'empty' && category.candidates === 0) ||
        (statusFilter.value === 'reviews' && category.pending > 0) ||
        (statusFilter.value === 'thin' && category.candidates > 0 && category.candidates < Math.max(2, category.maxNomineesPerUser))
      const matchesSearch = !search || [category.groupName, category.name, category.slug, category.description]
        .join(' ')
        .toLowerCase()
        .includes(search)
      return matchesStatus && matchesSearch
    })
  })
  const selectedCategory = computed(() =>
    filteredCategories.value.find((category) => category.id === selectedCategoryId.value) ?? filteredCategories.value[0] ?? null,
  )
  const categoryStats = computed(() => [
    { label: 'Kategorien', value: seasonDetail.value.categories.length },
    { label: 'Kandidaten', value: seasonDetail.value.candidates.length },
    { label: 'Reviews', value: seasonDetail.value.pendingNominations.length },
  ])
  const statusFilters = computed(() => [
    { key: 'all' as const, label: 'Alle', count: categoriesWithState.value.length },
    { key: 'empty' as const, label: 'Ohne Kandidaten', count: categoriesWithState.value.filter((category) => category.candidates === 0).length },
    { key: 'reviews' as const, label: 'Mit Reviews', count: categoriesWithState.value.filter((category) => category.pending > 0).length },
    { key: 'thin' as const, label: 'Dünn besetzt', count: categoriesWithState.value.filter((category) => category.candidates > 0 && category.candidates < Math.max(2, category.maxNomineesPerUser)).length },
  ])

  watch(
    seasonDetail,
    (detail) => {
      for (const category of detail.categories) {
        editForms[category.id] = createCategoryForm(category)
      }
      newCategoryForm.sortOrder = detail.categories.length + 1
      if (!detail.categories.some((category) => category.id === selectedCategoryId.value)) {
        selectedCategoryId.value = detail.categories[0]?.id ?? null
      }
    },
    { immediate: true },
  )

  watch(filteredCategories, (categories) => {
    if (!categories.some((category) => category.id === selectedCategoryId.value)) {
      selectedCategoryId.value = categories[0]?.id ?? null
    }
  })

  async function saveCategory(categoryId: number) {
    if (!selectedSeasonId.value) return
    saving.value = categoryId
    adminMessage.value = ''
    adminError.value = ''
    try {
      await store.updateAdminCategory(categoryId, selectedSeasonId.value, editForms[categoryId])
      adminMessage.value = 'Kategorie gespeichert.'
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Kategorie konnte nicht gespeichert werden.'
    } finally {
      saving.value = null
    }
  }

  async function createCategory() {
    if (!selectedSeasonId.value) return
    saving.value = 'new'
    adminMessage.value = ''
    adminError.value = ''
    try {
      await store.createAdminCategory(selectedSeasonId.value, newCategoryForm)
      adminMessage.value = 'Kategorie angelegt.'
      Object.assign(newCategoryForm, createEmptyCategoryForm(seasonDetail.value.categories.length + 1))
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Kategorie konnte nicht angelegt werden.'
    } finally {
      saving.value = null
    }
  }

  function fillNewSlug() {
    newCategoryForm.slug = slugify(newCategoryForm.name)
  }

  async function confirmDeleteCategory() {
    if (!categoryToDelete.value || !selectedSeasonId.value) return
    deleting.value = true
    adminError.value = ''
    try {
      await store.deleteAdminCategory(categoryToDelete.value.id, selectedSeasonId.value)
      adminMessage.value = `Kategorie „${categoryToDelete.value.name}" wurde gelöscht.`
      categoryToDelete.value = null
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Löschen fehlgeschlagen.'
    } finally {
      deleting.value = false
    }
  }

  return {
    selectedSeasonId,
    query,
    statusFilter,
    selectedCategoryId,
    saving,
    adminMessage,
    adminError,
    editForms,
    newCategoryForm,
    filteredCategories,
    selectedCategory,
    categoryStats,
    statusFilters,
    categoryToDelete,
    deleting,
    saveCategory,
    createCategory,
    fillNewSlug,
    confirmDeleteCategory,
  }
}

function createCategoryForm(category: AdminCategoryItem): CategoryForm
function createCategoryForm(category?: AdminCategoryItem, sortOrder?: number): CategoryForm
function createCategoryForm(category?: AdminCategoryItem, sortOrder = 1): CategoryForm {
  return {
    groupName: category?.groupName ?? '',
    name: category?.name ?? '',
    slug: category?.slug ?? '',
    description: category?.description ?? '',
    sortOrder: category?.sortOrder ?? sortOrder,
    maxNomineesPerUser: category?.maxNomineesPerUser ?? 3,
  }
}

function createEmptyCategoryForm(sortOrder = 1): CategoryForm {
  return createCategoryForm(undefined, sortOrder)
}

function slugify(value: string) {
  return value
    .trim()
    .toLowerCase()
    .normalize('NFD')
    .replace(/[\u0300-\u036f]/g, '')
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '')
}
