import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { IsNull, Not, Repository } from 'typeorm';
import { ZoomAnalyticsSessionSummary } from 'src/common/entities';
import { AppLoggerService } from 'src/common/services/logger.service';
import { handleKnownErrors } from 'src/common/utils/handle-error.util';
import { ERROR_CODES } from 'src/common/constants/error-string-constants';

/** Owns `zoom_analytics_session_summary` — one upserted row per session. */
@Injectable()
export class ZoomAnalyticsSessionSummaryRepository {
  constructor(
    @InjectRepository(ZoomAnalyticsSessionSummary)
    private readonly repo: Repository<ZoomAnalyticsSessionSummary>,
    private readonly logger: AppLoggerService,
  ) {}

  async findBySessionId(sessionId: number): Promise<ZoomAnalyticsSessionSummary | null> {
    try {
      return await this.repo.findOne({ where: { sessionId } });
    } catch (error) {
      this.logger.error('Error finding Zoom analytics session summary', error?.stack, { error, sessionId });
      handleKnownErrors(ERROR_CODES.ZOOM_ANALYTICS_GET_FAILED, error);
    }
  }

  create(data: Partial<ZoomAnalyticsSessionSummary>): ZoomAnalyticsSessionSummary {
    return this.repo.create(new ZoomAnalyticsSessionSummary(data));
  }

  async save(row: ZoomAnalyticsSessionSummary): Promise<ZoomAnalyticsSessionSummary> {
    try {
      return await this.repo.save(row);
    } catch (error) {
      this.logger.error('Error saving Zoom analytics session summary', error?.stack, { error });
      handleKnownErrors(ERROR_CODES.ZOOM_ANALYTICS_SAVE_FAILED, error);
    }
  }

  /** Upserts by sessionId — reconciliation is idempotent by construction. */
  async upsert(data: Partial<ZoomAnalyticsSessionSummary> & { sessionId: number }): Promise<ZoomAnalyticsSessionSummary> {
    const existing = await this.findBySessionId(data.sessionId);
    const row = existing ? Object.assign(existing, data) : this.create(data);
    return this.save(row);
  }

  /** Sessions that have started but not yet been reconciled — the live-poll scheduler's target set. */
  async findLive(): Promise<ZoomAnalyticsSessionSummary[]> {
    try {
      return await this.repo.find({ where: { actualStartAt: Not(IsNull()), reconciledAt: IsNull() } });
    } catch (error) {
      this.logger.error('Error finding live Zoom analytics sessions', error?.stack, { error });
      handleKnownErrors(ERROR_CODES.ZOOM_ANALYTICS_GET_FAILED, error);
    }
  }
}
