import type { ReactNode, ComponentType } from 'react'
import type {
  AppConfig,
  DataProvider,
  AuthProvider as AuthProviderInterface,
  NavigationProvider as NavigationProviderInterface,
  ResourceDefinition,
  Theme,
} from '../types'
import { AppProvider } from '../context/app-context'
import { DataProviderProvider } from '../context/data-provider-context'
import { AuthProvider } from '../context/auth-context'
import { NavigationProvider } from '../context/navigation-context'
import { ThemeProvider } from '../context/theme-context'
import { ResourcesProvider } from '../context/resource-context'

export interface AppProps {
  children: ReactNode
  /** App configuration (name, basePath, logo, etc.) */
  config: AppConfig
  /** Data provider for CRUD operations - consumers must implement */
  dataProvider: DataProvider
  /** Auth provider for authentication - consumers must implement */
  authProvider: AuthProviderInterface
  /** Navigation provider for routing integration (optional - defaults to window.location) */
  navigationProvider?: NavigationProviderInterface
  /** Resource definitions for auto-generating navigation and routes */
  resources?: ResourceDefinition[]
  /** Default theme setting */
  defaultTheme?: Theme
  /** Storage key for theme persistence */
  themeStorageKey?: string
  /** Custom layout component to wrap children */
  layout?: ComponentType<{ children: ReactNode }>
}

/**
 * App is the root component for building admin/app interfaces with @mdxui/app.
 *
 * It composes all the necessary providers (data, auth, navigation, theme, resources)
 * and requires consumers to provide their own implementations for DataProvider and AuthProvider.
 *
 * **Bring Your Own Backend Pattern:**
 * - `dataProvider`: Implement the 6-method DataProvider interface for your API/database
 * - `authProvider`: Implement the AuthProvider interface for your auth system
 * - `navigationProvider`: Optionally integrate with your router (react-router, next/router, etc.)
 *
 * @example
 * ```tsx
 * // Define your data provider
 * const myDataProvider: DataProvider = {
 *   getList: async (resource, params) => { ... },
 *   getOne: async (resource, params) => { ... },
 *   getMany: async (resource, params) => { ... },
 *   create: async (resource, params) => { ... },
 *   update: async (resource, params) => { ... },
 *   delete: async (resource, params) => { ... },
 * }
 *
 * // Define your auth provider
 * const myAuthProvider: AuthProvider = {
 *   login: async (params) => { ... },
 *   logout: async () => { ... },
 *   checkAuth: async () => { ... },
 *   checkError: async (error) => { ... },
 *   getIdentity: async () => ({ id: '1', fullName: 'John Doe' }),
 *   getPermissions: async () => ['admin'],
 * }
 *
 * // Define resources
 * const resources: ResourceDefinition[] = [
 *   { name: 'users', label: 'Users', icon: Users, list: UsersList, edit: UserEdit },
 *   { name: 'products', label: 'Products', icon: Package, list: ProductsList },
 * ]
 *
 * // Use in your application
 * <App
 *   config={{ name: 'My Admin', basePath: '/admin' }}
 *   dataProvider={myDataProvider}
 *   authProvider={myAuthProvider}
 *   resources={resources}
 * >
 *   <AppShell
 *     header={<TeamSwitcher />}
 *     nav={<NavMain />}
 *     footer={<NavUser />}
 *   >
 *     <Routes>
 *       <Route path="/" element={<Dashboard />} />
 *       {resources.map(r => (
 *         <Route key={r.name} path={`/${r.name}`} element={r.list && <r.list />} />
 *       ))}
 *     </Routes>
 *   </AppShell>
 * </App>
 * ```
 */
export function App({
  children,
  config,
  dataProvider,
  authProvider,
  navigationProvider,
  resources = [],
  defaultTheme = 'system',
  themeStorageKey = 'mdxui-app-theme',
  layout: Layout,
}: AppProps) {
  // Build navigation groups from resources
  const navigation = resources.length > 0
    ? [{
        label: 'Resources',
        items: resources
          .filter((r) => r.list) // Only include resources with list views
          .map((r) => ({
            title: r.labelPlural ?? r.label ?? r.name,
            url: `${config.basePath ?? ''}/${r.name}`,
            icon: r.icon,
          })),
      }]
    : []

  const content = Layout ? <Layout>{children}</Layout> : children

  return (
    <ThemeProvider defaultTheme={defaultTheme} storageKey={themeStorageKey}>
      <NavigationProvider navigationProvider={navigationProvider}>
        <DataProviderProvider dataProvider={dataProvider}>
          <AuthProvider authProvider={authProvider}>
            <ResourcesProvider resources={resources}>
              <AppProvider config={config} navigation={navigation}>
                {content}
              </AppProvider>
            </ResourcesProvider>
          </AuthProvider>
        </DataProviderProvider>
      </NavigationProvider>
    </ThemeProvider>
  )
}
