import { DatePipe, NgClass, NgFor, NgIf, formatDate } from '@angular/common';
import { ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { MessagePopoverComponent } from '@components/message-popover/message-popover.component';
import { api } from '@enums/api.enum';
import { GJainStorage } from '@enums/gjain-storage.enum';
import { Roots } from '@enums/root.enum';
import { Message } from '@interfaces/common';
import { IonContent, IonTextarea, IonicModule, NavController, PopoverController } from '@ionic/angular';
import { LocalDatePipe } from '@pipes/local-date.pipe';
import { HttpRequestService } from '@services/http-request.service';
import { StateManagementService } from '@services/state-management.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

@Component({
  selector: 'app-message-chat',
  templateUrl: './message-chat.page.html',
  styleUrls: ['./message-chat.page.scss'],
  standalone: true,
  imports: [IonicModule, NgIf, NgFor, NgClass, FormsModule, DatePipe, LocalDatePipe]
})
export class MessageChatPage implements OnInit, OnDestroy {
  @ViewChild('text') textElement: IonTextarea;
  @ViewChild('content', {
    static: false
  }) content: IonContent;
  backURL = '/message';
  messages: {
    [timeStr: string]: Array<Message>;
  } = null;
  page = 1;
  lastPage = 1;
  total = 0;
  loader: boolean;
  userId: number;
  currentUser: any;
  imageURL: string;
  messageInput: string;
  userName: string;
  destroy$: Subject<boolean> = new Subject<boolean>();
  isEnabledTopInfiniteScroll: boolean;
  today: string;
  popover: HTMLIonPopoverElement = null;
  allDates: Array<string> = [];
  isBlocked: number;

  constructor(
    private popoverCtrl: PopoverController,
    private httpService: HttpRequestService,
    private cRoute: ActivatedRoute,
    private stateManagementService: StateManagementService,
    private changeRef: ChangeDetectorRef,
    private navCtrl: NavController,
  ) { }


  ngOnInit() {
    this.userId = +this.cRoute.snapshot.paramMap.get('userId') || 0;
    this.userName = this.cRoute.snapshot.paramMap.get('name') === 'null' ?
      'Global Jain Member' : this.cRoute.snapshot.paramMap.get('name');
    this.fetchMessages();
    this.getStorage();
    this.today = formatDate(new Date(), 'yyyy/MM/dd', 'en-US');
    this.stateManagementService.messageDetailObservable.pipe(
      takeUntil(this.destroy$)
    ).subscribe((res: Message) => {
      if (res.user_id !== this.userId) {
        return;
      }
      if (!Object.hasOwn(this.messages, this.today)) {
        this.messages = { ...this.messages, ...{ [this.today]: [] } };
      }
      this.messages[this.today].push({
        id: res.id,
        avatar: res.avatar,
        avatar_url: res.avatar_url,
        name: res.name,
        user_id: res.user_id,
        message: res.message,
        created_at: res.created_at,
        unread_count: res.unread_count
      });
      this.changeRef.detectChanges();
      setTimeout(() => {
        this.content.scrollToBottom(200);
      }, 200);
    });
    this.stateManagementService.messageClearObservable.pipe(
      takeUntil(this.destroy$)
    ).subscribe(() => {
      this.messages = null;
      this.allDates = [];
      this.popover.dismiss();
      this.changeRef.detectChanges();
    });
    this.stateManagementService.messageThreadRemoveObservable.pipe(
      takeUntil(this.destroy$)
    ).subscribe(() => {
      this.popover.dismiss();
      this.navCtrl.navigateBack(this.backURL);
    });
  }

  async messagePopup(ev: any) {
    this.popover = await this.popoverCtrl.create({
      component: MessagePopoverComponent,
      event: ev,
      cssClass: 'message-popover',
      animated: true,
      showBackdrop: true,
      mode: 'md',
      componentProps: {
        shravakId: this.userId,
        messageExist: (this.messages && Object.keys(this.messages).length) ? true : false
      }
    });
    return await this.popover.present();
  }

  async getStorage() {
    this.currentUser = await this.stateManagementService.storage.get(GJainStorage.userData);
  }

  loadData(event: any) {
    if (this.page === this.lastPage) {
      event.target.disabled = true;
      return;
    }
    this.page++;
    this.fetchMessages().then(() => {
      event.target.complete();
      this.isEnabledTopInfiniteScroll = false;
    });
  }

  fetchMessages(loader = true) {
    if (this.page === 1 && loader) {
      this.loader = true;
    }
    const params = {
      page: this.page,
      user_id: null,
      id: null
    };
    if (+this.cRoute.snapshot.paramMap.get('userId')) {
      params.user_id = +this.cRoute.snapshot.paramMap.get('userId');
    }
    if (+this.cRoute.snapshot.paramMap.get('id')) {
      params.id = +this.cRoute.snapshot.paramMap.get('id');
    }
    return new Promise((resolve, reject) => {
      this.httpService.get(api.messageList, params)
        .then((res: any) => {
          this.isBlocked = res.data.is_blocked;
          this.imageURL = res.data.receiver_image;
          this.loader = false;
          if (!Array.isArray(res.data)) {
            for (const key in res.data.data) {
              if (Object.hasOwn(res.data.data, key)) {
                if (!this.messages) {
                  this.messages = {};
                }
                if (Object.hasOwn(this.messages, key)) {
                  this.messages[key] = [...res.data.data[key], ...this.messages[key]];
                } else {
                  this.allDates.push(key);
                  this.messages[key] = res.data.data[key];
                }
              }
            }
            this.allDates.sort((a, b) => new Date(a).valueOf() - new Date(b).valueOf());
            this.total = res.data.total;
            this.lastPage = res.data.last_page;
            if (this.page === this.lastPage) {
              this.isEnabledTopInfiniteScroll = false;
            }
            if (this.page === 1) {
              setTimeout(() => {
                this.content.scrollToBottom();
              }, 300);
            }
          }
          resolve(true);
        }, (err) => {
          this.loader = false;
          reject(err);
        });
    });
  }

  onScroll(event: any) {
    if (event.detail.deltaY < 0) {
      this.isEnabledTopInfiniteScroll = true;
    }
  }

  sendMessage() {
    this.today = formatDate(new Date(), 'yyyy/MM/dd', 'en-US');
    const now = new Date();
    const createdAt = formatDate(new Date(now.getTime()), 'yyyy/MM/dd HH:mm:ss', 'en-US');
    if (this.messageInput && this.messageInput.trim()) {
      if (!this.messages) {
        this.messages = {};
      }
      if (!Object.hasOwn(this.messages, this.today)) {
        this.allDates.push(this.today);
        this.messages = { ...this.messages, ...{ [this.today]: [] } };
      }
      this.messages[this.today].push({
        id: 0,
        avatar: '',
        avatar_url: '',
        name: this.currentUser.name,
        user_id: this.currentUser.id,
        message: this.messageInput,
        created_at: createdAt,
        unread_count: 0
      });
      const messageToSend = this.messageInput;
      this.messageInput = '';
      setTimeout(() => {
        this.content.scrollToBottom(200);
      }, 200);
      this.httpService.post(api.sendMessage, {
        receiver_id: this.userId,
        message: messageToSend
      }).then((res: any) => {
        this.stateManagementService.messageObservable.next({
          id: +res.data,
          avatar: '',
          avatar_url: this.imageURL,
          message: messageToSend,
          user_id: this.userId,
          created_at: createdAt,
          name: this.userName,
          unread_count: 0
        });
      }, () => {
        this.messageInput = messageToSend;
        this.messages[this.today].pop();
      });
    }
  }

  isTodayOrYesterDay(dt: string): string {
    const cdt = new Date();
    const yesterday = new Date((cdt.setDate(cdt.getDate() - 1)));
    if (new Date(dt).toDateString() === new Date().toDateString()) {
      return 'Today';
    } else if (new Date(dt).toDateString() === yesterday.toDateString()) {
      return 'Yesterday';
    } else {
      return null;
    }
  }

  async goToShravakProfile() {
    this.navCtrl.navigateForward([Roots.page + '/' + Roots.shravakOtherProfile, { id: this.userId }]);
  }

  scrollToBottom() {
    setTimeout(() => {
      this.content.scrollToBottom();
    }, 300);
  }

  ngOnDestroy() {
    this.destroy$.next(true);
    this.destroy$.complete();
  }
}
