import "./mobxIsolate"; // must be first: isolates mobx before any store loads (CORE-2628)
import { css, Global } from "@emotion/react";
import { colorOverrides, cursorOverrides } from "@jam/ds/base";
// TODO(matheus): we need to remove this and use theme provider from DS
// need to test visually all recorder pages, so will keep it for now
import { Theme } from "@radix-ui/themes";
import * as tsr from "@tanstack/react-router";
import { errorToJSON } from "@jam/commons";
import { StrictMode } from "react";
import ReactDOM from "react-dom/client";
// Import the generated route tree
import { routes } from "../routes.config";
import { LoadingSpinnerBig } from "./components/LoadingSpinner";
import { initDatadog } from "./datadog";
import * as gql from "./graphql/getGraphQLClient";
import logger from "./logger";
import { ErrorComponent } from "./routes/-rootComponents/ErrorComponent";
import * as Layout from "./routes/-rootComponents/Layout";
import { RecordingLinkFailure } from "./routes/-rootComponents/RecordingLinkFailure";
import { routeTree } from "./routeTree.gen";
import { DatadogLogger, installUncaughtErrorProbe } from "./utils";

// Set up our route masks
const recordingIdRouteMasks = [
  { from: routes.record._recordingId.index, to: routes._recordingId },
  { from: routes.record._recordingId.ready, to: routes._recordingId },
  { from: routes.record._recordingId.recording, to: routes._recordingId },
  { from: routes.record._recordingId.review, to: routes._recordingId },
  { from: routes.record._recordingId.submitted, to: routes._recordingId },
  { from: routes.record._recordingId.failed, to: routes._recordingId },
].map((config) =>
  tsr.createRouteMask({
    routeTree,
    ...config,
    params: (prev) => ({ recordingId: prev.recordingId }),
    // Preserve `jam-pip` through the mask so the query param survives route loads
    search: (prev: Record<string, unknown>) =>
      prev["jam-pip"] !== undefined ? { "jam-pip": prev["jam-pip"] } : {},
  }),
);

// Create shared context objects
const client = gql.getGraphQLClient();
const beaconClient = gql.getGraphQLBeaconClient();
const datadogLogger = new DatadogLogger();

// Create a new router instance
const router = tsr.createRouter({
  routeTree,
  routeMasks: recordingIdRouteMasks,
  context: { client, beaconClient, logger, datadogLogger },
  defaultErrorComponent: ErrorComponent,
  // A route error boundary swallows the throw, so nothing else reports it.
  defaultOnCatch: (error) => {
    logger.error("Unhandled recorder route error", {
      error: errorToJSON(error),
    });
  },
  // A URL with no recording link id (or a path that is not one) reads as a
  // bad link, the same card an unknown id gets after the API rejects it.
  // Render it at the root: the default "fuzzy" mode would render it inside
  // the record route's card for a stray segment under `/record/...`.
  notFoundMode: "root",
  defaultNotFoundComponent: () => (
    <Layout.Container>
      <RecordingLinkFailure reason="invalid" />
    </Layout.Container>
  ),
  defaultPendingMinMs: 250,
  defaultPendingComponent: () => <LoadingSpinnerBig />,
});

// Register the router instance for type safety
declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}

const themeOverrides = css`
  ${colorOverrides}
  ${cursorOverrides}
`;

// Render the app
const rootElement = document.querySelector("#root");
if (rootElement && !rootElement.innerHTML) {
  initDatadog();
  // Must follow initDatadog so the reports reach the Datadog sink; no-ops
  // outside the capture iframe.
  installUncaughtErrorProbe(logger);

  const root = ReactDOM.createRoot(rootElement);

  // todo: importing ThemedProvider from ds/base breaks fonts for some reason,
  // only apply color and cursor overrides for now :/
  root.render(
    <StrictMode>
      <Global styles={themeOverrides} />
      <Theme
        accentColor="lime"
        style={{ height: "100%" }}
        grayColor="gray"
        panelBackground="solid"
        radius="large"
      >
        <tsr.RouterProvider router={router} />
      </Theme>
    </StrictMode>,
  );
}
