import { Injectable } from '@angular/core';
import { Browser } from '@capacitor/browser';
import { ConnectionStatus, Network } from '@capacitor/network';
import { AlertController, IonDatetime, ModalController, NavController } from '@ionic/angular';
import { Observable } from 'rxjs';
import Swiper from 'swiper';

import { ImageModalComponent } from '@components/image-modal/image-modal.component';
import { ReportContentComponent } from '@components/report-content/report-content.component';
import { api } from '@enums/api.enum';
import { GJainStorage } from '@enums/gjain-storage.enum';
import { Roots } from '@enums/root.enum';
import { CommonResponse } from '@interfaces/common';
import { AlertService } from '@services/alert.service';
import { HttpRequestService } from '@services/http-request.service';
import { StateManagementService } from '@services/state-management.service';
declare let google: any;
@Injectable({
  providedIn: 'root'
})
export class UtilityService {

  constructor(
    private modalController: ModalController,
    private alert: AlertService,
    private stateManagementService: StateManagementService,
    private navController: NavController,
    private httpRequestService: HttpRequestService,
    private alertController: AlertController,
  ) { }

  async defaultButton(confirmButton: 'DONE' | 'CANCEL', ionDatetime: IonDatetime): Promise<void> {
    const nativeElement = (ionDatetime as any).el;
    if (nativeElement.classList.contains('show-month-and-year')) {
      const el: any = nativeElement.shadowRoot.querySelector('.calendar-month-year');
      el.querySelector('ion-item').shadowRoot.querySelector('button').click();
      return;
    }
    if (confirmButton === 'DONE') {
      await ionDatetime?.confirm(true);
    } else {
      await ionDatetime?.cancel(true);
    }
  }

  createAutocomplete(addressEl: HTMLInputElement, componentRestrictions = ['IN']): Observable<any> {
    const autocomplete = new google.maps.places.Autocomplete(addressEl, {
      types: [], strictBounds: false, componentRestrictions: {
        country: componentRestrictions
      }
    });
    return new Observable((sub: any) => {
      google.maps.event.addListener(autocomplete, 'place_changed', () => {
        const place = autocomplete.getPlace();
        if (!place.geometry) {
          sub.error({
            message: 'Autocomplete returned place with no geometry'
          });
        } else {
          sub.next(place);
        }
      });
    });
  }

  getAddress(address: string): any {
    const geocoder = new google.maps.Geocoder();
    return new Observable((sub: any) => {
      geocoder.geocode({ 'address': address }, function (results, status) {
        if (status == 'OK') {
          sub.next(results);
        }
      });
    });
  }

  handleInternetStatus() {
    function displayToaster(status: ConnectionStatus) {
      if (!status.connected) {
        this.alert.showToasterError('Please check internet connectivity');
      }
    }
    Network.addListener('networkStatusChange', status => {
      displayToaster.bind(this)(status);
    });
    Network.getStatus().then(status => {
      displayToaster.bind(this)(status);
    });
  }

  async imagePreview(url: string, slider?: Swiper) {
    if (slider) {
      slider.isLocked = true;
    }
    const modal = await this.modalController.create({
      component: ImageModalComponent,
      componentProps: {
        imgUrl: url,
        slider
      }
    });
    return await modal.present();
  }

  async logout() {
    const deviceUUID = await this.stateManagementService.storage.get(GJainStorage.deviceUUID);
    const params = {
      device_id: deviceUUID,
    };
    this.httpRequestService.get(api.logout, deviceUUID ? params : '').then((res: any) => {
      if (res.status === 200) {
        this.stateManagementService.token = '';
        this.stateManagementService.storage.remove(GJainStorage.loginType);
        this.stateManagementService.storage.remove(GJainStorage.profileData);
        this.stateManagementService.storage.remove(GJainStorage.userData).then(() => {
          this.navController.navigateRoot(Roots.auth + '/' + Roots.login);
          this.alert.showToaster('Logout successfully...');
        });
      }
      this.alert.showToaster(res.message);
      this.alert.hideLoader();
    }).catch(() => {
      this.alert.hideLoader();
    });
  }

  async openReport(data) {
    const modal = await this.modalController.create({
      component: ReportContentComponent,
      componentProps: { data },
      mode: 'ios',
      backdropDismiss: true,
      breakpoints: [0, 0.8, 1],
      initialBreakpoint: 0.8,
      canDismiss: true
    });
    return await modal.present();
  }

