import { computed, ref } from 'vue'

import type { AdminArchivedWinnerItem, UpsertArchivedWinnerPayload } from '../../types/awards'
import { useAwardsStore } from '../../stores/awards'

interface ArchiveDraft {
  localKey: string
  id: number | null
  year: string
  category: string
  subcategory: string
  winnerName: string
  winnerUrl: string
  updatedAt: string | null
  isNew: boolean
  isSaving: boolean
  isDeleting: boolean
}

let draftCounter = 0

export function useAdminArchiveManager() {
  const store = useAwardsStore()
  const loading = ref(false)
  const adminError = ref('')
  const adminMessage = ref('')
  const drafts = ref<ArchiveDraft[]>([])

  const stats = computed(() => {
    const savedDrafts = drafts.value.filter((draft) => draft.id !== null)
    const years = new Set(savedDrafts.map((draft) => draft.year).filter((year) => year.trim().length > 0))
    const unsaved = drafts.value.filter((draft) => draft.isNew).length

    return [
      {
        label: 'Archiv-Einträge',
        value: `${savedDrafts.length}`,
        note: 'Gespeicherte Gewinner für die Landingpage',
      },
      {
        label: 'Jahre',
        value: `${years.size}`,
        note: 'Unabhängig vom aktiven Award-Jahr',
      },
      {
        label: 'Neue Zeilen',
        value: `${unsaved}`,
        note: unsaved > 0 ? 'Noch nicht gespeichert' : 'Alles ist gespeichert',
      },
    ]
  })

  const groupedDrafts = computed(() => {
    const groups = new Map<string, { key: string; label: string; sortYear: number; items: ArchiveDraft[] }>()

    for (const draft of [...drafts.value].sort(compareDrafts)) {
      const numericYear = Number.parseInt(draft.year, 10)
      const isValidYear = !draft.isNew && Number.isFinite(numericYear)
      const key = isValidYear ? `year-${numericYear}` : 'new'
      const existing = groups.get(key)

      if (existing) {
        existing.items.push(draft)
        continue
      }

      groups.set(key, {
        key,
        label: isValidYear ? String(numericYear) : 'Neu',
        sortYear: isValidYear ? numericYear : Number.MAX_SAFE_INTEGER,
        items: [draft],
      })
    }

    return [...groups.values()]
      .sort((left, right) => right.sortYear - left.sortYear)
  })

  async function loadArchivedWinners() {
    loading.value = true
    adminError.value = ''
    try {
      const entries = await store.loadAdminArchivedWinners()
      drafts.value = entries.map(createDraftFromItem)
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Das Archiv konnte nicht geladen werden.'
      drafts.value = []
    } finally {
      loading.value = false
    }
  }

  function addDraft() {
    drafts.value.unshift(createEmptyDraft())
  }

  async function saveDraft(localKey: string) {
    const draft = drafts.value.find((item) => item.localKey === localKey)
    if (!draft) return

    adminError.value = ''
    adminMessage.value = ''

    let payload: UpsertArchivedWinnerPayload
    try {
      payload = buildPayload(draft)
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Bitte alle Pflichtfelder prüfen.'
      return
    }

    draft.isSaving = true
    try {
      if (draft.id === null) {
        await store.createAdminArchivedWinner(payload)
        adminMessage.value = 'Archiv-Eintrag wurde angelegt.'
      } else {
        await store.updateAdminArchivedWinner(draft.id, payload)
        adminMessage.value = 'Archiv-Eintrag wurde gespeichert.'
      }

      drafts.value = store.adminArchivedWinners.map(createDraftFromItem)
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Der Archiv-Eintrag konnte nicht gespeichert werden.'
    } finally {
      draft.isSaving = false
    }
  }

  async function deleteDraft(localKey: string) {
    const draft = drafts.value.find((item) => item.localKey === localKey)
    if (!draft) return

    adminError.value = ''
    adminMessage.value = ''

    if (draft.id === null) {
      drafts.value = drafts.value.filter((item) => item.localKey !== localKey)
      return
    }

    if (typeof window !== 'undefined' && !window.confirm(`Archiv-Eintrag für ${draft.winnerName || draft.subcategory} wirklich löschen?`)) {
      return
    }

    draft.isDeleting = true
    try {
      await store.deleteAdminArchivedWinner(draft.id)
      drafts.value = store.adminArchivedWinners.map(createDraftFromItem)
      adminMessage.value = 'Archiv-Eintrag wurde gelöscht.'
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Der Archiv-Eintrag konnte nicht gelöscht werden.'
    } finally {
      draft.isDeleting = false
    }
  }

  return {
    loading,
    adminError,
    adminMessage,
    drafts,
    groupedDrafts,
    stats,
    loadArchivedWinners,
    addDraft,
    saveDraft,
    deleteDraft,
  }
}

function createDraftFromItem(item: AdminArchivedWinnerItem): ArchiveDraft {
  return {
    localKey: `saved-${item.id}`,
    id: item.id,
    year: String(item.year),
    category: item.category,
    subcategory: item.subcategory,
    winnerName: item.winnerName,
    winnerUrl: item.winnerUrl,
    updatedAt: item.updatedAt,
    isNew: false,
    isSaving: false,
    isDeleting: false,
  }
}

function createEmptyDraft(): ArchiveDraft {
  draftCounter += 1
  return {
    localKey: `new-${draftCounter}`,
    id: null,
    year: '',
    category: '',
    subcategory: '',
    winnerName: '',
    winnerUrl: '',
    updatedAt: null,
    isNew: true,
    isSaving: false,
    isDeleting: false,
  }
}

function buildPayload(draft: ArchiveDraft): UpsertArchivedWinnerPayload {
  const year = Number.parseInt(draft.year.trim(), 10)
  if (!Number.isFinite(year)) {
    throw new Error('Bitte ein gültiges Jahr eintragen.')
  }

  const category = draft.category.trim()
  const subcategory = draft.subcategory.trim()
  const winnerName = draft.winnerName.trim()
  const winnerUrl = draft.winnerUrl.trim()

  if (!category || !subcategory || !winnerName || !winnerUrl) {
    throw new Error('Jahr, Gewinner, Link, Kategorie und Unterkategorie sind Pflichtfelder.')
  }

  return {
    year,
    category,
    subcategory,
    winnerName,
    winnerUrl,
  }
}

function compareDrafts(left: ArchiveDraft, right: ArchiveDraft) {
  const leftYear = Number.parseInt(left.year, 10)
  const rightYear = Number.parseInt(right.year, 10)
  const normalizedLeftYear = Number.isFinite(leftYear) ? leftYear : Number.MAX_SAFE_INTEGER
  const normalizedRightYear = Number.isFinite(rightYear) ? rightYear : Number.MAX_SAFE_INTEGER

  if (normalizedLeftYear !== normalizedRightYear) {
    return normalizedRightYear - normalizedLeftYear
  }

  return [
    left.category,
    left.subcategory,
    left.winnerName,
  ].join('\u0000').localeCompare([
    right.category,
    right.subcategory,
    right.winnerName,
  ].join('\u0000'), 'de')
}
