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

import { useAwardsStore } from '../../stores/awards'
import type { AdminRiskFlag, AdminRiskRule } from '../../types/awards'

export type RiskResolutionStatus = 'open' | 'resolved' | 'dismissed'

export interface RiskMetadataItem {
  key: string
  value: string
}

type SeverityFilter = 'all' | 'high' | 'medium' | 'low'
type HistoryStatusFilter = 'all' | 'resolved' | 'dismissed'
const QUEUE_PAGE_SIZE = 12
const HISTORY_PAGE_SIZE = 10

export function riskSeverityClass(severity: string) {
  const normalized = severity.toLowerCase()
  if (normalized === 'high') return 'border-rose-200 bg-rose-50 text-rose-700'
  if (normalized === 'medium') return 'border-amber-200 bg-amber-50 text-amber-700'
  if (normalized === 'low') return 'border-sky-200 bg-sky-50 text-sky-700'
  return 'border-slate-200 bg-slate-50 text-slate-600'
}

export function riskStatusLabel(status: string) {
  if (status === 'resolved') return 'Erledigt'
  if (status === 'dismissed') return 'Verworfen'
  if (status === 'open') return 'Offen'
  return status
}

export function riskAgeLabel(flag: AdminRiskFlag) {
  const createdAt = new Date(flag.createdAt)
  if (Number.isNaN(createdAt.getTime())) return 'unbekannt'

  const diffMinutes = Math.max(0, Math.round((Date.now() - createdAt.getTime()) / 60000))
  if (diffMinutes < 60) return `${diffMinutes} min`

  const diffHours = Math.round(diffMinutes / 60)
  if (diffHours < 48) return `${diffHours} Std.`

  return `${Math.round(diffHours / 24)} Tage`
}

