import { CommonModule } from '@angular/common';
import { Component, OnDestroy, signal } from '@angular/core';
import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { WidgetService } from 'src/app/widget-configuration.service';
import { MatIconModule } from '@angular/material/icon';
import { MatOptionModule } from '@angular/material/core';

export enum TypingStatus {
  COMPOSING = 'COMPOSING', // sta scrivendo 
  WROTE = 'WROTE',         // scritto ed inviato
  IDLE = 'IDLE'            // inattivo
}

@Component({
  selector: 'app-chat',
  imports: [
    CommonModule,
    MatCardModule,
    MatFormFieldModule,
    MatInputModule,
    MatSelectModule,
    MatButtonModule,
    ReactiveFormsModule,
    FormsModule,
    MatIconModule,
    MatOptionModule,
  ],
  templateUrl: './chat.component.html',
  styleUrl: './chat.component.scss',
  standalone: true,
})
export class ChatComponent implements OnDestroy {
  client: any;
  widgetConf: any;
  sessionId: any; // id della sessione (generato all'apertura di una nuova chat)

  selectedService = new FormControl();
  bodyMessage = new FormControl();
  outboundMessage = new FormControl('');

  chatEngagement = signal<boolean>(true);
  chatServices = signal<any[]>([]);
  connectingToOperator = signal<boolean>(false);
  composingInbound = signal<boolean>(false);
  isChatClosed = signal<boolean>(false);

  messages = signal<
    { type: 'INBOUND' | 'OUTBOUND'; text: string; author?: string }[]
  >([]);

  constructor(private widgetService: WidgetService) {
    this.client = this.widgetService.getClient();
    this.widgetConf = this.client.getConfiguration();

    this.client.chat;
    this.loadChatServices();
    this.monitorChatSession();
  }

  ngOnDestroy(): void {
    // se si esce dalla pagina, la sessione di chat viene chiusa
    this.closeChatSession();
  }

  /** CHAT ENGAGEMENT */

  // recupero i servizi disponibili per il canale MAIL
  private loadChatServices() {
    const services = this.widgetConf.servicesConfiguration
      .filter((conf: any) => conf.type === 'CHAT')
      .flatMap((conf: any) => conf.services);

    console.log('Servizi CHAT:', services);
    this.chatServices.set(services);
  }

  private monitorChatSession() {
    // importante sottoscriversi per sapere lo stato del canale
    this.client.chatChannelSessionMonitor().subscribe({
      next: (session: any) => {
        console.log('chatChannelSessionMonitor session:', session);

        // per sapere quando si connette l'operatore
        if (session.step.typeStep == 'CONNECTED') {
          this.connectingToOperator.set(false);
        }
      },
      error: (err: any) => {
        console.log('chatChannelSessionMonitor ERROR:', err);
      },
    });
  }

  openChatSession() {
    // metodo per creare nuova sessione CHAT
    this.client
      .chatChannelSessionNew({
        force: false, // forzare l'apertura di una nuova sessione di chat (chiudendo eventuali altre sessioni di chat aperte)
        service: this.selectedService.value?.code, // id del servizio che si desidera contattare
        firstMessage: this.bodyMessage.value, // primo messaggio di contatto (dal cliente)
        widgetId: this.widgetService.widgetId, // id della widget
      })
      .then((sessionId: string) => {
        console.log('chatChannelSessionNew SUCCESS');
        console.log('chatChannelSessionNew sessionId:', sessionId);
        this.sessionId = sessionId;
        this.chatEngagement.set(false);
        this.eventSubscription();
        this.connectingToOperator.set(true);
      })
      .catch((err: any) => {
        console.error('chatChannelSessionNew ERROR', err);
      });
  }

  /** CHAT SESSION */

  eventSubscription() {
    // metodo per sottoscriversi agli eventi della sessione chat appena aperta
    this.client
      .chatChannelEventSubscription(this.sessionId)
      .subscribe((chatEvent: any) => {
        console.log('ChatEvent', chatEvent);

        if (chatEvent.status == 'COMPOSING') {
          // corrisponde al 'Sta scrivendo...'
          this.composingInbound.set(true);
        } else {
          // in qualsiasi altro stato non voglio vedere il 'Sta scrivendo...'
          this.composingInbound.set(false);
        }

        // non appena mi arriva un messaggio registro il suo messageId
        let messageId = chatEvent.id;
        if (messageId) {
          this.markMessageAsReceived(messageId); // messageId che mi servirà per confermare la ricezione del messaggio
          this.markMessageAsRead(messageId); // messageId che mi servirà per confermare la lettura del messaggio
          this.messages.update((prevMessages) => [
            ...prevMessages,
            {
              type: chatEvent.direction as 'INBOUND' | 'OUTBOUND',
              text: chatEvent.message,
              author: chatEvent.direction === 'INBOUND' ? 'Operatore' : 'Io',
            },
          ]);
        }
      });
  }

  sendMessage() {
    // metodo per inviare un messaggio
    this.client
      .chatSendMessage(
        this.sessionId, // id della sessione di chat attiva
        this.outboundMessage.value, // testo del messaggio da inviare
        TypingStatus.WROTE, // stato 
        false // indica che non è un messaggio di sistema o di saluto automatico (notifyGreetingMessage)
      )
      .then((res: boolean) => {
        console.log('chatSendMessage DONE', res);
        this.outboundMessage.reset();
      })
      .catch((err: any) => {
        console.log('chatSendMessage ERROR', err);
      });
  }

  markMessageAsReceived(messageId: string) {
    // metodo per contrassegnare il messaggio come ricevuto
    this.client
      .chatChannelReceivedMessage(this.sessionId, messageId)
      .then((res: boolean) => {
        console.log('chatChannelReceivedMessage DONE', res);
      })
      .catch((err: any) => {
        console.log('chatChannelReceivedMessage ERROR', err);
      });
  }

  markMessageAsRead(messageId: string) {
    // metodo per contrassegnare il messaggio ricevuto come letto
    this.client
      .chatChannelReadMessage(this.sessionId, messageId)
      .then((res: boolean) => {
        console.log('chatChannelReadMessage DONE', res);
      })
      .catch((err: any) => {
        console.log('chatChannelReadMessage ERROR', err);
      });
  }

  /** CLOSE SESSION */

  closeChatSession() {
    // metodo per chiudere la sessione CHAT
    this.client
      .chatChannelSessionClose(this.sessionId)
      .then((res: boolean) => {
        console.log('chatChannelSessionClose DONE', res);
        this.isChatClosed.set(true);
      })
      .catch((err: any) => {
        console.log('chatChannelSessionClose ERROR', err);
      });
  }

  // al termine della sessione CHAT l'utente può scegliere se ricevere un riassunto della chat via email
  sendRecap(email: string) {
    // metodo per richiedere il riassunto della sessione
    this.client
      .chatSendRecapOfSession(this.sessionId, email)
      .then((res: boolean) => {
        console.log('chatSendRecapOfSession DONE', res);
      })
      .catch((err: any) => {
        console.log('chatSendRecapOfSession ERROR', err);
      });
  }
}
