// Agnular Core
import { Component, Input, OnInit, OnChanges, Output, EventEmitter, OnDestroy, SimpleChanges } from '@angular/core';
import { HttpErrorResponse } from '@angular/common/http';
import { LowerCasePipe } from '@angular/common';

// RxJs
import { Subscription, throwError } from 'rxjs';
import { catchError } from "rxjs/operators";

// Services
import { AccountInfoService } from 'src/app/services/accountInfo/account-info.service';
import { UtilitiesService } from 'src/app/services/utilities/utilities.service';

// Interfaces
import { DocumentConfig, uploadDocument } from 'src/app/interfaces/common-interfaces';

@Component({
  standalone: false,
  selector: 'app-upload-document',
  templateUrl: './upload-document.component.html',
  styleUrls: ['./upload-document.component.scss']
})
export class UploadDocumentComponent implements OnInit, OnDestroy {

  @Input() docConfig!: DocumentConfig;
  @Input() docUploaded: number | boolean = 0;
  @Input() isValidInfoReqd:boolean = false;
  @Input() authStateCode!:string;
  @Input() authType!: string;
  @Input() licenseExpireDate!: any;
  isDocListenerTriggered: boolean = false;
  isUploadReady: boolean = true;

  @Output() uploadComplete = new EventEmitter<DocumentConfig>();
  sendDocumentConfig(config: DocumentConfig) {
    if (this.isValidInfoReqd === true && !this.isDocListenerTriggered) {
        if (config.uploadStatus === true) {
            this.isDocListenerTriggered = true; 
        }
        this.utilitiesService.authStateLoadEvent.emit({config});
    }
    this.uploadComplete.emit(config);
  }

  config: DocumentConfig = {
    param: '',
    errorMsg: 'File must be either PDF, PNG, JPG, TIFF, PICT or RTF Format.',
    accFileTypes: [],
    uploadStatus: false,
    successMsg: 'Upload Complete',
    autoUpload: false,
    inputClass: 'upload-document',
    buttonName: 'Upload',
    className: '',
    successTxtCls: 'upload-success-msg',
    error: false,
    hideStatusMsg: false,
    buttonClass: '',
    uploadBtnClass: 'col-lg-8 col-md-6'
  };

  constructor(
    private accountInfoService:AccountInfoService,
    private utilitiesService:UtilitiesService,
  ) { 
  }

  ngOnInit(): void {
    this.config.accFileTypes = this.utilitiesService.getAcceptedFileTypes();
    if (this.docConfig.accFileTypes.length > 0) {
      this.config.accFileTypes = this.docConfig.accFileTypes;
    }
    if (this.config.hasOwnProperty('uploadBtnClass')) {
        this.config.uploadBtnClass = this.config.uploadBtnClass;
    }
    this.config = this.utilitiesService.merge(this.config, this.docConfig);
  }

  ngOnChanges(changes: SimpleChanges) {
    if (changes['licenseExpireDate']) {
      const current = changes['licenseExpireDate'].currentValue;
      this.isUploadReady = (current instanceof Date);
    }
  }

  /**s
   * 
   * @type FormData
   */
   formdata: any = new FormData();
   type: string = '';
   showStatus: boolean = false;
   statusMsg: string = '';
   
   /**
    * Checks whether given file extension is supported or not.
    * Returns true if given extension is in supported formats
    * Returns false if given extension is not in supported formats
    * @param {string | undefined} fileExt
    * @returns {Boolean}
    */
   isValidFileType(fileExt : string | undefined) {
      let lowerCase = new LowerCasePipe();
      fileExt = typeof fileExt === 'undefined' ? '' : fileExt;
       if (this.config.accFileTypes.indexOf(lowerCase.transform(fileExt)) !== -1) {       
            return true;
       }
       return false;
   };
   
