import type { AnalyticsService, AnalyticsEventProperties } from "./service";

export interface UmamiConfig {
  websiteId?: string;
  apiEndpoint: string; // The endpoint to send to (proxied or direct)
  enabled: boolean;
}

export interface Logger {
  debug(msg: string, data?: any): void;
  warn(msg: string, data?: any): void;
  error(msg: string, data?: any): void;
  trace(msg: string, data?: any): void;
}

/**
 * Umami Analytics Service Implementation (Script-less/Proxy edition).
 */
export class UmamiAnalyticsService implements AnalyticsService {
  private logger?: Logger;

  constructor(
    private config: UmamiConfig,
    logger?: Logger,
  ) {
    this.logger = logger;
  }

  private async sendPayload(type: "event", data: Record<string, any>) {
    if (!this.config.enabled) return;

    const isClient = typeof window !== "undefined";
    const websiteId = this.config.websiteId;

    if (!isClient && !websiteId) {
      this.logger?.warn(
        "Umami tracking called on server but no Website ID configured",
      );
      return;
    }

    try {
      const payload = {
        website: websiteId,
        hostname: isClient ? window.location.hostname : "server",
        screen: isClient
          ? `${window.screen.width}x${window.screen.height}`
          : undefined,
        language: isClient ? navigator.language : undefined,
        referrer: isClient ? document.referrer : undefined,
        ...data,
      };

      this.logger?.trace("Sending analytics payload", { type, url: data.url });

      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), 10000);

      try {
        const response = await fetch(`${this.config.apiEndpoint}/api/send`, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "User-Agent": isClient ? navigator.userAgent : "Mintel-Server",
          },
          body: JSON.stringify({ type, payload }),
          keepalive: true,
          signal: controller.signal,
        });

        clearTimeout(timeoutId);

        if (!response.ok) {
          const errorText = await response.text();
          this.logger?.warn("Umami API responded with error", {
            status: response.status,
            error: errorText.slice(0, 100),
          });
        }
      } catch (fetchError) {
        clearTimeout(timeoutId);
        if ((fetchError as Error).name === "AbortError") {
          this.logger?.error("Umami request timed out");
        } else {
          throw fetchError;
        }
      }
    } catch (error) {
      this.logger?.error("Failed to send analytics", {
        error: (error as Error).message,
      });
    }
  }

  track(eventName: string, props?: AnalyticsEventProperties) {
    this.sendPayload("event", {
      name: eventName,
      data: props,
      url:
        typeof window !== "undefined"
          ? window.location.pathname + window.location.search
          : undefined,
    });
  }

  trackPageview(url?: string) {
    this.sendPayload("event", {
      url:
        url ||
        (typeof window !== "undefined"
          ? window.location.pathname + window.location.search
          : undefined),
    });
  }
}
