import {App, GenericMessageEvent, MessageEvent} from "@slack/bolt";
import {WebClient} from "@slack/web-api";

import {TicketMessagePostedFromSlackWorkflow} from "../bl/ticket/ticket-message-posted-from-slack.workflow";
import {Message} from "../entity/message";
import {Ticket} from "../entity/ticket";

import {SlackBootstrapper} from "./slack-bootstrapper";

export class SlackWorker {

  get slackApp(): App {
    return this.parent.slackApp;
  }

  private slackApi: WebClient;

  private workingChannelId: string | undefined;

  constructor(
    private parent: SlackBootstrapper
  ) {
    this.slackApi = new WebClient(process.env.SLACK_BOT_TOKEN);

    this.findWorkingChannel();
  }

  private async findWorkingChannel() {
    const result: any = await this.slackApi.conversations.list();

    const channel = result.channels.find((c: any) => c.name === process.env.SLACK_WORKING_CHANNEL_NAME);
    if (channel == null) {
      return;
    }

    this.workingChannelId = channel.id;
    console.log('channel found', this.workingChannelId);

    this.addEventListeners();
  }

  public async postTestMessage() {
    if (this.workingChannelId == null) {
      console.warn('Test message was not send: workingChannelId not present');
      return;
    }

    const result: any = await this.slackApi.chat.postMessage({
      channel: this.workingChannelId,
      text: 'Test message\n\nnew *line*'
    });

    await this.slackApi.chat.postMessage({
      channel: this.workingChannelId,
      thread_ts: result.ts,
      text: 'Thread message'
    });

    console.log('message sent', result);
  }

  private addEventListeners() {
    this.slackApp.message('', async (e) => await this.onMessagePosted(e));
  }

  private async onMessagePosted(e: any) {
    await TicketMessagePostedFromSlackWorkflow.messagePosted(e.message as GenericMessageEvent);
  }

  public async createThreadForTicketId(ticket: Ticket): Promise<any> {
    this.checkForWorkingChannelId();

    return await this.slackApi.chat.postMessage({
      channel: this.workingChannelId,
      text: `*Ticket name:* ${ticket.name}\n*License:* ${ticket.licenseeId}`
    });
  }

  public async postTicketMessage(ticket: Ticket, message: Message) {
    await this.slackApi.chat.postMessage({
      channel: this.workingChannelId,
      thread_ts: ticket.slackThreadTs,
      text: message.body
    });
  }

  private checkForWorkingChannelId() {
    if (this.workingChannelId == null) {
      throw new Error('SlackWorker: failed to create thread for Ticket - `workingChannelId` is not present');
    }
  }

}
