import React, { Suspense, lazy, useState, useMemo, useEffect } from 'react';
import type { ComponentType } from 'react';
import Memes from './Memes.tsx';
import Lighting from './Lighting.tsx';
import { toast } from 'react-toastify';
import { JoyUIRootIsland } from './Components.tsx';
import { PrimeReactProvider } from "primereact/api";
import { usePrimeReactThemeSwitcher } from '@/hooks/usePrimeReactThemeSwitcher.tsx';
import CustomToastContainer from '../components/ToastProvider.tsx';
import 'primereact/resources/themes/bootstrap4-light-blue/theme.css';
import 'primereact/resources/primereact.min.css';
import "primeicons/primeicons.css";

const LoginPage = lazy(() => import('./Login.tsx'));
const LyricSearch = lazy(() => import('./LyricSearch'));
const MediaRequestForm = lazy(() => import('./TRip/MediaRequestForm.tsx'));
const RequestManagement = lazy(() => import('./TRip/RequestManagement.tsx'));
const DiscordLogs = lazy(() => import('./DiscordLogs.tsx'));
// NOTE: Player is intentionally NOT imported at module initialization.
// We create the lazy import inside the component at render-time only when
// we are on the main site and the Player island should be rendered. This
// prevents bundling the player island into pages that are explicitly
// identified as subsites.
const ReqForm = lazy(() => import('./req/ReqForm.tsx'));

// Simple error boundary for lazy islands
class LazyBoundary extends React.Component<{ children: React.ReactNode }, { hasError: boolean }> {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
  static getDerivedStateFromError() {
    return { hasError: true };
  }
  componentDidCatch(err) {
    if (import.meta.env.DEV) {
      console.error('[AppLayout] lazy island error', err);
    }
  }
  render() {
    if (this.state.hasError) {
      return <div style={{ padding: '1rem', textAlign: 'center' }}>Something went wrong loading this module.</div>;
    }
    return this.props.children;
  }
}

declare global {
  interface Window {
    toast: typeof toast;
    __IS_SUBSITE?: boolean;
  }
}

export interface User {
  id?: string;
  username?: string;
  roles?: string[];
  [key: string]: unknown;
}

export interface RootProps {
  child: string;
  user?: User;
  loggedIn?: boolean;
  [key: string]: unknown;
}

export default function Root({ child, user = undefined, ...props }: RootProps): React.ReactElement {
  window.toast = toast;
  const theme = document.documentElement.getAttribute("data-theme") ?? null;
  const toastTheme = theme ?? undefined;
  const loggedIn = props.loggedIn ?? Boolean(user);
  usePrimeReactThemeSwitcher(theme);
  // Avoid adding the Player island for subsite requests. We expose a
  // runtime flag `window.__IS_SUBSITE` from the server layout so pages
  // don't need to pass guards.
  const isSubsite = typeof document !== 'undefined' && document.documentElement.getAttribute('data-subsite') === 'true';
  // Log when the active child changes (DEV only)
  const devLogsEnabled = import.meta.env.DEV && import.meta.env.VITE_DEV_LOGS === '1';

  useEffect(() => {
    if (!devLogsEnabled) return;
    try {
      if (typeof console !== 'undefined' && typeof document !== 'undefined') {
        console.debug(`[AppLayout] child=${String(child)}, data-subsite=${document.documentElement.getAttribute('data-subsite')}`);
      }
    } catch (e) {
      // no-op
    }
  }, [child, devLogsEnabled]);

  // Only initialize the lazy player when this is NOT a subsite and the
  // active child is the Player island. Placing the lazy() call here
  // avoids creating a static dependency at module load time.
  // Create the lazy component only when we actually need it. Using
  // `useMemo` ensures we don't re-create the lazy factory on every render
  // which would create a new component identity and cause mount/unmount
  // loops and repeated log messages.
  const wantPlayer = !isSubsite && child === "Player";

  // Use dynamic import+state on the client to avoid React.lazy identity
  // churn and to surface any import-time errors. Since Root is used via
  // client:only, this code runs in the browser and can safely import.
  const [PlayerComp, setPlayerComp] = useState<ComponentType<{ user?: User }> | null>(null);
  useEffect(() => {
    let mounted = true;
    if (wantPlayer) {
      if (import.meta.env.DEV) { try { console.debug('[AppLayout] dynamic-import: requesting AudioPlayer'); } catch (e) { } }
      import('./Radio.tsx')
        .then((mod) => {
          if (!mounted) return;
          // set the component factory
          setPlayerComp(() => mod.default ?? null);
          if (import.meta.env.DEV) { try { console.debug('[AppLayout] AudioPlayer import succeeded'); } catch (e) { } }
        })
        .catch((err) => {
          console.error('[AppLayout] AudioPlayer import failed', err);
          if (mounted) setPlayerComp(null);
        });
    } else {
      // unload if we no longer want the player
      setPlayerComp(() => null);
    }
    return () => { mounted = false; };
  }, [wantPlayer]);

  return (
    <PrimeReactProvider>
      <CustomToastContainer
        theme={toastTheme}
        newestOnTop={true}
        closeOnClick={true} />
      <JoyUIRootIsland>
        {/* <Alert
        className="alert"
        startDecorator={<WarningIcon />}
        variant="soft"
        color="danger">
          Work in progress... bugs are to be expected.
        </Alert> */}
        {child == "LoginPage" && (
          <LazyBoundary>
            <Suspense fallback={<div style={{ padding: '2rem', textAlign: 'center' }}>Loading...</div>}>
              <LoginPage {...props} loggedIn={loggedIn} />
            </Suspense>
          </LazyBoundary>
        )}
        {child == "LyricSearch" && (
          <LazyBoundary>
            <Suspense fallback={<div style={{ padding: '2rem', textAlign: 'center' }}>Loading...</div>}>
              <LyricSearch />
            </Suspense>
          </LazyBoundary>
        )}
        {child == "Player" && !isSubsite && PlayerComp && (
          <LazyBoundary>
            <Suspense fallback={null}>
              <PlayerComp user={user} />
            </Suspense>
          </LazyBoundary>
        )}
        {child == "Memes" && (
          <LazyBoundary>
            <Memes />
          </LazyBoundary>
        )}
        {child == "DiscordLogs" && (
          <LazyBoundary>
            <Suspense fallback={<div style={{ padding: '2rem', textAlign: 'center' }}>Loading...</div>}>
              <DiscordLogs />
            </Suspense>
          </LazyBoundary>
        )}
        {child == "qs2.MediaRequestForm" && (
          <LazyBoundary>
            <MediaRequestForm />
          </LazyBoundary>
        )}
        {child == "qs2.RequestManagement" && (
          <LazyBoundary>
            <RequestManagement />
          </LazyBoundary>
        )}
        {child == "ReqForm" && (
          <LazyBoundary>
            <ReqForm />
          </LazyBoundary>
        )}
        {child == "Lighting" && (
          <LazyBoundary>
            <Lighting key={window.location.pathname + Math.random()} />
          </LazyBoundary>
        )}
      </JoyUIRootIsland>
    </PrimeReactProvider>
  );
}

