import { Component, OnDestroy, OnInit } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { Professor } from '../../model/Professor';
import { NotificationService } from '../../service/notification.service';
import { NotificationType } from '../../notification/notification-type';
import { HttpErrorResponse, HttpEvent, HttpEventType } from '@angular/common/http';
import { NgForm } from '@angular/forms';
import { CustomHttpResponse } from '../../dto/custom-http-response';
import { Router } from '@angular/router';
import { FileUploadStatus } from 'src/app/model/file-upload.status';
import { SubSink } from 'subsink';
import { WorkingStatus } from "../../enum/WorkingStatus";
import { User } from 'src/app/model/user';
;
import { Role } from 'src/app/enum/role.enum';
import { AuthenticationService } from 'src/app/service/authentication.service';
import { ProfessorService } from 'src/app/service/professor.service';
;

@Component({
  selector: 'app-professor',
  templateUrl: './professor.component.html',
  styleUrls: ['./professor.component.css']
})
export class ProfessorComponent implements OnInit, OnDestroy {
  WorkingStatus = WorkingStatus; // Declare enum here

  private titleSubject = new BehaviorSubject<string>('Professors');
  public titleAction$ = this.titleSubject.asObservable();
  public loggedInUser: User;


  public professors: Professor[] = [];
  public loggedInProfessor: Professor;
  public refreshing: boolean;
  private subs = new SubSink();
  selectedProfessor: Professor = {
    professorId: '',          // Initialize with empty string or appropriate default
    firstName: '',            // Initialize with empty string or appropriate default
    lastName: '',             // Initialize with empty string or appropriate default
    email: '',                // Initialize with empty string or appropriate default
    profileImageUrl: '',     // Optional property, can be initialized with empty string or `null`
    status: WorkingStatus.ACTIVE, // Initialize with a default value from your enum
    department: '',           // Initialize with empty string or appropriate default
    position: '',             // Initialize with empty string or appropriate default
    officeLocation: '',       // Initialize with empty string or appropriate default
    joinDate: new Date()      // Initialize with the current date or an appropriate default
  };
    public profileImageFileName: string | null;
  public profileImage: File | null;
  // public editProfessor: Professor = new Professor();
  public fileUploadStatus: FileUploadStatus = new FileUploadStatus();

  constructor(
    private professorService: ProfessorService,
    private notificationService: NotificationService,
    private router: Router,
    private authenticationService: AuthenticationService,

  ) {}

  ngOnInit(): void {
    
    this.getProfessors(true);
    this.loggedInUser = this.authenticationService.getUserFromLocalStorage();

  }

  ngOnDestroy(): void {
    this.subs.unsubscribe();
  }

  handleTitleChange(title: string): void {
    this.titleSubject.next(title);
  }


  public changeTitle(title: string): void {
    this.titleSubject.next(title);
  }

  public getProfessors(showNotification: boolean): void {
    this.refreshing = true;
    this.subs.sink = this.professorService.getAllProfessors().subscribe(
      professorsPage => {
        this.professors = professorsPage.content;
        this.professorService.addProfessorsToLocalStorage(this.professors);
        if (showNotification) {
          this.notificationService.notify(NotificationType.SUCCESS, `${this.professors.length} professors loaded successfully`);
        }
        this.refreshing = false;
      },
      (errorResponse: HttpErrorResponse) => {
        this.sendErrorNotification(errorResponse.error.message);
        this.refreshing = false;
      }
    );
  }

  public onSelectProfessor(selectedProfessor: Professor): void {
    this.selectedProfessor = selectedProfessor;
    this.clickButton('openProfessorInfo');
  }

  public onProfileImageChange(fileList: FileList): void {
    this.profileImageFileName = fileList[0].name;
    this.profileImage = fileList[0];
  }

  private sendErrorNotification(message: string): void {
    this.sendNotification(NotificationType.ERROR, message);
  }

  private sendNotification(type: NotificationType, message: string): void {
    this.notificationService.notify(type, message ? message : 'An error occurred. Please try again');
  }

  public onAddNewProfessor(professorForm: NgForm): void {
    const formData = this.professorService.createProfessorFormData(professorForm.value, this.profileImage);
    this.subs.sink = this.professorService.addProfessor(formData).subscribe(
      (professor: Professor) => {
        this.clickButton('new-professor-close');
        this.getProfessors(false);
        this.invalidateVariables();
        professorForm.reset();
        this.notificationService.notify(NotificationType.SUCCESS, `Professor ${professor.firstName} added successfully`);
      },
      (errorResponse: HttpErrorResponse) => {
        this.sendErrorNotification(errorResponse.error.message);
      }
    );
  }

