import React from 'react';
import {
  Navigate,
  Outlet,
  Route,
  createBrowserRouter,
  createHashRouter,
  createRoutesFromElements,
  redirect,
  useParams,
} from 'react-router-dom';

import { ClientConfig } from '../hooks/useClientConfig';
import { AuthLayout, Login, Register, ResetPassword } from './auth';
import {
  DIRECT_PATH,
  EXPLORE_PATH,
  HOME_PATH,
  LOGIN_PATH,
  INBOX_PATH,
  REGISTER_PATH,
  RESET_PASSWORD_PATH,
  SPACE_PATH,
  _CREATE_PATH,
  _FEATURED_PATH,
  _INVITES_PATH,
  _JOIN_PATH,
  _LOBBY_PATH,
  _NOTIFICATIONS_PATH,
  _ROOM_PATH,
  _SEARCH_PATH,
  _SERVER_PATH,
  CREATE_PATH,
  USER_LINK_HOST,
  USER_LINK_PATH,
  DirectCreateSearchParams,
} from './paths';
import {
  getAppPathFromHref,
  getDirectCreatePath,
  getExploreFeaturedPath,
  getHomePath,
  getInboxNotificationsPath,
  getLoginPath,
  getOriginBaseUrl,
  getSpaceLobbyPath,
  withSearchParam,
} from './pathUtils';
import { getMxIdServer, isUserId } from '../utils/matrix';
import { ClientBindAtoms, ClientLayout, ClientRoot } from './client';
import { HomeRouteRoomProvider } from './client/home';
import { Direct, DirectCreate, DirectRouteRoomProvider } from './client/direct';
import { RouteSpaceProvider, Space, SpaceRouteRoomProvider, SpaceSearch } from './client/space';
import { Explore, FeaturedRooms, PublicRooms } from './client/explore';
import { Notifications, Inbox, Invites } from './client/inbox';
import { setAfterLoginRedirectPath } from './afterLoginRedirectPath';
import { Room } from '../features/room';
import { Lobby } from '../features/lobby';
import { WelcomePage } from './client/WelcomePage';
import { SidebarNav } from './client/SidebarNav';
import { PageRoot } from '../components/page';
import { ScreenSize } from '../hooks/useScreenSize';
import { MobileFriendlyPageNav, MobileFriendlyClientNav } from './MobileFriendly';
import { ClientInitStorageAtom } from './client/ClientInitStorageAtom';
import { ClientNonUIFeatures } from './client/ClientNonUIFeatures';
import { AuthRouteThemeManager, UnAuthRouteThemeManager } from './ThemeManager';
import { ReceiveSelfDeviceVerification } from '../components/DeviceVerification';
import { AutoRestoreBackupOnVerification } from '../components/BackupRestore';
import { RoomSettingsRenderer } from '../features/room-settings';
import { ClientRoomsNotificationPreferences } from './client/ClientRoomsNotificationPreferences';
import { SpaceSettingsRenderer } from '../features/space-settings';
import { UserRoomProfileRenderer } from '../components/UserRoomProfileRenderer';
import { CreateRoomModalRenderer } from '../features/create-room';
import { Create } from './client/create';
import { CreateSpaceModalRenderer } from '../features/create-space';
import { SearchModalRenderer } from '../features/search';
import { getFallbackSession } from '../state/sessions';
import { CallStatusRenderer } from './CallStatusRenderer';
import { CallEmbedProvider } from '../components/CallEmbedProvider';
import { useIncomingRtcNotifications } from '../hooks/useIncomingRtcNotifications';
import { useCallerAutoHangup } from '../hooks/useCallerAutoHangup';
import { usePendingCallActionConsumer } from '../hooks/usePendingCallActionConsumer';
import { IncomingCallStripRenderer } from './IncomingCallStripRenderer';
import { useAppUrlOpen } from '../hooks/useAppUrlOpen';

