import { OrderAssociatonComponent } from './../../gdel/order-associaton/order-associaton.component';
import { AccessDialogComponent } from './../../gdel/access-dialog/access-dialog.component';
import { DateRangePickerComponent } from './../../gdel/date-range-picker/date-range-picker.component';
import { Component, ElementRef, Inject, OnInit, ViewChild } from '@angular/core';
import { apiTemp, docClassification, modules, supportedFiles } from '../../../../environments/environment.prod';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { FormControl } from '@angular/forms';
import { FindedFile, FindedFilesResponse } from '../../../interfaces/finded-files.interface';
import { MatTableDataSource } from '@angular/material/table';
import { DOCUMENT } from '@angular/common';
import { EncService } from '../../../services/enc.service';
import { MatDialog } from '@angular/material/dialog';
import { GdelService } from '../../../services/gdel.service';
import { ActivatedRoute, Router } from '@angular/router';
import { ResourcesService } from '../../../services/resources.service';
import { SocketService } from '../../../services/socket.service';
import { UsersProfilesService } from '../../../services/users-profiles.service';
import { FunctionsService } from '../../../services/functions.service';
import { UserConsultResponse } from '../../../interfaces/user.interface';
import { lastValueFrom } from 'rxjs';
import { ProfileInterface } from '../../../interfaces/profile.interface';
import { Permissions } from '../../../interfaces/permissions.interface';
import { IndividualUploadComponent } from '../individual-equipment-upload/individual-upload.component';
import { MultipleUploadComponent } from '../multiple-equipment-upload/multiple-upload.component';
import { AlertComponent } from '../../resources/dialogs/alert/alert.component';
import { WebviewerComponent } from '../../gdel/webviewer/webviewer.component';
import { ShareFileComponent } from '../../gdel/share-file/share-file.component';
import { IndividualCorrectiveUploadComponent } from '../individual-corrective-upload/individual-corrective-upload.component';
import { MultipleCorrectiveUploadComponent } from '../multiple-corrective-upload/multiple-corrective-upload.component';

const ID_MODULE = "S002V01M15IDUP"; 

export interface DocumentoEquipamiento {
  CODIGO: string;
  VERSION: string;
  NOMBRE: string;
  TAMANIO: string;
  USRREG: string;
  ACCESO: UsersAccess[];
}

export interface UsersAccess {
  userLabel: string;
  userName: string;
  userColor: string;
  isTrigger: boolean;
}

@Component({
  selector: 'app-corrective-documents-upload',
  standalone: false,
  templateUrl: './corrective-documents-upload.component.html',
  styleUrl: './corrective-documents-upload.component.css'
})

export class CorrectiveDocumentsUploadComponent implements OnInit {
  public btnSmall: boolean;

  isLoading: boolean;
  hasError: boolean;
  errorStr: string;
  category: string;

  modulesArr = modules;
  clasificationsArr = docClassification;
  supportedFilesArr = supportedFiles;

  startDate: Date | null;
  endDate: Date | null;

  @ViewChild('dateRange') dateRange?: ElementRef;
  @ViewChild(MatPaginator) paginator!: MatPaginator;
  @ViewChild(MatSort) sort!: MatSort;

  moduleControl: FormControl;
  clasificationControl: FormControl;
  fileNameControl: FormControl;
  fileTypeControl: FormControl;
  datesRangeControl: FormControl;

  files: FindedFile[];
  dataSource: MatTableDataSource<DocumentoEquipamiento>;
  displayedColumns = ['CODIGO', 'VERSION', 'NOMBRE', 'TAMANIO', 'USRREG', 'ACCIONES'];

  avatarColors = {
    A: 244, B: 67, C:  54, D: 233, E: 30, F:  99, G: 156, H:  39, I: 176, 
    J: 103, K: 58, L:  58, M: 183, N: 63, Ñ:  81, O: 181, P:  33, Q: 150, 
    R: 243, S:  3, T: 169, U: 244, V: 76, W: 175, X:  80, Y: 255, Z: 193
  };

  isFromModule: boolean;
  module: string;

