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 superjson from "superjson";
import { toast } from "sonner";
import App from "./App";
import { getLoginUrl } from "./const";
import { AquaVoiceProvider } from "./contexts/AquaVoiceContext";
import { LanguageProvider } from "./contexts/LanguageContext";
import { IndustryProvider } from "./contexts/IndustryContext";
import "./index.css";

// ── Friendly error messages for common server errors ────────────────────
const friendlyError = (err: unknown): string => {
  const msg = err instanceof Error ? err.message : String(err);
  if (msg.includes("412") || msg.includes("429") || msg.includes("exhausted") || msg.includes("rate"))
    return "AI service is temporarily at capacity. Please try again in a moment.";
  if (msg.includes("FORBIDDEN")) return "You don't have permission for that action.";
  if (msg.includes("NOT_FOUND")) return "The requested item was not found.";
  if (msg.includes("fetch failed") || msg.includes("NetworkError") || msg.includes("Failed to fetch"))
    return "Network connection lost. Check your internet and try again.";
  if (msg.includes("TIMEOUT") || msg.includes("timeout")) return "Request timed out. Please try again.";
  if (msg.length > 120) return "Something went wrong. Please try again.";
  return msg || "Something went wrong. Please try again.";
};

// ── QueryClient with resilient defaults ─────────────────────────────────
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      retry: (failureCount, error) => {
        const msg = error instanceof Error ? error.message : "";
        // Don't retry auth, permission, or not-found errors
        if (msg.includes(UNAUTHED_ERR_MSG) || msg.includes("FORBIDDEN") || msg.includes("NOT_FOUND")) return false;
        // Don't retry quota errors — they won't resolve by retrying
        if (msg.includes("412") || msg.includes("429") || msg.includes("exhausted")) return false;
        return failureCount < 2;
      },
      staleTime: 30_000, // 30s — reduce unnecessary refetches
      refetchOnWindowFocus: false, // Prevent refetch storms when switching tabs
    },
    mutations: {
      retry: false, // Never auto-retry mutations — user should consciously retry
    },
  },
});

// ── Auth redirect on 401 ────────────────────────────────────────────────
const redirectToLoginIfUnauthorized = (error: unknown) => {
  if (!(error instanceof TRPCClientError)) return;
  if (typeof window === "undefined") return;
  const isUnauthorized = error.message === UNAUTHED_ERR_MSG;
  if (!isUnauthorized) return;
  // Don't redirect on public pages (mirror kiosk, etc.)
  const publicPaths = ["/mirror"];
  if (publicPaths.some(p => window.location.pathname.startsWith(p))) return;
  window.location.href = getLoginUrl();
};

// ── Global query error handler ──────────────────────────────────────────
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);
  }
});

// ── Global mutation error handler — shows toast for unhandled errors ────
queryClient.getMutationCache().subscribe(event => {
  if (event.type === "updated" && event.action.type === "error") {
    const error = event.mutation.state.error;
    redirectToLoginIfUnauthorized(error);
    // Show a toast for every mutation failure so the user always knows
    const msg = friendlyError(error);
    toast.error(msg);
    console.error("[API Mutation Error]", error);
  }
});

// ── tRPC client ─────────────────────────────────────────────────────────
const trpcClient = trpc.createClient({
  links: [
    httpBatchLink({
      url: "/api/trpc",
      transformer: superjson,
      fetch(input, init) {
        return globalThis.fetch(input, {
          ...(init ?? {}),
          credentials: "include",
        });
      },
    }),
  ],
});

createRoot(document.getElementById("root")!).render(
  <trpc.Provider client={trpcClient} queryClient={queryClient}>
    <QueryClientProvider client={queryClient}>
      <AquaVoiceProvider>
        <LanguageProvider>
          <IndustryProvider>
            <App />
          </IndustryProvider>
        </LanguageProvider>
      </AquaVoiceProvider>
    </QueryClientProvider>
  </trpc.Provider>
);
