import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
} from 'react'
import api from '../utils/api'
import { activeClubMemberships } from '../utils/activeClub'

const OrgInboxContext = createContext(null)

export function canAccessOrgInbox(user) {
  if (!user?.id) return false
  if (user.role === 'admin' || user.role === 'superadmin') return true
  return activeClubMemberships(user.clubs).some((c) => (c.roles || []).includes('club_admin'))
}

/** Gründungsanträge freigeben — aktuell nur Superadmin (platform.club_creation.approve). */
export function canAccessClubCreationInbox(user) {
  return user?.role === 'superadmin'
}

function canSeeContentReports(user) {
  if (user?.role === 'admin' || user?.role === 'superadmin') return true
  return activeClubMemberships(user?.clubs || []).some((c) => (c.roles || []).includes('club_admin'))
}

/** Nach Annahme/Ablehnung: Posteingang-Badges & Widget aktualisieren */
export function notifyOrgInboxChanged() {
  window.dispatchEvent(new Event('shinkan:inbox-changed'))
}

/** Eine konsistente Ladepfad-Logik für Join-Requests + Content-Reports (ein Codepfad für Mount + refresh). */
async function fetchOrgInboxSnapshot(canAccess, canAccessReports, canAccessClubCreation) {
  const out = {
    items: [],
    clubCreationRequests: [],
    contentReports: [],
    contentReportsError: null,
  }
  if (canAccess) {
    try {
      const data = await api.getInboxJoinRequests()
      out.items = Array.isArray(data) ? data : []
    } catch {
      out.items = []
    }
  }
  if (canAccessClubCreation) {
    try {
      const data = await api.listAdminClubCreationRequests()
      out.clubCreationRequests = Array.isArray(data) ? data : []
    } catch {
      out.clubCreationRequests = []
    }
  }
  if (canAccessReports) {
    try {
      const data = await api.getInboxContentReports()
      out.contentReports = Array.isArray(data) ? data : []
    } catch (err) {
      out.contentReports = []
      out.contentReportsError = err?.message || String(err)
    }
  }
  return out
}

export function OrgInboxProvider({ user, children }) {
  const [items, setItems] = useState([])
  const [clubCreationRequests, setClubCreationRequests] = useState([])
  const [contentReports, setContentReports] = useState([])
  const [contentReportsError, setContentReportsError] = useState(null)
  const canAccess = useMemo(() => canAccessOrgInbox(user), [user])
  const canAccessReports = useMemo(() => canSeeContentReports(user), [user])
  const canAccessClubCreation = useMemo(() => canAccessClubCreationInbox(user), [user])
  const hasInboxAccess = canAccess || canAccessReports || canAccessClubCreation

  const refresh = useCallback(async () => {
    if (!hasInboxAccess) {
      setItems([])
      setClubCreationRequests([])
      setContentReports([])
      setContentReportsError(null)
      return
    }
    const snap = await fetchOrgInboxSnapshot(canAccess, canAccessReports, canAccessClubCreation)
    setItems(snap.items)
    setClubCreationRequests(snap.clubCreationRequests)
    setContentReports(snap.contentReports)
    setContentReportsError(canAccessReports ? snap.contentReportsError : null)
  }, [hasInboxAccess, canAccess, canAccessReports, canAccessClubCreation])

  useEffect(() => {
    if (!hasInboxAccess) {
      setItems([])
      setClubCreationRequests([])
      setContentReports([])
      setContentReportsError(null)
      return undefined
    }
    let cancelled = false
    let idleId = null
    let timeoutId = null

    const load = async () => {
      const snap = await fetchOrgInboxSnapshot(canAccess, canAccessReports, canAccessClubCreation)
      if (cancelled) return
      setItems(snap.items)
      setClubCreationRequests(snap.clubCreationRequests)
      setContentReports(snap.contentReports)
      setContentReportsError(canAccessReports ? snap.contentReportsError : null)
    }

    const schedule = () => {
      if (cancelled) return
      if (typeof window.requestIdleCallback === 'function') {
        idleId = window.requestIdleCallback(
          () => {
            idleId = null
            void load()
          },
          { timeout: 1500 },
        )
      } else {
        timeoutId = window.setTimeout(() => {
          timeoutId = null
          void load()
        }, 0)
      }
    }

    schedule()

    return () => {
      cancelled = true
      if (idleId != null && typeof window.cancelIdleCallback === 'function') {
        window.cancelIdleCallback(idleId)
      }
      if (timeoutId != null) window.clearTimeout(timeoutId)
    }
  }, [hasInboxAccess, canAccess, canAccessReports, canAccessClubCreation, user?.id])

  useEffect(() => {
    const onChange = () => { refresh() }
    window.addEventListener('shinkan:inbox-changed', onChange)
    return () => window.removeEventListener('shinkan:inbox-changed', onChange)
  }, [refresh])

  const clubCreationCount = clubCreationRequests.length
  const joinCount = items.length

  const value = useMemo(
    () => ({
      inboxJoinRequests: items,
      inboxClubCreationRequests: clubCreationRequests,
      clubCreationRequestCount: clubCreationCount,
      inboxCount: joinCount + clubCreationCount,
      contentReports,
      contentReportCount: contentReports.filter((r) => r.status === 'submitted').length,
      contentReportsError,
      refreshOrgInbox: refresh,
      canAccessOrgInbox: canAccess,
      canAccessContentReports: canAccessReports,
      canAccessClubCreationInbox: canAccessClubCreation,
      canShowInboxNav: hasInboxAccess,
      isSuperadmin: user?.role === 'superadmin',
      isPlatformAdmin: user?.role === 'admin' || user?.role === 'superadmin',
      isClubAdmin: activeClubMemberships(user?.clubs || []).some((c) => (c.roles || []).includes('club_admin')),
    }),
    [
      items,
      clubCreationRequests,
      clubCreationCount,
      joinCount,
      contentReports,
      contentReportsError,
      refresh,
      canAccess,
      canAccessReports,
      canAccessClubCreation,
      hasInboxAccess,
      user?.role,
      user?.clubs,
    ]
  )

  return <OrgInboxContext.Provider value={value}>{children}</OrgInboxContext.Provider>
}

export function useOrgInbox() {
  const ctx = useContext(OrgInboxContext)
  if (!ctx) {
    throw new Error('useOrgInbox must be used within OrgInboxProvider')
  }
  return ctx
}
