import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { debounceTime, distinctUntilChanged, Subject } from 'rxjs';
import { FriendsService } from '../../services/friends/friends.service';
import { LocalStorageService } from '../../services/local-storage/local-storage.service';
import { UserService } from '../../services/user/user.service';

@Component({
  selector: 'app-friend-page',
  imports: [CommonModule, FormsModule],
  templateUrl: './friend-page.component.html',
})
export class FriendPageComponent implements OnInit {
  protected listFriend: {
    username: string;
    status: string;
    friend_user_id: string;
    id: string;
  }[] = [];

  protected listUser: {
    uid: string;
    username: string;
  }[] = [];

  userId: string = '';
  status: string = '';
  isFriendModalOpen: boolean = false;
  hasAcceptedFriends: boolean = false;
  hasPendingFriends: boolean = false;
  searchTerm: string = '';
  searchTermChanged = new Subject<string>();

  constructor(
    private friendService: FriendsService,
    private userService: UserService,
    private localStorage: LocalStorageService
  ) {}

  ngOnInit(): void {
    this.getFriendData();
    this.searchTermChanged
      .pipe(debounceTime(200), distinctUntilChanged())
      .subscribe((username: string) => {
        this.searchUser(username);
      });
  }

  protected searchUser(username: string) {
    this.searchTerm = username;
    if (this.searchTerm) {
      this.getUserData(this.searchTerm.trim());
    } else {
      this.listUser = [];
    }
  }

  onSearchTermChange(username: string) {
    this.searchTermChanged.next(username);
  }

  private getUserData(search: string): void {
    const username = this.localStorage.getUsername();
    this.userService
      .getUser('^(?!' + username + ')' + search)
      .subscribe((data: any[]) => {
        if (data.length > 0) {
          const existingFriendIds = this.listFriend.map(
            (friend) => friend.friend_user_id
          );
          this.listUser = data.filter(
            (user) => !existingFriendIds.includes(user.uid)
          );
        }
      });
  }

  protected addUser(user_id: string): void {
    this.friendService.addFriend(user_id).subscribe((data: any) => {
      if (data.id) {
        const add_user = this.listUser.find((x) => x.uid == user_id);
        if (add_user) {
          this.listFriend.push({
            username: add_user.username,
            status: 'pending',
            friend_user_id: add_user.uid,
            id: data.id,
          });
          this.searchTerm = '';
          this.listUser = [];
        }
      }
    });
  }

  private getFriendData(): void {
    this.friendService.getFriend().subscribe((data: any[]) => {
      if (data.length > 0) {
        data.forEach((friend) => {
          let status = friend['status'];
          let userId = friend['friend_user_id'];
          let id = friend['id'];
          this.friendService
            .getFriendById(userId)
            .subscribe((friendData: any) => {
              this.listFriend.push({
                username: friendData.username,
                status: status,
                friend_user_id: userId,
                id: id,
              });
            });
        });
      }
    });
  }

  onAcceptOrDeny(id: string, choice: string) {
    if (choice == 'accept') {
      // If return code is 200, then the friend has been accepted so we can change the status of the friend to accepted
      this.friendService.acceptFriendById(id).subscribe((data: any) => {
        if (data.message == 'Friend request accepted') {
          this.listFriend.forEach((friend) => {
            if (friend.id == id) {
              friend.status = 'accepted';
            }
          });
        }
      });
    } else {
      // If return code is 200, then the friend has been denied so we can delete the friend from the list
      this.friendService.denyFriendById(id).subscribe((data: any) => {
        if (data.message == 'Friend request denied') {
          this.listFriend.forEach((friend, index) => {
            if (friend.id == id) {
              this.listFriend.splice(index, 1);
            }
          });
        }
      });
    }
  }

  openFriendModal() {
    this.isFriendModalOpen = true;
  }

  closeFriendModal() {
    this.isFriendModalOpen = false;
  }

  deleteFriend(id: string) {
    this.friendService.deleteFriend(id).subscribe((data: any) => {
      if (data.message == 'Friend deleted') {
        this.listFriend.forEach((friend, index) => {
          if (friend.id == id) {
            this.listFriend.splice(index, 1);
          }
        });
      }
    });
  }

  hasNoAcceptedFriends(): boolean {
    return (
      this.listFriend.filter((friend) => friend.status === 'accepted')
        .length === 0
    );
  }

  hasPendingApprovalFriend(): boolean {
    return (
      this.listFriend.filter((friend) => friend.status === 'pending_approval')
        .length !== 0
    );
  }

  hasPendingFriend(): boolean {
    return (
      this.listFriend.filter((friend) => friend.status === 'pending').length !==
      0
    );
  }
}