  documentsManagementEnabled: boolean;
  documentsViewerEnabled: boolean;
  documentsEditorEnabled: boolean;
  shareDocumentsEnabled: boolean;
  registerDocumentsEnabled: boolean;
  versionsHistoryEnabled: boolean;

  constructor(
    @Inject(DOCUMENT) private _document: Document,
    private _encService: EncService,
    private _dialog: MatDialog,
    private _gdelService: GdelService,
    private _activatedRoute: ActivatedRoute,
    private _resourcesService: ResourcesService,
    private _socketService: SocketService,
    private _usersProfilesService: UsersProfilesService,
    private _router: Router,
    private _functionsService: FunctionsService,
  ) {
    this._functionsService.consultModuleStatus(ID_MODULE);
    this.btnSmall = false;
    this.isLoading = true;
    this.hasError = true;
    this.errorStr = '';
    this.category = 'my-files';
    this.startDate = null;
    this.endDate = null;

    this.moduleControl = new FormControl('IDUP');
    this.clasificationControl = new FormControl('LA'); 
    this.fileNameControl = new FormControl('');
    this.fileTypeControl = new FormControl('');
    this.datesRangeControl = new FormControl('');

    this.dataSource = new MatTableDataSource();
    this.files = [];

    this.isFromModule = true; //
    this.module = 'ADSI';

    this.documentsManagementEnabled = true;
    this.documentsViewerEnabled = true;
    this.documentsEditorEnabled = true;
    this.shareDocumentsEnabled = true;
    this.registerDocumentsEnabled = true;
    this.versionsHistoryEnabled = true;
  }

  ngOnInit(): void {
    this.initPermissions();
    

    this._socketService.refreshPermissions().subscribe(async (profUpdEnc) => {
      try {
        let idUser = localStorage.getItem('idusuario')!;
        let usrInfo: UserConsultResponse = await lastValueFrom(this._usersProfilesService.getUser(idUser, idUser, 1));
        
        if (usrInfo.error) {
          this._resourcesService.openSnackBar('ERR_NPE000: Ocurrió un error inesperado.');
        } else {
          let idProfDec = await this._encService.decrypt(usrInfo.response.PERFIL);
          let currentProfile = await this._encService.decrypt(localStorage.getItem('perfil')!);

          if (idProfDec != currentProfile) {
            this._router.navigate(['/sam/home']);
            return;
          }
          
          let profileUpdated = await this._encService.decrypt(`${profUpdEnc}`);
          if (profileUpdated == currentProfile) {
            let profile = localStorage.getItem('perfil')!;
            let profInfo: ProfileInterface = await lastValueFrom(this._usersProfilesService.getProfile(
              profile,
              idUser,
              1
            ));

            let permArr = await this._functionsService.processPermissions(profInfo.response.PERMISOS.permissions);
            let modPerm = permArr.filter(item => item.id == ID_MODULE);
            if (modPerm.length > 0) {

              this.updateModulePermissions(modPerm[0]);
            }
          }
        }
      } catch (error: any) {
        this.handlePermissionsError(error);
      }
    });


    this._socketService.refreshModules().subscribe(async () => this._functionsService.consultModuleStatus(ID_MODULE));

    // Listeners para controles - mantenemos la funcionalidad pero con valores fijos
    this.fileNameControl.valueChanges.subscribe(dna => {
      this.getFiles('ADSI', 'LA', this.startDate, this.endDate, dna, this.fileTypeControl.value);
    });

    this.fileTypeControl.valueChanges.subscribe(ext => {
      this.getFiles('ADSI', 'LA', this.startDate, this.endDate, this.fileNameControl.value, ext);
    });

    this.getFiles('ADSI', 'LA', this.startDate, this.endDate, '', '');
  }

  async initPermissions() {
    try {
      let permissionsEnc = localStorage.getItem('permisos');
      let permissionsDec = await this._encService.decrypt(permissionsEnc!);
      let permissionsArr: Permissions = JSON.parse(permissionsDec);

      // Buscar permisos específicos del módulo de equipamiento
      let modPerm = permissionsArr.permissions.filter(item => item.id == ID_MODULE);
      if (modPerm.length > 0) {
        this.updateModulePermissions(modPerm[0]);
      }
    } catch (error: any) {
      this._resourcesService.openSnackBar('Hubo un error al obtener los permisos del módulo.');
      this.documentsManagementEnabled = false;
    }
  }

