import { addEventListener, ReportBI, withoutDefaults } from '@wix/bex-core'; // withoutDefaults
import { EntityPageState } from './EntityPageState';
import { FieldValues } from 'react-hook-form';
import { action } from 'mobx';
import {
  cairoTryAgainClicked,
  cairoApiRequestDataLoadEnd,
  cairoPageCtaClicked,
  cairoPageDiscardChangesBeforeSave,
  loadStart,
  loadEnd,
} from '@wix/bex-core/bi';

export interface EntityPageStateBIReporterParams<
  T,
  V extends FieldValues = FieldValues,
> {
  reportBI: ReportBI;
  entityPageState: EntityPageState<T, V>;
}

export class EntityPageStateBIReporter<T, V extends FieldValues> {
  readonly entityPageState: EntityPageState<T, V>;
  readonly reportBI: ReportBI;
  readonly startTime: number = performance.now();
  appLoaded?: () => void;

  constructor(params: EntityPageStateBIReporterParams<T, V>) {
    this.entityPageState = params.entityPageState;
    this.reportBI = params.reportBI;
  }

  _getErrorType(e: any) {
    const isNetworkError = e?.code === 'ERR_NETWORK';
    return isNetworkError ? 'Network error' : 'Technical issue';
  }

  init() {
    const { events } = this.entityPageState;
    const disposers = [
      addEventListener(
        events,
        'save',
        action(() => {
          events.once('saveError', (err) => {
            this.reportSaveError(err, this.startTime);
          });
        }),
      ),
      (this.appLoaded = this.reportOnLoadStart(this.startTime)),
    ];

    return () => {
      disposers.forEach((disposer) => disposer());
    };
  }

  reportButtonClick({
    ctaName,
    isValid,
    additionalInfo,
  }: {
    ctaName: string;
    isValid?: boolean;
    additionalInfo?: string;
  }) {
    this.reportBI(
      withoutDefaults(cairoPageCtaClicked)({
        ctaName,
        ctaType: 'Main',
        location: 'Entity page header',
        isValid,
        additionalInfo,
      }),
    );
  }

  reportSaveTryAgain() {
    this.reportBI(
      withoutDefaults(cairoTryAgainClicked)({
        actionName: 'Saving Entity',
        loaction: 'toast',
      }),
    );
  }

  reportSaveError(e: any, startTime: number) {
    this.reportBI(
      withoutDefaults(cairoApiRequestDataLoadEnd)({
        errorType: this._getErrorType(e),
        duration: performance.now() - startTime,
      }),
    );
  }

  reportOnBeforeUnload() {
    const values = this.entityPageState.form.getValues();
    const fields = Object.keys(values);
    this.reportBI(
      withoutDefaults(cairoPageDiscardChangesBeforeSave)({
        numOfFields: fields.length,
        numOfActions: fields.reduce(
          (prev, key: any) =>
            prev + +this.entityPageState.form.getFieldState(key)?.isDirty,
          0,
        ),
      }),
    );
  }

  reportOnLoadStart(startTime: number) {
    this.reportBI(
      withoutDefaults(loadStart)({
        ...this._commonDynamicBiParams(),
      }),
    );
    return () => {
      this.reportOnLoadEnd(Math.round(performance.now() - startTime));
    };
  }

  reportOnLoadEnd(endTime: number) {
    this.reportBI(
      withoutDefaults(loadEnd)({
        ...this._commonDynamicBiParams(),
        loadingTime: endTime,
      }),
    );
  }

  _commonDynamicBiParams() {
    return {
      url: window.location.href,
      route: window.location.pathname,
      routerUsage: this.entityPageState._withinRouter,
    };
  }
}