function IncomingCallsFeature() {
  useIncomingRtcNotifications();
  useCallerAutoHangup();
  usePendingCallActionConsumer();
  // Native CallStyle dismissal is owned by the Android ring registry:
  // VojoFirebaseMessagingService.removeIncomingRing (ownership-checked cancel)
  // fires on atom REMOVE via bridge, and MainActivity.onResume calls
  // cancelRenderedIncomingRings for the background→foreground handoff.
  // A JS-side dismiss hook here is redundant and risks a blind tag/id cancel
  // hitting a foreign ring in the same room slot.
  useAppUrlOpen();
  return null;
}

// Deep-link entry for /u/<user>. `<user>` is either a bare localpart or a
// full MXID; we normalize to an MXID using USER_LINK_HOST (the deep-link's own
// host, NOT the logged-in user's homeserver — a user signed into matrix.org
// opening vojo.chat/u/test3 still means @test3:vojo.chat) and forward to the
// existing DirectCreate flow, which itself dedupes to any existing DM via
// getDMRoomFor.
function UserLinkRedirect() {
  const { userIdOrLocalPart } = useParams();
  if (!userIdOrLocalPart) return <Navigate to={getHomePath()} replace />;

  const raw = decodeURIComponent(userIdOrLocalPart);
  const mxid = isUserId(raw) && getMxIdServer(raw) ? raw : `@${raw}:${USER_LINK_HOST}`;
  if (!isUserId(mxid)) return <Navigate to={getHomePath()} replace />;

  const params: DirectCreateSearchParams = { userId: mxid };
  return <Navigate to={withSearchParam(getDirectCreatePath(), params)} replace />;
}