export function useAdminRiskManager() {
  const store = useAwardsStore()
  const riskSaving = ref<number | null>(null)
  const riskLoading = ref(false)
  const adminMessage = ref('')
  const adminError = ref('')
  const riskFilter = ref('')
  const severityFilter = ref<SeverityFilter>('all')
  const historyStatusFilter = ref<HistoryStatusFilter>('all')
  const selectedRiskFlagId = ref<number | null>(null)
  const selectedDecisionNote = ref('')
  const queuePage = ref(1)
  const historyPage = ref(1)
  const selectedBulkRiskFlagIds = ref<number[]>([])
  const bulkReviewNote = ref('')
  const bulkSaving = ref(false)
  const riskRules = ref<AdminRiskRule[]>([])
  const riskRulesLoading = ref(false)
  const riskRulesSaving = ref(false)
  const queuePageSize = QUEUE_PAGE_SIZE
  const historyPageSize = HISTORY_PAGE_SIZE

  const riskFlags = computed(() => store.admin.riskFlags)
  const riskHistory = computed(() => store.adminRiskHistory)
  const riskLoadedLabel = computed(() => {
    const total = store.adminRiskFlagsPage.totalCount
    return total > 0 ? createPageLabel(store.adminRiskFlagsPage.offset, store.adminRiskFlagsPage.returnedCount, total) : 'keine offenen Hinweise'
  })
  const queuePageLabel = computed(() =>
    createPageLabel(store.adminRiskFlagsPage.offset, store.adminRiskFlagsPage.returnedCount, store.adminRiskFlagsPage.totalCount),
  )
  const queueHasPrevious = computed(() => queuePage.value > 1)
  const queueHasMore = computed(() => store.adminRiskFlagsPage.hasMore)
  const historyPageLabel = computed(() =>
    createPageLabel(store.adminRiskHistoryPage.offset, store.adminRiskHistoryPage.returnedCount, store.adminRiskHistoryPage.totalCount),
  )
  const historyHasPrevious = computed(() => historyPage.value > 1)
  const historyHasMore = computed(() => store.adminRiskHistoryPage.hasMore)

  const filteredRiskFlags = computed(() => riskFlags.value)
  const selectedRiskFlag = computed(() =>
    filteredRiskFlags.value.find((flag) => flag.id === selectedRiskFlagId.value) ?? filteredRiskFlags.value[0] ?? null,
  )
  const selectedRiskMetadata = computed<RiskMetadataItem[]>(() => parseRiskMetadata(selectedRiskFlag.value?.metadataJson))
  const selectedDecisionNoteLength = computed(() => selectedDecisionNote.value.trim().length)
  const selectedDecisionReady = computed(() => selectedDecisionNoteLength.value >= 3 && selectedDecisionNoteLength.value <= 500)
  const canBulkResolve = computed(() =>
    selectedBulkRiskFlagIds.value.length > 0 &&
    bulkReviewNote.value.trim().length >= 3 &&
    bulkReviewNote.value.trim().length <= 500,
  )

  const riskStats = computed(() => {
    const highCount = countFor(store.adminRiskFlagsPage.severityCounts, 'high')
    const uniqueUsers = new Set(riskFlags.value.map((flag) => flag.twitchUserId).filter(Boolean)).size
    return [
      { label: 'Offen', value: store.adminRiskFlagsPage.totalCount, tone: store.adminRiskFlagsPage.totalCount > 0 ? 'warning' : 'ok' },
      { label: 'High', value: highCount, tone: highCount > 0 ? 'danger' : 'ok' },
      { label: 'Medium', value: countFor(store.adminRiskFlagsPage.severityCounts, 'medium'), tone: 'warning' },
      { label: 'User betroffen', value: uniqueUsers, tone: 'neutral' },
    ]
  })
  const severityFilters = computed(() => [
    { key: 'all' as const, label: 'Alle', count: store.adminRiskFlagsPage.totalCount },
    { key: 'high' as const, label: 'High', count: countFor(store.adminRiskFlagsPage.severityCounts, 'high') },
    { key: 'medium' as const, label: 'Medium', count: countFor(store.adminRiskFlagsPage.severityCounts, 'medium') },
    { key: 'low' as const, label: 'Low', count: countFor(store.adminRiskFlagsPage.severityCounts, 'low') },
  ])

  const recentRiskHistory = computed(() => riskHistory.value)
  const riskHistoryStats = computed(() => [
    { label: 'Entschieden', value: store.adminRiskHistoryPage.totalCount },
    { label: 'Erledigt', value: countFor(store.adminRiskHistoryPage.statusCounts, 'resolved') },
    { label: 'Verworfen', value: countFor(store.adminRiskHistoryPage.statusCounts, 'dismissed') },
  ])
  const historyStatusFilters = computed(() => [
    { key: 'all' as const, label: 'Alle', count: store.adminRiskHistoryPage.totalCount },
    { key: 'resolved' as const, label: 'Erledigt', count: countFor(store.adminRiskHistoryPage.statusCounts, 'resolved') },
    { key: 'dismissed' as const, label: 'Verworfen', count: countFor(store.adminRiskHistoryPage.statusCounts, 'dismissed') },
  ])

  async function loadRiskFlags() {
    riskLoading.value = true
    adminError.value = ''

    try {
      const query = riskFilter.value.trim()
      await Promise.all([
        store.loadAdminRiskFlagsPage({
          limit: queuePageSize,
          offset: (queuePage.value - 1) * queuePageSize,
          status: 'open',
          severity: severityFilter.value === 'all' ? undefined : severityFilter.value,
          query,
        }),
        store.loadAdminRiskHistoryPage({
          limit: historyPageSize,
          offset: (historyPage.value - 1) * historyPageSize,
          status: historyStatusFilter.value,
          reviewedOnly: true,
          query,
        }),
      ])
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Risikohinweise konnten nicht geladen werden.'
    } finally {
      riskLoading.value = false
    }
  }

  async function setQueuePage(page: number) {
    queuePage.value = Math.max(1, page)
    selectedBulkRiskFlagIds.value = []
    await loadRiskFlags()
  }

  async function setHistoryPage(page: number) {
    historyPage.value = Math.max(1, page)
    await loadRiskFlags()
  }

  async function updateRiskFlagStatus(riskFlagId: number, status: RiskResolutionStatus) {
    if (riskSaving.value) return
    if (status !== 'open' && !selectedDecisionReady.value) {
      adminError.value = 'Bitte notiere kurz, warum du diesen Hinweis entscheidest.'
      return
    }

    riskSaving.value = riskFlagId
    adminMessage.value = ''
    adminError.value = ''

    try {
      const reviewNote = status === 'open' ? 'Wieder geöffnet.' : selectedDecisionNote.value.trim()
      await store.resolveRiskFlag(riskFlagId, { status, reviewNote })
      selectedDecisionNote.value = ''
      await loadRiskFlags()
      adminMessage.value = `Risikohinweis ${riskFlagId} wurde aktualisiert.`
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Risikohinweis konnte nicht aktualisiert werden.'
    } finally {
      riskSaving.value = null
    }
  }

  function toggleBulkRiskFlag(riskFlagId: number) {
    const flag = filteredRiskFlags.value.find((item) => item.id === riskFlagId)
    if (!flag || flag.severity.toLowerCase() !== 'low') return

    selectedBulkRiskFlagIds.value = selectedBulkRiskFlagIds.value.includes(riskFlagId)
      ? selectedBulkRiskFlagIds.value.filter((id) => id !== riskFlagId)
      : [...selectedBulkRiskFlagIds.value, riskFlagId]
  }

  function selectVisibleLowRiskFlags() {
    selectedBulkRiskFlagIds.value = filteredRiskFlags.value
      .filter((flag) => flag.severity.toLowerCase() === 'low')
      .map((flag) => flag.id)
  }

  function clearBulkSelection() {
    selectedBulkRiskFlagIds.value = []
    bulkReviewNote.value = ''
  }

  async function bulkResolveRiskFlags(status: Exclude<RiskResolutionStatus, 'open'>) {
    if (!canBulkResolve.value || bulkSaving.value) return

    bulkSaving.value = true
    adminMessage.value = ''
    adminError.value = ''

    try {
      await store.bulkResolveRiskFlags({
        riskFlagIds: selectedBulkRiskFlagIds.value,
        status,
        reviewNote: bulkReviewNote.value.trim(),
      })
      adminMessage.value = `${selectedBulkRiskFlagIds.value.length} Risikohinweise wurden aktualisiert.`
      clearBulkSelection()
      await loadRiskFlags()
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Bulk-Entscheidung konnte nicht gespeichert werden.'
    } finally {
      bulkSaving.value = false
    }
  }

  function updateRiskRule(ruleKey: string, patch: Partial<AdminRiskRule>) {
    riskRules.value = riskRules.value.map((rule) =>
      rule.key === ruleKey ? { ...rule, ...patch } : rule,
    )
  }

  async function saveRiskRules() {
    riskRulesSaving.value = true
    adminMessage.value = ''
    adminError.value = ''

    try {
      const response = await store.updateAdminRiskRules({ rules: riskRules.value })
      riskRules.value = response.rules
      adminMessage.value = 'Risk-Regeln wurden gespeichert.'
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Risk-Regeln konnten nicht gespeichert werden.'
    } finally {
      riskRulesSaving.value = false
    }
  }

  async function loadRiskRules() {
    riskRulesLoading.value = true
    try {
      const response = await store.loadAdminRiskRules()
      riskRules.value = response.rules
    } catch (error) {
      adminError.value = error instanceof Error ? error.message : 'Risk-Regeln konnten nicht geladen werden.'
    } finally {
      riskRulesLoading.value = false
    }
  }

  watch(filteredRiskFlags, (flags) => {
    if (!flags.some((flag) => flag.id === selectedRiskFlagId.value)) {
      selectedRiskFlagId.value = flags[0]?.id ?? null
    }
  }, { immediate: true })
  watch(selectedRiskFlag, (flag) => {
    selectedDecisionNote.value = flag?.reviewNote ?? ''
  })
  let filterReloadTimer: number | undefined
  watch([riskFilter, severityFilter, historyStatusFilter], () => {
    queuePage.value = 1
    historyPage.value = 1
    window.clearTimeout(filterReloadTimer)
    filterReloadTimer = window.setTimeout(() => {
      void loadRiskFlags()
    }, 250)
  })

  onMounted(() => {
    void loadRiskFlags()
    void loadRiskRules()
  })

  return {
    riskSaving,
    riskLoading,
    adminMessage,
    adminError,
    riskFilter,
    severityFilter,
    historyStatusFilter,
    selectedRiskFlagId,
    selectedDecisionNote,
    selectedDecisionNoteLength,
    selectedDecisionReady,
    queuePage,
    queuePageLabel,
    queueHasPrevious,
    queueHasMore,
    historyPage,
    historyPageLabel,
    historyHasPrevious,
    historyHasMore,
    selectedBulkRiskFlagIds,
    bulkReviewNote,
    bulkSaving,
    canBulkResolve,
    riskRules,
    riskRulesLoading,
    riskRulesSaving,
    riskFlags,
    riskHistory,
    filteredRiskFlags,
    selectedRiskFlag,
    selectedRiskMetadata,
    riskStats,
    riskHistoryStats,
    recentRiskHistory,
    severityFilters,
    historyStatusFilters,
    riskLoadedLabel,
    loadRiskFlags,
    updateRiskFlagStatus,
    setQueuePage,
    setHistoryPage,
    toggleBulkRiskFlag,
    selectVisibleLowRiskFlags,
    clearBulkSelection,
    bulkResolveRiskFlags,
    updateRiskRule,
    saveRiskRules,
  }
}

function countFor(counts: Array<{ key: string; count: number }>, key: string) {
  return counts.find((item) => item.key === key)?.count ?? 0
}

function createPageLabel(offset: number, returnedCount: number, totalCount: number) {
  if (totalCount === 0) return '0 Treffer'

  const start = offset + 1
  const end = offset + returnedCount
  return `${start}-${end} / ${totalCount}`
}

function parseRiskMetadata(metadataJson: string | undefined) {
  if (!metadataJson) return []

  try {
    const parsed = JSON.parse(metadataJson) as Record<string, unknown>
    return Object.entries(parsed)
      .filter(([key]) => key !== 'entityLinks')
      .map(([key, value]) => ({
        key,
        value: typeof value === 'string' ? value : JSON.stringify(value),
      }))
  } catch {
    return [{ key: 'raw', value: metadataJson }]
  }
}