   /**
    * Function to set FormData with files and return param
    * @param {any} $files
    * @param {type} type
    * @returns {undefined}
    */
   uploadEnable: boolean = false;
   disable: boolean = true;
   files:any;
   setFormData(event:any, type:string) {
       this.uploadEnable = false;
       this.statusMsg = '';
       this.isUploadReady = true;
       const file:File = event.target.files[0];
       if (file) {
        var extension = file.name.split(".").pop();
           if (this.isValidFileType(extension) || (extension !== "" && type === "dur_report_document")) {
              this.uploadEnable = true;
              this.config.error = false;
              this.formdata.append(type, file);
              if (this.isValidInfoReqd === true) {
                 this.sendDocumentConfig(this.config);
              };
              if (this.config.autoUpload) {
                this.uploadFiles(type);
              }
           } else if (file.name !== "") {
              this.uploadEnable = false;
              this.config.error = true;
              this.config.errorMsg = 'Files must be either '+this.config.accFileTypes.slice(0,-1).join(', ').toUpperCase().concat(this.config.accFileTypes.length > 1 ? ' or ' : '', this.config.accFileTypes.slice(-1).toString().toUpperCase())+'.';
           }
          this.sendDocumentConfig(this.config);
       }
   };

    /**
     * Method to validate Authorized state license document epiration date.
     * @param string type
     * @return void
    */
    validateAuthStateLicenseExp(type:string) {
        if (type === 'auth_state_license_document') {
            this.formdata.append('authType', this.authType);
            this.formdata.append('stateCode', this.authStateCode);
            if (this.licenseExpireDate === "0000-00-00" || this.licenseExpireDate === undefined || this.licenseExpireDate === "") {
                 this.config.errorMsg = "Please select document expiration date";
                 this.isUploadReady = false;
                 this.sendDocumentConfig(this.config);
            }
        }
    }

   uploadDocumentSubscribe!:Subscription;

   /**
    * Function to upload files
    * @returns {undefined}
    */
   uploadFiles(type:string) {
    this.validateAuthStateLicenseExp(type);
    if (!this.isUploadReady) {
        return;
    }
    this.uploadDocumentSubscribe = this.accountInfoService.uploadDocument(this.formdata)
    .pipe(
      catchError((err) => {
        this.config.error = true;
        if(err.error.feedback){
          err.error.feedback.forEach((errorMessage: string) => {
            this.config.errorMsg = errorMessage;
          });
        }else{
          this.config.errorMsg = "An error occurred, please try again later";
        }
        this.sendDocumentConfig(this.config);
        return throwError(() => err);
      })
    )
    .subscribe({
      next: (res: uploadDocument) => {
        if(res.data.document !== "" && res.data.document !== undefined) {
            this.showStatus = true;
            this.uploadEnable = false;
            this.config.uploadStatus = true;
            var tempFormData = new FormData();
            this.formdata.forEach((value:any, key:any) => {
                if (key !== type) {
                    tempFormData.append(key, value);
                }
            });
            this.formdata = tempFormData;
        } else if(res.data.document === undefined || res.data.document === '') {
            this.config.error = true;
            this.config.errorMsg = "An error occurred, please try again later";
            if (res.data.message !== undefined) {
                this.config.errorMsg = res.data.message;
            }
        }
        this.sendDocumentConfig(this.config);
      },
      error: (err: HttpErrorResponse) => {
        this.config.error = true;
          if(err.error.feedback){
            err.error.feedback.forEach((errorMessage: string) => {
              this.config.errorMsg = errorMessage;
            });
          }else{
            this.config.errorMsg = "An error occurred, please try again later";
            
          }
           var tempFormData = new FormData();
           this.formdata.forEach((value:any, key:any) => {
               if (key !== type) {
                   tempFormData.append(key, value);
               }
           });
           this.formdata = tempFormData;
           this.sendDocumentConfig(this.config);
        this.accountInfoService.errorCallBack(err)
      }
    });
   };

   ngOnDestroy(){
    this.uploadDocumentSubscribe?.unsubscribe();
   }

}