export const createRouter = (clientConfig: ClientConfig, screenSize: ScreenSize) => {
  const { hashRouter } = clientConfig;
  const mobile = screenSize === ScreenSize.Mobile;

  const routes = createRoutesFromElements(
    <Route>
      <Route
        index
        loader={() => {
          if (getFallbackSession()) return redirect(getHomePath());
          const afterLoginPath = getAppPathFromHref(getOriginBaseUrl(), window.location.href);
          if (afterLoginPath) setAfterLoginRedirectPath(afterLoginPath);
          return redirect(getLoginPath());
        }}
      />
      <Route
        loader={() => {
          if (getFallbackSession()) {
            return redirect(getHomePath());
          }

          return null;
        }}
        element={
          <>
            <AuthLayout />
            <UnAuthRouteThemeManager />
          </>
        }
      >
        <Route path={LOGIN_PATH} element={<Login />} />
        <Route path={REGISTER_PATH} element={<Register />} />
        <Route path={RESET_PASSWORD_PATH} element={<ResetPassword />} />
      </Route>

      <Route
        loader={() => {
          const session = getFallbackSession();
          if (!session) {
            const afterLoginPath = getAppPathFromHref(
              getOriginBaseUrl(hashRouter),
              window.location.href
            );
            if (afterLoginPath) setAfterLoginRedirectPath(afterLoginPath);
            return redirect(getLoginPath());
          }
          return null;
        }}
        element={
          <AuthRouteThemeManager>
            <ClientRoot>
              <ClientInitStorageAtom>
                <ClientRoomsNotificationPreferences>
                  <ClientBindAtoms>
                    <ClientNonUIFeatures>
                      <CallEmbedProvider>
                        <ClientLayout
                          nav={
                            <MobileFriendlyClientNav>
                              <SidebarNav />
                            </MobileFriendlyClientNav>
                          }
                        >
                          <Outlet />
                        </ClientLayout>
                        <IncomingCallStripRenderer />
                        <CallStatusRenderer />
                        <IncomingCallsFeature />
                      </CallEmbedProvider>
                      <SearchModalRenderer />
                      <UserRoomProfileRenderer />
                      <CreateRoomModalRenderer />
                      <CreateSpaceModalRenderer />
                      <RoomSettingsRenderer />
                      <SpaceSettingsRenderer />
                      <ReceiveSelfDeviceVerification />
                      <AutoRestoreBackupOnVerification />
                    </ClientNonUIFeatures>
                  </ClientBindAtoms>
                </ClientRoomsNotificationPreferences>
              </ClientInitStorageAtom>
            </ClientRoot>
          </AuthRouteThemeManager>
        }
      >
        {/* Legacy /home/ tree — kept only as a redirect surface so cold-start
            push deep links and pre-P3c bookmarks resolve cleanly. The Home
            page itself is gone; HomeRouteRoomProvider redirects /home/{roomId}/
            into /direct/{roomId}/ on mount. See plan §6.7 / §8 P3c. */}
        <Route path={HOME_PATH}>
          <Route index element={<Navigate to={DIRECT_PATH} replace />} />
          <Route path={_CREATE_PATH} element={<Navigate to={getDirectCreatePath()} replace />} />
          <Route path={_JOIN_PATH} element={<Navigate to={DIRECT_PATH} replace />} />
          <Route path={_SEARCH_PATH} element={<Navigate to={DIRECT_PATH} replace />} />
          <Route
            path={_ROOM_PATH}
            element={
              <HomeRouteRoomProvider>
                <Room />
              </HomeRouteRoomProvider>
            }
          />
        </Route>
        <Route
          path={DIRECT_PATH}
          element={
            <PageRoot
              nav={
                <MobileFriendlyPageNav path={DIRECT_PATH}>
                  <Direct />
                </MobileFriendlyPageNav>
              }
            >
              <Outlet />
            </PageRoot>
          }
        >
          {mobile ? null : <Route index element={<WelcomePage />} />}
          <Route path={_CREATE_PATH} element={<DirectCreate />} />
          <Route
            path={_ROOM_PATH}
            element={
              <DirectRouteRoomProvider>
                <Room />
              </DirectRouteRoomProvider>
            }
          />
        </Route>
        <Route
          path={SPACE_PATH}
          element={
            <RouteSpaceProvider>
              <PageRoot
                nav={
                  <MobileFriendlyPageNav path={SPACE_PATH}>
                    <Space />
                  </MobileFriendlyPageNav>
                }
              >
                <Outlet />
              </PageRoot>
            </RouteSpaceProvider>
          }
        >
          {mobile ? null : (
            <Route
              index
              loader={({ params }) => {
                const { spaceIdOrAlias } = params;
                if (spaceIdOrAlias) {
                  return redirect(getSpaceLobbyPath(spaceIdOrAlias));
                }
                return null;
              }}
              element={<WelcomePage />}
            />
          )}
          <Route path={_LOBBY_PATH} element={<Lobby />} />
          <Route path={_SEARCH_PATH} element={<SpaceSearch />} />
          <Route
            path={_ROOM_PATH}
            element={
              <SpaceRouteRoomProvider>
                <Room />
              </SpaceRouteRoomProvider>
            }
          />
        </Route>
        <Route
          path={EXPLORE_PATH}
          element={
            <PageRoot
              nav={
                <MobileFriendlyPageNav path={EXPLORE_PATH}>
                  <Explore />
                </MobileFriendlyPageNav>
              }
            >
              <Outlet />
            </PageRoot>
          }
        >
          {mobile ? null : (
            <Route
              index
              loader={() => redirect(getExploreFeaturedPath())}
              element={<WelcomePage />}
            />
          )}
          <Route path={_FEATURED_PATH} element={<FeaturedRooms />} />
          <Route path={_SERVER_PATH} element={<PublicRooms />} />
        </Route>
        <Route path={CREATE_PATH} element={<Create />} />
        <Route path={USER_LINK_PATH} element={<UserLinkRedirect />} />
        <Route
          path={INBOX_PATH}
          element={
            <PageRoot
              nav={
                <MobileFriendlyPageNav path={INBOX_PATH}>
                  <Inbox />
                </MobileFriendlyPageNav>
              }
            >
              <Outlet />
            </PageRoot>
          }
        >
          {mobile ? null : (
            <Route
              index
              loader={() => redirect(getInboxNotificationsPath())}
              element={<WelcomePage />}
            />
          )}
          <Route path={_NOTIFICATIONS_PATH} element={<Notifications />} />
          <Route path={_INVITES_PATH} element={<Invites />} />
        </Route>
      </Route>
      <Route path="/*" element={<p>Page not found</p>} />
    </Route>
  );

  if (hashRouter?.enabled) {
    return createHashRouter(routes, { basename: hashRouter.basename });
  }
  return createBrowserRouter(routes, {
    basename: import.meta.env.BASE_URL,
  });
};
