/**
 * PostHog wiring — session replay, exception capture, console logs.
 *
 * NOTE: `portal/src/lib/posthog.ts` is the twin of this file. The init config
 * below (masking rules) and the PII allowlist in `useIdentify` MUST be kept
 * identical in both — a change made here alone silently leaks staff data into
 * the other app's replays.
 *
 * This is instrumentation, not analytics: autocapture is off and no product
 * events are sent.
 */
import posthog from "posthog-js";
import { useEffect } from "react";

import type { AuthUser } from "@/auth/types";

const APP = "freight-backoffice";

const TOKEN = import.meta.env.VITE_POSTHOG_KEY;
const HOST = import.meta.env.VITE_POSTHOG_HOST;

/**
 * Whether init actually ran. Without a token every export below is a no-op, so
 * local dev and any environment whose env file lacks the vars keeps working —
 * a missing observability token must never break the app.
 */
let enabled = false;

export function initPostHog(): void {
  if (enabled || !TOKEN || !HOST) return;

  posthog.init(TOKEN, {
    api_host: HOST,
    defaults: "2026-05-30",

    // Debuggability, not analytics.
    autocapture: false,
    capture_pageview: true,
    capture_pageleave: true,
    disable_surveys: true,
    person_profiles: "identified_only",

    capture_exceptions: {
      capture_unhandled_errors: true,
      capture_unhandled_rejections: true,
      capture_console_errors: true,
    },

    // Off by default; this is half the point of the integration.
    enable_recording_console_log: true,

    // Inputs are masked; rendered text stays visible so replays are readable.
    // Wrap sensitive elements in `ph-no-capture` to blank them individually.
    session_recording: { maskAllInputs: true },
  });

  // Portal and backoffice share one PostHog project — filter by this.
  posthog.register({ app: APP });

  enabled = true;
}

export function captureException(
  error: unknown,
  properties?: Record<string, unknown>,
): void {
  if (!enabled) return;
  posthog.captureException(error, properties);
}

/**
 * Report a failed API call.
 *
 * Called from the axios interceptor rather than from `emitApiError`, which
 * early-returns on suppressed paths (warehouse / first-mile / onboarding /
 * auth) — hooking there would drop errors on exactly those pages.
 *
 * 5xx and network failures are real defects and go to Error tracking. 4xx is
 * usually the server correctly rejecting input, so it is recorded as a plain
 * event to keep the issue list signal-heavy.
 */
export function captureApiError(error: unknown): void {
  if (!enabled) return;

  const err = error as {
    message?: string;
    config?: { method?: string; url?: string };
    response?: { status?: number };
  };

  const status = err.response?.status;
  const properties = {
    api_status: status ?? null,
    api_method: err.config?.method?.toUpperCase() ?? null,
    api_path: err.config?.url ?? null,
  };

  if (status && status < 500) {
    posthog.capture("api_error", properties);
    return;
  }

  posthog.captureException(error, properties);
}

/**
 * Identify the current user to PostHog so replays and exceptions are
 * attributable.
 *
 * Deliberately sends NO contact details. `AuthUser` carries email, phoneNumber,
 * name and username; these are railway staff, and debugging a replay never
 * requires knowing how to phone the person in it.
 */
export function useIdentify(user: AuthUser | null): void {
  const employee = user?.employee?.[0];

  useEffect(() => {
    if (!enabled) return;

    if (!user?.id) {
      posthog.reset();
      return;
    }

    posthog.identify(user.id, {
      roles: user.roles?.map((role) => role.key ?? role.id),
      status: user.status,
      is_super_admin: user.isSuperAdmin,
      organization_id: employee?.organizationId,
      unit_id: employee?.unitId,
    });
  }, [
    user?.id,
    user?.roles,
    user?.status,
    user?.isSuperAdmin,
    employee?.organizationId,
    employee?.unitId,
  ]);
}