  private updateModulePermissions(modPerm: any) {

    let funPerm = modPerm.children?.filter((item: any) => item.id == 'S002V01F01ADDO');
    if (funPerm && funPerm.length > 0) {
      this.documentsManagementEnabled = funPerm[0].children?.filter((item: any) => item.id == 'S002V01P01GEDO')[0]?.access > 0 || true;
      this.documentsViewerEnabled = funPerm[0].children?.filter((item: any) => item.id == 'S002V01P02VIDO')[0]?.access > 0 || true;
      this.documentsEditorEnabled = funPerm[0].children?.filter((item: any) => item.id == 'S002V01P03EDDO')[0]?.access > 0 || true;
      this.shareDocumentsEnabled = funPerm[0].children?.filter((item: any) => item.id == 'S002V01P04CODO')[0]?.access > 0 || true;
      this.registerDocumentsEnabled = funPerm[0].children?.filter((item: any) => item.id == 'S002V01P05REDO')[0]?.access > 0 || true;
      this.versionsHistoryEnabled = funPerm[0].children?.filter((item: any) => item.id == 'S002V01P06HIVE')[0]?.access > 0 || true;
    }
  }

  private handlePermissionsError(error: any) {
    if (error.error == undefined) {
      this._resourcesService.openSnackBar('ERR_PAD001: Ocurrió un error inesperado.');
    } else if (error.error.msg == undefined) {
      this._resourcesService.openSnackBar('ERR_PAD002: Ocurrió un error inesperado.');
    } else {
      this._resourcesService.openSnackBar(`ERR_PAD003: ${error.error.msg}`);
    }
  }

async getFiles(module: string | undefined, clas: string | undefined, startDate: Date | null, endDate: Date | null, name: string | undefined, type: string | undefined) {
  try {
    this.isLoading = true;
    this.hasError = false;
    this.errorStr = "";


    let mod = 'ADSI';
    let cla = 'LA';
    let sda = startDate == null ? '-' : this.formatSearchDate(startDate);
    let eda = endDate == null ? '-' : this.formatSearchDate(endDate);
    let dna = name == undefined || name == '' ? '-' : name;
    let ext = type == undefined || type == '' ? '-' : JSON.stringify(type.split(','));
    let idUser = localStorage.getItem('idusuario')!;

    let files: FindedFilesResponse = await lastValueFrom(this._gdelService.getFiles(
      mod, cla, sda, eda, dna, ext, this.category, idUser, 1
    ));

    this.hasError = files.error;
    this.errorStr = files.msg;

    if (!this.hasError) {

      const filteredFiles = files.response.filter(file => 
        file.NOMBRE.toLowerCase().includes('correctivo')
      );
      
      this.files = filteredFiles;
      let filesFound: DocumentoEquipamiento[] = [];
      
      filteredFiles.forEach(file => {
        let fileSize = this.formatBytes(file.TAMANIO as number);
        let fileAccess = this.getUsersAccess(file.ACCESO);
        let fileObj: DocumentoEquipamiento = {
          CODIGO: file.CODIGO,
          VERSION: file.VERSION,
          NOMBRE: file.NOMBRE,
          TAMANIO: fileSize,
          USRREG: file.USRREG,
          ACCESO: fileAccess,
        };

        filesFound.push(fileObj);
      });
      
      this.dataSource = new MatTableDataSource(filesFound);
      this.dataSource.paginator = this.paginator;
      this.dataSource.sort = this.sort;
    }

    this.isLoading = false;
  } catch (error: any) {
    this.handleGetFilesError(error);
  }
}

  private handleGetFilesError(error: any) {
    if (error.error == undefined) {
      this.errorStr = 'Ocurrió un error inesperado.';
    } else if (error.error.msg == undefined) {
      this.errorStr = 'Ocurrió un error inesperado.';
    } else {
      this.errorStr = error.error.msg;
    }

    this.hasError = true;
    this.isLoading = false;
  }

