import Echo from "laravel-echo";
import Pusher from "pusher-js";
import { env } from "@/infrastructure/config/env";
import { tokenStorage } from "@/infrastructure/auth/token-storage";
import type { SupportActivityEvent } from "@/domain/entities/ticket";

type Listener = (event: SupportActivityEvent) => void;

/**
 * Single WebSocket connection for the support inbox, subscribed to the staff-only
 * `admin.support` channel. Disabled (no-op) when no Pusher key is configured: the
 * inbox then polls instead.
 */
class SupportRealtime {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  private echo: any = null;
  private listeners = new Set<Listener>();
  private connected = false;

  get isEnabled(): boolean {
    return typeof window !== "undefined" && !!env.pusher.key;
  }

  get isConnected(): boolean {
    return this.connected;
  }

  subscribe(listener: Listener): () => void {
    this.listeners.add(listener);
    this.connect();
    // The connection stays open for the tab: components remount often (route changes),
    // and tearing it down in between left the next connection without its subscription.
    return () => {
      this.listeners.delete(listener);
    };
  }

  private connect() {
    if (this.echo || !this.isEnabled) return;
    const token = tokenStorage.get();
    if (!token) return;

    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    (window as any).Pusher = Pusher;
    const forceTLS = env.pusher.scheme === "https";
    this.echo = new Echo({
      broadcaster: "pusher",
      key: env.pusher.key,
      cluster: env.pusher.cluster,
      wsHost: env.pusher.host || undefined,
      wsPort: env.pusher.port,
      wssPort: env.pusher.port,
      forceTLS,
      enabledTransports: ["ws", "wss"],
      disableStats: true,
      authEndpoint: env.pusher.authUrl,
      auth: { headers: { Authorization: `Bearer ${token}`, Accept: "application/json" } },
    });

    const pusher = this.echo.connector.pusher;
    pusher.connection.bind("connected", () => { this.connected = true; });
    pusher.connection.bind("disconnected", () => { this.connected = false; });
    pusher.connection.bind("unavailable", () => { this.connected = false; });

    this.echo
      .private("admin.support")
      .listen(".support-activity", (event: SupportActivityEvent) => {
        this.listeners.forEach((listener) => {
          try {
            listener(event);
          } catch (error) {
            console.error("[SupportRealtime] listener error", error);
          }
        });
      });
  }
}

export const supportRealtime = new SupportRealtime();
