import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useRef,
  useState,
  type ReactNode,
} from 'react'
import { applyDocumentFavicon } from '@meshkee/dashboard-core'
import { useLocale } from '@meshkee/dashboard-ui'
import { isAbortError } from '../lib/api'
import { getBusinessDomain } from '../lib/config'
import { BUSINESS_PROFILE_UPDATED_EVENT } from '../lib/businessContext'
import { getBusinessProfile } from '../services/businessProfileService'
import { resolveTenantByDomain } from '../services/tenantService'

interface TenantBrandingContextValue {
  businessName: string
  logoUrl: string | null
  faviconUrl: string | null
  refreshBranding: () => void
}

const TenantBrandingContext = createContext<TenantBrandingContextValue | null>(null)

function pickBusinessName(
  ...candidates: Array<string | null | undefined>
): string {
  for (const value of candidates) {
    const trimmed = value?.trim()
    if (trimmed) return trimmed
  }
  return ''
}

export function TenantBrandingProvider({ children }: { children: ReactNode }) {
  const { locale, setLocale } = useLocale()
  const [nameEn, setNameEn] = useState('')
  const [nameFa, setNameFa] = useState('')
  const [logoUrl, setLogoUrl] = useState<string | null>(null)
  const [faviconUrl, setFaviconUrl] = useState<string | null>(null)
  const [refreshToken, setRefreshToken] = useState(0)
  const defaultLocaleAppliedRef = useRef(false)

  const refreshBranding = useCallback(() => {
    setRefreshToken((value) => value + 1)
  }, [])

  useEffect(() => {
    const controller = new AbortController()
    const domain = getBusinessDomain()

    async function loadBranding() {
      try {
        const tenant = await resolveTenantByDomain(domain)
        if (controller.signal.aborted) return

        let nextNameEn = pickBusinessName(tenant.name, domain)
        let nextNameFa = pickBusinessName(tenant.nameFa, tenant.name, domain)
        let nextLogo = tenant.logoUrl?.trim() || null
        let nextFavicon =
          tenant.faviconUrl?.trim() || tenant.logoUrl?.trim() || null

        try {
          const profile = await getBusinessProfile(controller.signal)
          if (!controller.signal.aborted) {
            nextNameEn = pickBusinessName(
              profile.profile.nameEn,
              nextNameEn,
              domain,
            )
            nextNameFa = pickBusinessName(
              profile.profile.nameFa,
              profile.profile.nameEn,
              nextNameFa,
              domain,
            )
            nextLogo = profile.profile.logoUrl?.trim() || nextLogo
            nextFavicon =
              profile.profile.faviconUrl?.trim() ||
              profile.profile.logoUrl?.trim() ||
              nextFavicon
          }
        } catch (err) {
          if (!isAbortError(err)) {
            // Guest or unauthorized — tenant branding is enough.
          }
        }

        if (!controller.signal.aborted) {
          setNameEn(nextNameEn || domain)
          setNameFa(nextNameFa || nextNameEn || domain)
          setLogoUrl(nextLogo)
          setFaviconUrl(nextFavicon)
          applyDocumentFavicon(nextFavicon)
          if (!defaultLocaleAppliedRef.current) {
            defaultLocaleAppliedRef.current = true
            if (tenant.defaultLocale === 'en' || tenant.defaultLocale === 'fa') {
              setLocale(tenant.defaultLocale)
            } else {
              setLocale('fa')
            }
          }
        }
      } catch (err) {
        if (isAbortError(err) || controller.signal.aborted) return
        const domain = getBusinessDomain()
        setNameEn(domain)
        setNameFa(domain)
        setLogoUrl(null)
        setFaviconUrl(null)
        applyDocumentFavicon(null)
      }
    }

    void loadBranding()

    function handleProfileUpdated() {
      refreshBranding()
    }

    window.addEventListener(BUSINESS_PROFILE_UPDATED_EVENT, handleProfileUpdated)
    return () => {
      controller.abort()
      window.removeEventListener(BUSINESS_PROFILE_UPDATED_EVENT, handleProfileUpdated)
    }
  }, [refreshToken, refreshBranding, setLocale])

  const businessName = useMemo(() => {
    if (locale === 'fa') {
      return nameFa.trim() || nameEn.trim() || getBusinessDomain()
    }
    return nameEn.trim() || nameFa.trim() || getBusinessDomain()
  }, [locale, nameEn, nameFa])

  const value = useMemo(
    () => ({ businessName, logoUrl, faviconUrl, refreshBranding }),
    [businessName, logoUrl, faviconUrl, refreshBranding],
  )

  return (
    <TenantBrandingContext.Provider value={value}>{children}</TenantBrandingContext.Provider>
  )
}

export function useTenantBranding() {
  const context = useContext(TenantBrandingContext)
  if (!context) {
    throw new Error('useTenantBranding must be used within TenantBrandingProvider')
  }
  return context
}