  formatSearchDate(date: Date): string {
    let day = date.getDate() < 10 ? `0${date.getDate()}` : `${date.getDate()}`;
    let month = date.getMonth() + 1 < 10 ? `0${date.getMonth() + 1}` : `${date.getMonth() + 1}`;
    let fullYear = `${date.getFullYear()}`;
    let year = fullYear.substring(2);
    
    return `${year}${month}${day}`;
  }

  formatBytes(bytes: number, decimals = 2) {
    if (bytes === 0) return '0 Bytes';

    const k = 1024;
    const dm = decimals < 0 ? 0 : decimals;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

    const i = Math.floor(Math.log(bytes) / Math.log(k));

    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
  }

  getUsersAccess(accessStr: string): UsersAccess[] {
    let accessArr = JSON.parse(accessStr);
    let arrFn: UsersAccess[] = [];

    for (const user of accessArr) {
      let userNameArr = user.split(' ');
      let userLabel = '';

      for (let i = 0; i < 2; i++) {
        userLabel += userNameArr[i][0];
      }

      let userColor = "rgb(";
      for (let i = 0; i < 3; i++) {
        let char: never = user.charAt(i) as never;
        let code = this.avatarColors[char];

        userColor += `${code}, `;
      }

      userColor = userColor.substring(0, userColor.length - 2);
      userColor += ")";

      let userObj: UsersAccess = {
        userLabel: userLabel,
        userName: user,
        userColor: userColor,
        isTrigger: false,
      }

      arrFn.push(userObj);
    }

    let arrFnAux: UsersAccess[] = [];
    if (arrFn.length > 4) {
      for (let i = 0; i < 3; i++) {
        arrFnAux.push(arrFn[i]);
      }

      let moreUsers: UsersAccess = {
        userLabel: `${arrFn.length - 3}+`,
        userName: `Ver ${arrFn.length - 3} más...`,
        userColor: 'rgba(0,0,0,0.54)',
        isTrigger: true,
      };

      arrFnAux.push(moreUsers);
      return arrFnAux;
    }

    return arrFn;
  }

  public onResize(): void {
    this.btnSmall = window.innerWidth <= 1573;
  }

 
  openIndividualUpload() {
    if (this.registerDocumentsEnabled) {
      let dialogRef = this._dialog.open(IndividualCorrectiveUploadComponent, {
        width: '1000px',
        minWidth: '1000px',
        maxHeight: '90vh',
        disableClose: true,
      });
  
      dialogRef.afterClosed().subscribe(res => {
        if (res == true) {
          this.refreshData();
        }
      });
    }
  }

  openMassiveUpload() {
    if (this.registerDocumentsEnabled) {
      let dialogRef = this._dialog.open(MultipleCorrectiveUploadComponent, {
        width: '1000px',
        minWidth: '1000px',
        maxHeight: '90vh',
        disableClose: true,
      });
  
      dialogRef.afterClosed().subscribe(res => {
        if (res == true) {
          this.refreshData();
        }
      });
    }
  }

  refreshData() {
    this.getFiles('ADSI', 'LA', this.startDate, this.endDate, this.fileNameControl.value, this.fileTypeControl.value);
  }

  updateCategory(category: string) {
    this.category = category;
    this.getFiles('ADSI', 'LA', this.startDate, this.endDate, this.fileNameControl.value, this.fileTypeControl.value);
  }

  openDateRangePicker() {
    let dialogRef = this._dialog.open(DateRangePickerComponent, {
      disableClose: true,
      width: '480px',
      maxWidth: '480px',
      data: {
        startDate: this.startDate,
        endDate: this.endDate
      }
    });

    dialogRef.afterClosed().subscribe(res => {
      if (res != null && res != undefined && res != '') {
        let resObj = JSON.parse(res);
        let dateRange = "";

        if (resObj.startDate != null || resObj.endDate != null) {
          if (resObj.startDate != null) {
            let startDateTimeArr = resObj.startDate.split('T');
            let startDateArr = startDateTimeArr[0].split('-').reverse();
            let startDateStr = startDateArr.join('/');
  
            this.startDate = new Date(resObj.startDate);
            dateRange += `desde ${startDateStr}, `;
          }
          
          if (resObj.endDate != null) {
            let endDateTimeArr = resObj.endDate.split('T');
            let endDateArr = endDateTimeArr[0].split('-').reverse();
            let endDateStr = endDateArr.join('/');
  
            this.endDate = new Date(resObj.endDate);
            dateRange += `hasta ${endDateStr}, `;
          }
  
          let fl = dateRange[0].toUpperCase();
          let dateRangeArr = dateRange.split("");
  
          dateRangeArr[0] = fl;
          dateRange = dateRangeArr.join("");
          dateRange = dateRange.substring(0, dateRange.length - 2);

          this.dateRange!.nativeElement.value = dateRange;
          this.getFiles('ADSI', 'LA', this.startDate, this.endDate, this.fileNameControl.value, this.fileTypeControl.value);
        }
      }
    });
  }

