/**
 * UpgradeModalProvider + useUpgradeModal — upgrade-upsell-modal (spec 36).
 *
 * Global context that controls the upgrade modal. Mount once at the app root
 * (inside QueryClientProvider + LocaleProvider so role/tier/subscription reads work).
 * The provider renders <UpgradeModal /> as its last child — it is always mounted
 * and rendered into a Radix Portal, unaffected by nesting z-index.
 */
import React, {
  createContext,
  useCallback,
  useContext,
  useState,
  type ReactNode,
} from 'react'
import { TenantTier } from '@zync/types'
import { UpgradeModal } from './UpgradeModal'

// ---------------------------------------------------------------------------
// Public types
// ---------------------------------------------------------------------------

export interface UpgradeModalOpts {
  /**
   * Human-readable feature name shown as a context line at the top of the modal.
   * e.g. "AI Assistant", "Custom Domain", "API Access".
   * When omitted, the context line is not shown.
   */
  featureName?: string
  /**
   * Pre-select a tier card. Defaults to the next tier above the tenant's current
   * tier (nextTierAbove(currentTier)).
   */
  targetTier?: TenantTier
}

export interface UpgradeModalState {
  isOpen: boolean
  opts: UpgradeModalOpts | null
}

export interface UpgradeModalContextValue {
  state: UpgradeModalState
  open(opts?: UpgradeModalOpts): void
  close(): void
}

// ---------------------------------------------------------------------------
// Context
// ---------------------------------------------------------------------------

const UpgradeModalContext = createContext<UpgradeModalContextValue | null>(null)

// ---------------------------------------------------------------------------
// Provider
// ---------------------------------------------------------------------------

export function UpgradeModalProvider({ children }: { children: ReactNode }): React.JSX.Element {
  const [state, setState] = useState<UpgradeModalState>({ isOpen: false, opts: null })

  const open = useCallback((opts?: UpgradeModalOpts) => {
    setState({ isOpen: true, opts: opts ?? null })
  }, [])

  const close = useCallback(() => {
    setState({ isOpen: false, opts: null })
  }, [])

  return (
    <UpgradeModalContext.Provider value={{ state, open, close }}>
      {children}
      <UpgradeModal />
    </UpgradeModalContext.Provider>
  )
}

// ---------------------------------------------------------------------------
// Hook
// ---------------------------------------------------------------------------

/**
 * Access the upgrade modal controls from anywhere inside `UpgradeModalProvider`.
 * Throws a descriptive error when called outside the provider.
 */
export function useUpgradeModal(): {
  isOpen: boolean
  open(opts?: UpgradeModalOpts): void
  close(): void
} {
  const ctx = useContext(UpgradeModalContext)
  if (!ctx) {
    throw new Error('useUpgradeModal must be used within UpgradeModalProvider')
  }
  return { isOpen: ctx.state.isOpen, open: ctx.open, close: ctx.close }
}

// Internal access used by UpgradeModal itself (avoids re-exporting state internals).
export function useUpgradeModalContext(): UpgradeModalContextValue {
  const ctx = useContext(UpgradeModalContext)
  if (!ctx) {
    throw new Error('useUpgradeModalContext must be used within UpgradeModalProvider')
  }
  return ctx
}
