import { Injectable } from '@nestjs/common';
import { AppLoggerService } from 'src/common/services/logger.service';
import {
  ZOOM_ANALYTICS_API_PATHS,
  ZOOM_ANALYTICS_HTTP_STATUS,
  ZOOM_ANALYTICS_LOG,
} from '../constants/zoom-analytics.constants';
import { ZoomAnalyticsHttpUtil } from './zoom-analytics-http.util';
import { ZoomAnalyticsResourceType } from 'src/common/enum/zoom-analytics-resource-type.enum';

export interface ZoomDashboardParticipant {
  user_email?: string;
  email?: string;
  device?: string;
  /** Zoom's dashboard participants response reports this as `user_name` on some endpoints, `name` on others — check both defensively. */
  user_name?: string;
  name?: string;
  [key: string]: unknown;
}

/**
 * Client for the Dashboard/Metrics API's live-participants endpoints —
 * `GET /metrics/webinars/{id}/participants` or `/metrics/meetings/{id}/participants`
 * depending on the resource type — the one pair of Zoom endpoints that
 * returns data for a session that's still *live* (unlike every Report-tier
 * endpoint, which is post-session only), backing the self-heal poll. Requires
 * a Business+ plan and, per Zoom's granular scope model,
 * `dashboard:read:list_meeting_participants:admin` for meetings /
 * `dashboard:read:list_webinar_participants:admin` for webinars — confirmed
 * missing on this account's Server-to-Server app as of 2026-07-13 (Zoom
 * returns HTTP 400, code 4711, "does not contain scopes"). Degrades
 * gracefully (returns `null`, logs once) instead of throwing so the
 * live-poll fallback simply no-ops until that access exists.
 */
@Injectable()
export class ZoomDashboardApiClient {
  private unavailableWarned = false;

  constructor(
    private readonly http: ZoomAnalyticsHttpUtil,
    private readonly logger: AppLoggerService,
  ) {}

  async fetchLiveParticipants(
    externalId: string,
    resourceType: ZoomAnalyticsResourceType,
  ): Promise<ZoomDashboardParticipant[] | null> {
    const path =
      resourceType === ZoomAnalyticsResourceType.MEETING
        ? ZOOM_ANALYTICS_API_PATHS.DASHBOARD_MEETING_PARTICIPANTS(externalId)
        : ZOOM_ANALYTICS_API_PATHS.DASHBOARD_WEBINAR_PARTICIPANTS(externalId);
    try {
      const data = await this.http.get<{ participants?: ZoomDashboardParticipant[] }>(path, {
        page_size: 300,
      });
      return data?.participants ?? [];
    } catch (error: any) {
      const status = error?.response?.status;
      if (
        status === ZOOM_ANALYTICS_HTTP_STATUS.UNAUTHORIZED ||
        status === ZOOM_ANALYTICS_HTTP_STATUS.FORBIDDEN ||
        status === ZOOM_ANALYTICS_HTTP_STATUS.NOT_FOUND
      ) {
        if (!this.unavailableWarned) {
          this.logger.warn(ZOOM_ANALYTICS_LOG.LIVE_POLL_UNAVAILABLE, { externalId, resourceType, status });
          this.unavailableWarned = true;
        }
        return null;
      }
      throw error;
    }
  }
}