  private invalidateVariables(): void {
    this.profileImage = null;
    this.profileImageFileName = null;
  }

  public saveNewProfessor(): void {
    this.clickButton('new-professor-save');
  }

  public searchProfessors(searchTerm: string): void {
    if (!searchTerm) {
      this.professors = this.professorService.getProfessorsFromLocalStorage();
      return;
    }

    const matchProfessors: Professor[] = [];
    searchTerm = searchTerm.toLowerCase();
    for (const professor of this.professorService.getProfessorsFromLocalStorage()) {
      if (
        professor.firstName.toLowerCase().includes(searchTerm) ||
        professor.lastName.toLowerCase().includes(searchTerm) ||
        professor.email.toLowerCase().includes(searchTerm) ||
        professor.department.toLowerCase().includes(searchTerm)
      ) {
        matchProfessors.push(professor);
      }
    }
    this.professors = matchProfessors;
  }

  private clickButton(buttonId: string): void {
    document.getElementById(buttonId)?.click();
  }

  public onEditProfessor(professor: Professor): void {
    // this.editProfessor = professor;
    this.selectedProfessor = professor;
    this.clickButton('openProfessorEdit');
  }

  onUpdateProfessor(form: NgForm) {
    if (form.invalid) {
      // Handle form validation errors if needed
      this.notificationService.notify(NotificationType.ERROR, 'Please fill out all required fields.');
      return;
    }

    const formData = this.professorService.createProfessorFormData(this.selectedProfessor, this.profileImage);

    this.subs.add(this.professorService.updateProfessor(this.selectedProfessor.professorId, formData).subscribe(
      (professor: Professor) => {
        this.clickButton('closeEditProfessorButton');
        this.getProfessors(false);
        this.invalidateVariables();
        this.notificationService.notify(NotificationType.SUCCESS, `Professor ${professor.firstName} updated successfully`);
      },
      (errorResponse: HttpErrorResponse) => {
        this.sendErrorNotification(errorResponse.error.message);
      }
    ));
  }


  public onDeleteProfessor(professor: Professor): void {
    this.subs.sink = this.professorService.deleteProfessor(professor.professorId).subscribe(
      (response: CustomHttpResponse) => {
        this.getProfessors(false);
        this.invalidateVariables();
        this.notificationService.notify(NotificationType.SUCCESS, response.message);
      },
      (errorResponse: HttpErrorResponse) => {
        this.sendErrorNotification(errorResponse.error.message);
      }
    );
  }

  public updateProfileImage(): void {
    this.clickButton('profile-image-input');
  }

  public onUpdateProfileImage(): void {
    if (!this.profileImage) return;
    this.refreshing = true;
    const formData = new FormData();
    formData.append("profileImage", this.profileImage);
    let professor = this.professorService.getSelectedProfessor();
    this.subs.sink = this.professorService.updateProfileImage(professor.professorId, formData).subscribe(
      (event: HttpEvent<any>) => {
        this.reportUploadProgress(event);
      },
      (errorResponse: HttpErrorResponse) => {
        this.sendErrorNotification(errorResponse.error.message);
        this.refreshing = false;
        this.fileUploadStatus.status = 'error';
      },
      () => {
        this.refreshing = false;
        this.getProfessors(false);
      }
    );
  }

  private reportUploadProgress(event: HttpEvent<any>): void {
    switch (event.type) {
      case HttpEventType.UploadProgress:
        this.fileUploadStatus.percentage = Math.round(100 * event.loaded / event.total!);
        this.fileUploadStatus.status = 'progress';
        break;
      case HttpEventType.Response:
        if (event.status === 200) {
          // For browser to fetch image when updating (because name left the same)
          this.loggedInProfessor.profileImageUrl = `${event.body.profileImageUrl}?time=${new Date().getTime()}`;
          this.notificationService.notify(NotificationType.SUCCESS, `${event.body.firstName}'s image updated successfully`);
          this.fileUploadStatus.status = 'done';
        } else {
          this.sendErrorNotification('Unable to upload image. Please try again');
        }
        break;
      default:
        this.fileUploadStatus.status = 'default';
    }
  }

  public get isAdmin(): boolean {
    return this.loggedInUser.role === Role.ADMIN || this.loggedInUser.role === Role.SUPER_ADMIN;
  }

  public get isManager(): boolean {
    return this.isAdmin || this.loggedInUser.role === Role.MANAGER;
  }
}