  async hidePost(post) {
    const alert = await this.alertController.create({
      header: 'Confirm!',
      message: `Are you sure you want to ${post.hide ? 'show' : 'hide'} this post?`,
      buttons: [{
        text: 'Yes',
        handler: async () => {
          this.alert.showLoader();
          const status = post.hide ? 0 : 1; // 0: Unhide, 1: Hide
          this.httpRequestService.post(api.hideThisPost, {
            id: post.id,
            status
          })
            .then((res: CommonResponse) => {
              post.hide = status;
              this.alert.showToaster(res.message);
            }).finally(() => {
              this.alert.hideLoader();
            });
        }
      }, {
        text: 'No',
        role: 'cancel',
        cssClass: 'secondary'
      }]
    });
    await alert.present();
  }

  async presentConfirm(
    message: string,
    noText = 'No',
    okText = 'Yes',
    header = 'Confirm!'
  ): Promise<number> {

    return new Promise(async (resolve) => {
      const alert = await this.alertController.create({
        header,
        message,
        mode: 'ios',
        buttons: [{
          text: okText,
          handler: () => {
            resolve(1);
          }
        }, {
          text: noText,
          role: 'cancel',
          cssClass: 'secondary',
          handler: () => {
            resolve(0);
          }
        }]
      });
      await alert.present();
    });
  }

  async presentAcceptDecline(
    message: string,
    noText = 'Decline',
    okText = 'Accept',
    header = 'Membership Request'): Promise<number> {

    return new Promise(async (resolve) => {
      const alert = await this.alertController.create({
        header,
        message,
        mode: 'ios',
        buttons: [{
          text: okText,
          handler: () => {
            resolve(1);
          }
        }, {
          text: noText,
          handler: () => {
            resolve(2);
          }
        }, {
          text: 'Cancel',
          role: 'cancel',
          cssClass: 'secondary',
          handler: () => {
            resolve(0);
          }
        }]
      });
      await alert.present();
    });
  }

  openGoogleMap(lat: string, lng: string) {
    if (lat && lng) {
      window.open(`https://www.google.com/maps/search/?api=1&query=${lat},${lng}`, '_system');
    }
  }

  convertLinksToClickableLinks(text: string) {
    const urlRegex = /(((https?:\/\/)|(www\.))[^\s]+)/g;
    return text?.replace(urlRegex, (url: string) => {
      if (url.startsWith('http')) {
        return '<a onclick="event.stopPropagation();" target="_system" href="' + url + '">' + url + '</a>';
      }
      return '<a onclick="event.stopPropagation();" target="_system" href="https://' + url + '">' + url + '</a>';
    });
  }

  extractMentionedNames(description: string, mentionsArr: any[]) {
    const regex = /(?<=@)[^@]+/g;
    const matches = description.match(regex);
    if (matches) {
      return mentionsArr.filter(item => matches.some(str => str.startsWith(item.name)));
    }
    return [];
  }

  extractWordsAfterAtSign(str) {
    const lastLine = str.split('\n').pop();
    const lastWords = lastLine.split(/\s+/).slice(-3);
    for (let i = lastWords.length - 1; i >= 0; i--) {
      if (lastWords[i].charAt(0) === '@') {
        const wordsAfterAtSign = lastWords.slice(i).join(' ');
        return wordsAfterAtSign;
      }
    }
    return '';
  }

  async openBrowser(url: string) {
    await Browser.open({ url });
  }

  isSameStr(currentValue: string, prevValue: string, isIgnoredBlankCall = false): boolean {
    let res = true;
    if ((prevValue?.trim() && !currentValue?.trim()) ||
      (!prevValue?.trim() && currentValue?.trim()) ||
      (prevValue?.trim() && currentValue?.trim() && prevValue?.trim() !== currentValue?.trim())) {
      res = false;
    }
    if (isIgnoredBlankCall && !currentValue?.trim()) { res = true; }
    return res;
  }

  isMaxFileSize(size: number): boolean {
    const MAX_SIZE = 2 * 1024 * 1024; // 2MB in bytes
    return size > MAX_SIZE ? true : false;
  }

}
