"use client";

import { useEffect } from "react";

const SEEN = new Set<string>();
const MAX_SEEN = 50;

function fingerprint(type: string, message: string, stack?: string): string {
  const head = (stack || "").split("\n").slice(0, 3).join("\n");
  return `${type}|${message.slice(0, 80)}|${head.slice(0, 120)}`;
}

async function report(payload: {
  type: string;
  message: string;
  stack?: string;
  url?: string;
}) {
  const fp = fingerprint(payload.type, payload.message, payload.stack);
  if (SEEN.has(fp)) return;
  SEEN.add(fp);
  if (SEEN.size > MAX_SEEN) {
    const first = SEEN.values().next().value;
    if (first) SEEN.delete(first);
  }
  try {
    await fetch("/api/errors", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ ...payload, url: payload.url || location.href }),
      keepalive: true,
    });
  } catch {}
}

export function ErrorReporter() {
  useEffect(() => {
    if (typeof window === "undefined") return;
    if (process.env.NODE_ENV !== "production") return;

    const onError = (e: ErrorEvent) => {
      report({
        type: "window.error",
        message: e.message || String(e.error),
        stack: e.error?.stack,
        url: e.filename,
      });
    };

    const onRejection = (e: PromiseRejectionEvent) => {
      const reason = e.reason;
      const message =
        reason instanceof Error ? reason.message : String(reason);
      const stack = reason instanceof Error ? reason.stack : undefined;
      report({ type: "unhandledrejection", message, stack });
    };

    window.addEventListener("error", onError);
    window.addEventListener("unhandledrejection", onRejection);
    return () => {
      window.removeEventListener("error", onError);
      window.removeEventListener("unhandledrejection", onRejection);
    };
  }, []);

  return null;
}
