// §22.9 (M3) — runtime deployment config, replacing the build-time
// VITE_APP_NAME. Fetches GET /api/deployment once on boot and provides it to
// the whole tree:
//
//   { name, tagline, defaultProjectId, defaultProjectReadable, projects[],
//     viewer, loading, refresh }
//
// `projects` is the per-caller-visible set (§22.5: public + member-gated;
// unlisted omitted). `defaultProjectId` is the corpus-served project the
// M3-frontend guard keys on. `defaultProjectReadable` (§22 S5) is whether that
// redirect target is reachable by this viewer — the deployment landing only
// bounces into it when true, else it renders the role-aware directory empty
// state. `viewer` carries the §22 S5 capability flags (`can_create_project`).
// `refresh` re-fetches the payload (e.g. after creating a project). During the
// pre-fetch paint, consumers fall back to the neutral brandTitle() default
// ('RFC') — never a hardcoded deployment name.
import { createContext, useContext, useCallback, useEffect, useState } from 'react'
import { getDeployment } from '../api'

const DeploymentContext = createContext({
  name: '',
  tagline: '',
  defaultProjectId: null,
  defaultProjectReadable: false,
  projects: [],
  viewer: null,
  loading: true,
  refresh: () => {},
})

export function useDeployment() {
  return useContext(DeploymentContext)
}

export function DeploymentProvider({ children }) {
  const [state, setState] = useState({
    name: '',
    tagline: '',
    defaultProjectId: null,
    defaultProjectReadable: false,
    projects: [],
    viewer: null,
    loading: true,
  })

  const load = useCallback((cancelledRef) => {
    return getDeployment()
      .then(d => {
        if (cancelledRef?.cancelled) return
        setState({
          name: d.name || '',
          tagline: d.tagline || '',
          defaultProjectId: d.default_project_id || null,
          defaultProjectReadable: !!d.default_project_readable,
          projects: Array.isArray(d.projects) ? d.projects : [],
          viewer: d.viewer || null,
          loading: false,
        })
      })
      .catch(() => {
        // A failed deployment fetch must not wedge the app: fall back to the
        // neutral brand and an empty directory so the shell still paints.
        if (!cancelledRef?.cancelled) setState(s => ({ ...s, loading: false }))
      })
  }, [])

  useEffect(() => {
    const ref = { cancelled: false }
    load(ref)
    return () => { ref.cancelled = true }
  }, [load])

  const refresh = useCallback(() => load(), [load])

  return (
    <DeploymentContext.Provider value={{ ...state, refresh }}>
      {children}
    </DeploymentContext.Provider>
  )
}
