import assert from 'assert';

import { IChannel } from '../interfaces/channel';
import { IInteractionPayloadAccessor } from '../interfaces/request-from-slack';

import loggerFactory from './logger';

const logger = loggerFactory('@growi/slack:utils:interaction-payload-accessor');


export class InteractionPayloadAccessor implements IInteractionPayloadAccessor {

  private payload: any;

  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
  constructor(payload: any) {
    this.payload = payload;
  }

  firstAction(): any | null {
    const actions = this.payload.actions;

    if (actions != null && actions[0] != null) {
      return actions[0];
    }

    return null;
  }

  getResponseUrl(): string {
    const responseUrl = this.payload.response_url;
    if (responseUrl != null) {
      return responseUrl;
    }

    const responseUrls = this.payload.response_urls;
    assert(responseUrls != null);
    assert(responseUrls[0] != null);

    return responseUrls[0].response_url;
  }

  getStateValues(): any | null {
    const state = this.payload.state;
    if (state != null && state.values != null) {
      return state.values;
    }

    const view = this.payload.view;
    if (view != null && view.state != null && view.state.values != null) {
      return view.state.values;
    }

    return null;
  }

  getViewPrivateMetaData(): any | null {
    const view = this.payload.view;

    if (view != null && view.private_metadata) {
      return JSON.parse(view.private_metadata);
    }

    return null;
  }

  getActionIdAndCallbackIdFromPayLoad(): {[key: string]: string} {
    const actionId = this.firstAction()?.action_id || '';
    const callbackId = this.payload.view?.callback_id || '';

    return { actionId, callbackId };
  }

  getChannel(): IChannel | null {
    // private_metadata should have the channelName parameter when view_submission
    const privateMetadata = this.getViewPrivateMetaData();
    if (privateMetadata != null && privateMetadata.channelName != null) {
      throw new Error('PrivateMetaDatas are not implemented after removal of modal from slash commands. Use payload instead.');
    }
    const channel = this.payload.channel;
    if (channel != null) {
      return channel;
    }

    return null;
  }

  getOriginalData(): any | null {
    const value = this.firstAction()?.value;
    if (value == null) return null;

    const { originalData } = JSON.parse(value);
    if (originalData == null) return JSON.parse(value);

    let parsedOriginalData;
    try {
      parsedOriginalData = JSON.parse(originalData);
    }
    catch (err) {
      logger.error('Failed to parse original data:\n', err);
      return null;
    }

    return parsedOriginalData;
  }

}
