import { matchPath } from 'react-router-dom';
import {
  BOTS_PATH,
  CHANNELS_PATH,
  CHANNELS_ROOM_EVENT_PATH,
  CHANNELS_ROOM_PATH,
  CHANNELS_SPACE_PATH,
  CHANNELS_THREAD_PATH,
  DIRECT_PATH,
  EXPLORE_PATH,
  HOME_PATH,
  SPACE_PATH,
} from '../pages/paths';
import {
  getBotsPath,
  getChannelsPath,
  getChannelsRoomPath,
  getChannelsSpacePath,
  getDirectPath,
  getExplorePath,
  getHomePath,
  getSpacePath,
} from '../pages/pathUtils';

/**
 * Returns the section-root parent path for the given pathname, or null
 * when pathname is not under a known section or is already at the root
 * of its section. Shared by the UI back arrow (BackRouteHandler) and the
 * Android hardware back button (useAndroidBackButton) so they can't drift.
 */
export const getRouteSectionParent = (pathname: string): string | null => {
  const atRoot = (path: string) =>
    matchPath({ path, caseSensitive: true, end: true }, pathname) !== null;
  const under = (path: string) =>
    matchPath({ path, caseSensitive: true, end: false }, pathname) !== null;

  if (under(HOME_PATH)) return atRoot(HOME_PATH) ? null : getHomePath();
  if (under(DIRECT_PATH)) return atRoot(DIRECT_PATH) ? null : getDirectPath();
  if (under(BOTS_PATH)) return atRoot(BOTS_PATH) ? null : getBotsPath();

  if (under(CHANNELS_PATH)) {
    // Thread URL collapses to its parent room view (drawer closed) — must
    // match before the room-level matcher because thread is a strict
    // subpath of room (`/channels/:s/:r/thread/:rootId/`).
    const threadMatch = matchPath(
      { path: CHANNELS_THREAD_PATH, caseSensitive: true, end: false },
      pathname
    );
    if (threadMatch?.params.spaceIdOrAlias && threadMatch?.params.roomIdOrAlias) {
      return getChannelsRoomPath(
        decodeURIComponent(threadMatch.params.spaceIdOrAlias),
        decodeURIComponent(threadMatch.params.roomIdOrAlias)
      );
    }
    // Event-anchored permalink collapses to the same parent room view as
    // thread does — so back from a search/notification permalink lands on
    // the room timeline first, not on the space root.
    const eventMatch = matchPath(
      { path: CHANNELS_ROOM_EVENT_PATH, caseSensitive: true, end: false },
      pathname
    );
    if (eventMatch?.params.spaceIdOrAlias && eventMatch?.params.roomIdOrAlias) {
      return getChannelsRoomPath(
        decodeURIComponent(eventMatch.params.spaceIdOrAlias),
        decodeURIComponent(eventMatch.params.roomIdOrAlias)
      );
    }
    const roomMatch = matchPath(
      { path: CHANNELS_ROOM_PATH, caseSensitive: true, end: false },
      pathname
    );
    const roomSpace = roomMatch?.params.spaceIdOrAlias;
    if (roomSpace) {
      return getChannelsSpacePath(decodeURIComponent(roomSpace));
    }
    const spaceMatch = matchPath(
      { path: CHANNELS_SPACE_PATH, caseSensitive: true, end: false },
      pathname
    );
    const channelsSpace = spaceMatch?.params.spaceIdOrAlias;
    if (channelsSpace) {
      const channelsSpacePath = getChannelsSpacePath(decodeURIComponent(channelsSpace));
      return pathname === channelsSpacePath ? getChannelsPath() : channelsSpacePath;
    }
    return atRoot(CHANNELS_PATH) ? null : getChannelsPath();
  }

  const spaceMatch = matchPath({ path: SPACE_PATH, caseSensitive: true, end: false }, pathname);
  const encodedSpaceIdOrAlias = spaceMatch?.params.spaceIdOrAlias;
  if (encodedSpaceIdOrAlias) {
    const spacePath = getSpacePath(decodeURIComponent(encodedSpaceIdOrAlias));
    return pathname === spacePath ? null : spacePath;
  }

  if (under(EXPLORE_PATH)) return atRoot(EXPLORE_PATH) ? null : getExplorePath();

  return null;
};

/**
 * True when `pathname` is exactly one of the mobile tab listing roots
 * (Direct, Bots, Channels landing, or a Channels workspace). The mobile
 * swipe-back overlay uses this on the result of `getRouteSectionParent` to
 * decide whether a chat pops to a real LIST (run the animated card-slide
 * with the list revealed behind) or to another DETAIL screen — e.g. a
 * thread / event-permalink whose parent is the room itself — in which case
 * it skips the visual swipe and leaves the instant header/hardware back.
 */
export const isListingRootPath = (pathname: string): boolean => {
  const exact = (path: string) =>
    matchPath({ path, caseSensitive: true, end: true }, pathname) !== null;
  return (
    exact(DIRECT_PATH) || exact(BOTS_PATH) || exact(CHANNELS_PATH) || exact(CHANNELS_SPACE_PATH)
  );
};