  clearDatesRange() {
    this.startDate = null;
    this.endDate = null;
    this.datesRangeControl.setValue('');

    this.getFiles('ADSI', 'LA', this.startDate, this.endDate, this.fileNameControl.value, this.fileTypeControl.value);
  }




  async downloadFile(code: string, version: string, name: string) {
    try {
      let idFile = `${code}=${version}=${name}`;
      this._resourcesService.openSnackBar(`Iniciando la descarga del archivo ${idFile}...`);

      let idFileEnc = await this._encService.encrypt(idFile);
      let download = this._document.getElementById(`download`) as HTMLAnchorElement;
  
      let idUser = localStorage.getItem('idusuario')!;
      let downloadToken = await lastValueFrom(this._gdelService.getDownloadToken(
        idFileEnc,
        idUser,
        1
      ));
  
      download.href = `${apiTemp}download-file/${downloadToken.response.TOKEN}/${idUser}/1`;
      download.download = idFile;
      download.click();
    } catch (error: any) {
      if (error.error == undefined) {
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      } else if (error.error.msg == undefined) {
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      } else {
        this._resourcesService.openSnackBar(error.error.msg);
      }
    }
  }

  async openViewer(code: string, version: string, name: string) {
    try {
      let idFile = `${code}=${version}=${name}`;
      this._resourcesService.openSnackBar(`Abriendo el archivo ${idFile}...`);
      
      let idFileEnc = await this._encService.encrypt(idFile);
      let idUser = localStorage.getItem('idusuario')!;

      let publicURL = await lastValueFrom(this._gdelService.getPublicDocumentUrl(
        idFileEnc,
        idUser,
        1
      ));

      let fileData = {
        url: publicURL.response.public_uri,
      };

      this._dialog.open(WebviewerComponent, {
        data: fileData,
        width: '1080px',
        maxWidth: '1080px',
      });
    } catch (error: any) {
      if (error.error == undefined) {
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      } else if (error.error.msg == undefined) {
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      } else {
        this._resourcesService.openSnackBar(error.error.msg);
      }
    }
  }



  confirmDelete(code: string, version: string, name: string) {
    let idFile = `${code}=${version}=${name}`;
    let dialogRef = this._dialog.open(AlertComponent, {
      disableClose: true,
      width: '480px',
      maxWidth: '480px',
      data: {
        title: 'Confirmar acción',
        icon: 'warning',
        description: `¿Está seguro de querer eliminar el archivo ${idFile}?`,
        description2: 'Esta acción no se puede deshacer'
      }
    });

    dialogRef.afterClosed().subscribe(res => {
      if (res == true) {
        this.deleteFile(idFile);
      }
    });
  }

  async deleteFile(idFile: string) {
    try {
      let idUser = localStorage.getItem('idusuario');
      let idFileEnc = await this._encService.encrypt(idFile);
      let formData = new FormData();

      formData.append('id_user', idUser!);
      formData.append('id_file', idFileEnc);
      formData.append('linea', '1');

      await lastValueFrom(this._gdelService.deleteFile(formData));
      this._resourcesService.openSnackBar('El archivo se eliminó correctamente.');
      
      this.refreshData();
    } catch (error: any) {
      if (error.error == undefined) {
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      } else if (error.error.msg == undefined) {
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      } else {
        this._resourcesService.openSnackBar(error.error.msg);
      }
    }
  }
}