import { CommonModule } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { Component, signal } from '@angular/core';
import {
  FormControl,
  FormGroup,
  FormsModule,
  ReactiveFormsModule,
  Validators,
} 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 { MatListModule } from '@angular/material/list';
import { MatSelectModule } from '@angular/material/select';
import { error } from 'console';
import { forkJoin, map } from 'rxjs';
import { WidgetService } from 'src/app/widget-configuration.service';

@Component({
  selector: 'app-call',
  imports: [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    MatCardModule,
    MatListModule,
    MatFormFieldModule,
    MatInputModule,
    MatSelectModule,
    MatButtonModule,
  ],
  templateUrl: './call.component.html',
  styleUrl: './call.component.scss',
  standalone: true,
})
export class CallComponent {
  client: any;
  widgetConf: any;
  serverUrl!: string;
  formId!: string;
  sessionId!: string;

  dynamicForm: FormGroup = new FormGroup({});
  fields = signal<any[]>([]);

  callServices = signal<any[]>([]);
  sessionState = signal<string>('');
  callEngagement = signal<boolean>(true);
  selectedService = new FormControl();
  bodyMessage = new FormControl();

  constructor(private widgetService: WidgetService, private http: HttpClient) {
    this.client = this.widgetService.getClient();
    this.serverUrl = this.widgetService.getServerUrl();
    this.widgetConf = this.client.getConfiguration();

    this.loadCallServices();
    this.loadFormConfigurations();
  }

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

    console.log('Servizi PHONE_CALL:', services);
    this.callServices.set(services);
  }

  // recupero il form associato ai vari servizi (in modo da sapere quali campi vanno compilati e inviati all'apertura di una nuova sessione)
  private loadFormConfigurations() {
    const formRequests: any[] = [];
    const seenFormIds = new Set<string>();

    this.widgetConf.servicesConfiguration?.forEach((conf: any) => {
      conf.services?.forEach((service: any) => {
        if (service.formId && !seenFormIds.has(service.formId)) {
          seenFormIds.add(service.formId);
          this.formId = service.formId;

          const request$ = this.http
            .get(
              `${this.serverUrl}/apps/widget/conf/forms/form_${service.formId}.json`
            )
            .pipe(
              map((config: any) => ({
                formId: service.formId,
                config,
              }))
            );

          formRequests.push(request$);
        }
      });
    });

    if (formRequests.length) {
      forkJoin(formRequests).subscribe((formConfigs: any[]) => {
        console.log('Form configs ricevuti:', formConfigs);

        const allFields = formConfigs.flatMap((fc) => fc.config.fields || []);
        const sortedFields = allFields.sort((a, b) => +a.order - +b.order);

        this.fields.set(sortedFields);
        this.buildForm(sortedFields);
      });
    }
  }

  // costruisco il form con i campi che mi sono arrivati dal json del form configurato
  private buildForm(fields: any[]) {
    const formGroup: { [key: string]: FormControl } = {};

    fields.forEach((field) => {
      const validators = [];

      if (field.required === 'TRUE') {
        validators.push(Validators.required);
      }

      if (field.validationPattern) {
        validators.push(Validators.pattern(field.validationPattern));
      }

      formGroup[field.key] = new FormControl(
        field.defaultValue || '',
        validators
      );
    });

    this.dynamicForm = new FormGroup(formGroup);
    console.log('Form created:', this.dynamicForm);
  }

  openCallSession() {
    this.sessionSubscription();

    if (this.dynamicForm.invalid) return;

    const formValues = this.dynamicForm.value;

    const formattedFields = this.fields().map((field: any) => ({
      id: field.key,
      label: field.label,
      value: formValues[field.key],
    }));

    this.client
      .callChannelSessionNew(
        this.selectedService.value?.code, // id servizio selezionato
        null, // nome cliente
        null, // mail cliente
        null, // callMeOnThisNumber
        formattedFields, // form fields
        this.formId, // id della form associata al servizio
        this.widgetService.widgetId // id widget
      )
      .then((sessionId: string) => {
        console.log('callChannelSessionNew SUCCESS');
        console.log('Session id:', sessionId);
        this.sessionId = sessionId;
      })
      .catch((err: any) => {
        console.error('callChannelSessionNew ERROR', err);
      });
  }

  sessionSubscription() {
    // sottoscrizione per monitorare le stato del canale TELEFONICO
    this.client.callChannelSessionMonitor().subscribe({
      next: (session: any) => {
        console.log('callChannelSessionMonitor:', session);
        if (session.sessionState == 'ACTIVE') {
          switch (session.state) {
            case 'NEW_OUTBOUND': // nuova chiamata in uscita
              console.log('callChannelSessionMonitor session: NEW_OUTBOUND');
              this.callEngagement.set(false);
              this.sessionState.set(session.state);
              break;

            case 'CONNECTED':
              console.log('callChannelSessionMonitor session: CONNECTED');
               this.sessionState.set(session.state);
              break;

            default:
              console.warn('callChannelSessionMonitor session: stato sconosciuto', session.state);
              break;
          }
        } else if (session.sessionState == 'CLOSED') {
          // chiamata terminata
          console.log('call session CLOSED');
          this.sessionState.set('CLOSED');
        }
      },
      error: (err: any) => {
        console.error('callChannelSessionMonitor ERROR:', err);
      },
    });
  }

  /** CHIUSURA CHIAMATA */

  closeCallSession() {
    // metodo per chiudere una sessione PHONE-CALL
    this.client
      .callChannelSessionClose(this.sessionId)
      .then((res: boolean) => {
        console.log('callChannelSessionClose SUCCESS');
      })
      .catch((err: any) => {
        console.error('callChannelSessionClose ERROR', err);
      });
  }
}
