import { trpc } from "@/lib/trpc";
import { UNAUTHED_ERR_MSG } from '@shared/const';
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { httpBatchLink, TRPCClientError } from "@trpc/client";
import { createRoot } from "react-dom/client";
import { useState } from "react";
import superjson from "superjson";
import App from "./App";
import { getLoginUrl } from "./const";
import { ENABLE_AUTH } from "@/lib/featureFlags";
import "./index.css";

// ── Domain detection ──────────────────────────────────────────────────
// Clerk production keys are bound to marlowekeynes.org and its registered
// satellite domains. On any other domain (dev, manus.space preview, etc.)
// we skip Clerk entirely and fall back to legacy Manus OAuth.
const CLERK_VALID_DOMAINS = [
  "marlowekeynes.org",
  "mkinitiationreport.com",
  "www.mkinitiationreport.com",
  "steinbergstock.com",
  "www.steinbergstock.com",
  "mkinitiationreport.manus.space",
  "deepdiveanaly-mzjhetg8.manus.space",
];

const currentHost = typeof window !== "undefined" ? window.location.hostname : "";
const isClerkDomain = CLERK_VALID_DOMAINS.some(
  (d) => currentHost === d || currentHost.endsWith(`.${d}`)
);

// Satellite domains are production domains that are NOT the primary domain
const CLERK_PRIMARY_DOMAIN = "marlowekeynes.org";
const isSatelliteDomain = isClerkDomain && currentHost !== CLERK_PRIMARY_DOMAIN;
const CLERK_SIGN_IN_URL = `https://${CLERK_PRIMARY_DOMAIN}/login`;

// Map satellite hostnames to their Clerk CNAME (clerk.{base-domain}).
// The Clerk JS SDK uses the `domain` prop to construct the sync URL:
//   `https://{domain}/v1/client/sync`
// So `domain` must point to the Clerk CNAME, NOT the site hostname.
const SATELLITE_CLERK_DOMAINS: Record<string, string> = {
  "mkinitiationreport.com": "clerk.mkinitiation.com",
  "www.mkinitiationreport.com": "clerk.mkinitiation.com",
  "mkinitiationreport.manus.space": "clerk.mkinitiation.com",
  "deepdiveanaly-mzjhetg8.manus.space": "clerk.mkinitiation.com",
};
const satelliteClerkDomain = SATELLITE_CLERK_DOMAINS[currentHost] || `clerk.${currentHost.replace(/^www\./, '')}`;

// [OPT-091] Configure QueryClient defaults for performance
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 2 * 60 * 1000,
      gcTime: 10 * 60 * 1000,
      refetchOnWindowFocus: false,
      retry: 1,
      refetchOnReconnect: 'always',
    },
    mutations: {
      retry: 0,
    },
  },
});

const redirectToLoginIfUnauthorized = (error: unknown) => {
  if (!ENABLE_AUTH) return; // Auth disabled — never redirect to login
  if (!(error instanceof TRPCClientError)) return;
  if (typeof window === "undefined") return;
  const isUnauthorized = error.message === UNAUTHED_ERR_MSG;
  if (!isUnauthorized) return;
  if (isClerkDomain) {
    window.location.href = CLERK_SIGN_IN_URL;
  } else {
    window.location.href = getLoginUrl();
  }
};

queryClient.getQueryCache().subscribe(event => {
  if (event.type === "updated" && event.action.type === "error") {
    const error = event.query.state.error;
    redirectToLoginIfUnauthorized(error);
    console.error("[API Query Error]", error);
  }
});

queryClient.getMutationCache().subscribe(event => {
  if (event.type === "updated" && event.action.type === "error") {
    const error = event.mutation.state.error;
    redirectToLoginIfUnauthorized(error);
    console.error("[API Mutation Error]", error);
  }
});

// ── tRPC client wrapper (WITHOUT Clerk) ───────────────────────────────
// Used on dev/preview domains where Clerk is not available.
function TrpcWithLegacyAuth({ children }: { children: React.ReactNode }) {
  const [trpcClient] = useState(() =>
    trpc.createClient({
      links: [
        httpBatchLink({
          url: "/api/trpc",
          transformer: superjson,
          fetch(input, init) {
            return globalThis.fetch(input, {
              ...(init ?? {}),
              credentials: "include",
            });
          },
        }),
      ],
    })
  );

  return (
    <trpc.Provider client={trpcClient} queryClient={queryClient}>
      <QueryClientProvider client={queryClient}>
        {children}
      </QueryClientProvider>
    </trpc.Provider>
  );
}

// ── Conditional Clerk loading ─────────────────────────────────────────
// Only import and use Clerk on domains where the production key is valid
// AND when authentication is enabled. When ENABLE_AUTH is false, we skip
// Clerk entirely to prevent forced sign-up/sign-in flows.
if (isClerkDomain && ENABLE_AUTH) {
  // Dynamic import to avoid loading Clerk SDK on non-Clerk domains
  import("@clerk/clerk-react").then(({ ClerkProvider, useAuth: useClerkAuth }) => {
    const CLERK_PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY;

    /**
     * tRPC client wrapper with Clerk auth token injection.
     * Must be inside ClerkProvider to access useAuth().
     */
    function TrpcWithClerkAuth({ children }: { children: React.ReactNode }) {
      const { getToken } = useClerkAuth();

      // Memoize the tRPC client so it's not recreated on every render.
      // getToken is stable from Clerk, so this is safe.
      const [trpcClient] = useState(() =>
        trpc.createClient({
          links: [
            httpBatchLink({
              url: "/api/trpc",
              transformer: superjson,
              async headers() {
                try {
                  const token = await getToken();
                  return token ? { Authorization: `Bearer ${token}` } : {};
                } catch {
                  return {};
                }
              },
              fetch(input, init) {
                return globalThis.fetch(input, {
                  ...(init ?? {}),
                  credentials: "include",
                });
              },
            }),
          ],
        })
      );

      return (
        <trpc.Provider client={trpcClient} queryClient={queryClient}>
          <QueryClientProvider client={queryClient}>
            {children}
          </QueryClientProvider>
        </trpc.Provider>
      );
    }

    // Build ClerkProvider props
    const clerkProps: Record<string, unknown> = {
      publishableKey: CLERK_PUBLISHABLE_KEY,
      signInUrl: CLERK_SIGN_IN_URL,
      signUpUrl: `https://${CLERK_PRIMARY_DOMAIN}/login`,
    };

    if (isSatelliteDomain) {
      clerkProps.isSatellite = true;
      clerkProps.domain = satelliteClerkDomain;
    } else {
      // Primary domain: allow redirects back to all satellite domains
      clerkProps.allowedRedirectOrigins = [
        "https://mkinitiationreport.com",
        "https://www.mkinitiationreport.com",
        "https://mkinitiationreport.manus.space",
        "https://deepdiveanaly-mzjhetg8.manus.space",
      ];
    }

    createRoot(document.getElementById("root")!).render(
      <ClerkProvider {...(clerkProps as any)}>
        <TrpcWithClerkAuth>
          <App />
        </TrpcWithClerkAuth>
      </ClerkProvider>
    );
  });
} else {
  // Non-Clerk domain: use legacy Manus OAuth (cookie-based auth)
  createRoot(document.getElementById("root")!).render(
    <TrpcWithLegacyAuth>
      <App />
    </TrpcWithLegacyAuth>
  );
}
