import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { UsersProfilesService } from '../../../services/users-profiles.service';
import { lastValueFrom } from 'rxjs';
import { UserResponse, UsersResponse } from '../../../interfaces/users.interface';
import { EncService } from '../../../services/enc.service';
import { MatTableDataSource } from '@angular/material/table';
import { Router } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
import { EditOrganizationComponent } from './edit-organization/edit-organization.component';
import { FunctionsService } from '../../../services/functions.service';
import { Profile } from '../../../interfaces/profile.interface';
import { BlockDialogComponent } from '../../corrective-maintenance/security-management/block-dialog/block-dialog.component';
import { BlockUserComponent } from './block-user/block-user.component';

export interface Organigrama {
  nombre_completo: string;
  supervisor1: string;
  supervisor2?: string | null;
  supervisor3?: string | null;
  supervisor4?: string | null;
  supervisor5?: string | null;
  supervisor6?: string | null;
  idUsuario?: string;
  
  [key: string]: string | null | undefined;
}

export interface Usuario {
  id: number;
  nombre: string;
  organigrama: Organigrama | null;
  userData?: UserResponse;
}

export interface UserToBlock {
  idUsuario: string;           
  idUsuarioEncriptado: string; 
  nombre_completo: string;
  userData?: UserResponse;

}


@Component({
  selector: 'app-organization',
  templateUrl: './organization.component.html',
  styleUrl: './organization.component.css',
  standalone: false,
})
export class OrganizationComponent implements OnInit {

  ngOnInit(): void {
    this.getUsers()
  }

  public usuarios: Usuario[] = [];
  public isLoading: boolean;
  public dataSource: MatTableDataSource<Organigrama>;
  public displayedColumns: string[];
  public hasError: boolean;
  public Error: string;
  public selectedUsr: Usuario | null = null;
  private cachedUsers: UserResponse[] = [];
  private originalEncryptedIds: Map<string, string> = new Map();

  constructor(
    private _usersProfilesService: UsersProfilesService,
    private _encrypt: EncService,
    private _router: Router,
    private _matDialog: MatDialog,
    private _functionService: FunctionsService,
    private _dialog: MatDialog
  ) {
    this.isLoading = true;
    this.displayedColumns = ['Nombre_completo', 'Supervisor_1', 'Supervisor_2', 'Acciones'];
    this.hasError = false;
    this.Error = '';
    this.dataSource = new MatTableDataSource();
  }

  private async getUsers() {
    try {
      this.isLoading = true;
      this.originalEncryptedIds.clear();
      this.cachedUsers = [];

      let idUser = localStorage.getItem('idusuario')!
      let users: UsersResponse = await lastValueFrom(this._usersProfilesService.getUsers(idUser, 1))

      console.log(users)


      this.hasError = users.error;
      this.Error = users.msg;

      if (!this.hasError) {

        this.cachedUsers = users.response.map(user => ({...user}));
        
        let decryptID = await this._encrypt.decrypt(idUser);
        let organigrama: Organigrama[] = [];
        let nombresUsuarios: string[] = [];

        for (const user of users.response) {
          let idDesencrypt = await this._encrypt.decrypt(user.IDUSUARIO)
          
          this.originalEncryptedIds.set(idDesencrypt, user.IDUSUARIO);
          
          let username = this._functionService.buildName(user.NOMBRE, user.APEPAT, user.APEMAT);
          username = (username + ` (${idDesencrypt})`)
          nombresUsuarios.push(username)
        }

        for (const user of users.response) {
          let idDesencrypt = await this._encrypt.decrypt(user.IDUSUARIO)

          if (decryptID != idDesencrypt && user.ESTATUS != 'Eliminado') {
            let username = this._functionService.buildName(user.NOMBRE, user.APEPAT, user.APEMAT);
            username = (username + ` (${idDesencrypt})`)

            const itemObj: Organigrama = {
              nombre_completo: username,
              supervisor1: 'No configurado',
              supervisor2: null,
              supervisor3: null,
              supervisor4: null,
              supervisor5: null,
              supervisor6: null,
              idUsuario: idDesencrypt
            };

            if (user.ORGANIGRAMA != null && user.ORGANIGRAMA != undefined && user.ORGANIGRAMA !== '[]') {
              try {
                let organigramaArray = JSON.parse(user.ORGANIGRAMA);
                
                for (const item of organigramaArray) {
                  if (item.id_chief && item.level) {
                    let idChiefDec = await this._encrypt.decrypt(item.id_chief);
                    let userFilt = nombresUsuarios.filter(nombre => nombre.includes(idChiefDec));
                    
                    if (userFilt.length > 0) {
                      const level = parseInt(item.level);
                      
                      if (level === 1) {
                        itemObj.supervisor1 = userFilt[0];
                      } else if (level <= 6) {
                        itemObj[`supervisor${level}`] = userFilt[0];
                      } else {
                        itemObj[`supervisor${level}`] = userFilt[0];
                      }
                    }
                  }
                }
              } catch (parseError) {
                console.error('Error parseando el organigrama para el usuario:', username, parseError);
              }
            }

            organigrama.push(itemObj);
          }
        }

        this.cachedUsers.forEach(user => {
          const mappedId = Array.from(this.originalEncryptedIds.entries())
            .find(([decrypted, encrypted]) => encrypted === user.IDUSUARIO);
          if (mappedId) {
          }
        });

        this.dataSource = new MatTableDataSource(organigrama);
      }

    } catch (error: any) {
      console.error('Error al cargar usuarios:', error)
      this.hasError = true;
      this.Error = 'Error al cargar los datos del organigrama';
    } finally {
      this.isLoading = false;
    }
  }

  async openOrganizationEdit(organigramaElement: Organigrama) {
    const originalEncryptedId = this.originalEncryptedIds.get(organigramaElement.idUsuario!);
    
    if (!originalEncryptedId) {
      console.error('No se encontró el ID encriptado original para:', organigramaElement.idUsuario);
      return;
    }

    let userCompleteData: UserResponse | undefined = this.cachedUsers.find(user => user.IDUSUARIO === originalEncryptedId);
    
    if (!userCompleteData) {
      console.error('No se encontró el usuario en el cache');
      return;
    }

    const usuarioParaEditar: Usuario = {
      id: 0,
      nombre: organigramaElement.nombre_completo,
      organigrama: this.cloneOrganigrama(organigramaElement), 
      userData: userCompleteData 
    }

    this.selectedUsr = usuarioParaEditar;

    let dialogRef = this._matDialog.open(EditOrganizationComponent, {
      width: '700px',
      minWidth: '700px',
      maxHeight: '90vh',
      disableClose: true,
      data: {
        usuarioDATA: this.selectedUsr
      }
    });

    dialogRef.afterClosed().subscribe(res => {
      if (res != null && res != undefined && res != '') {
        this.getUsers();
      }
    })
  }

  private cloneOrganigrama(organigrama: Organigrama): Organigrama {
    const cloned: Organigrama = {
      nombre_completo: organigrama.nombre_completo,
      supervisor1: organigrama.supervisor1,
      idUsuario: organigrama.idUsuario
    };

    Object.keys(organigrama).forEach(key => {
      if (key.startsWith('supervisor') && key !== 'supervisor1') {
        cloned[key] = organigrama[key];
      }
    });

    return cloned;
  }
  

  public getAllSupervisors(organigrama: Organigrama): string[] {
    const supervisors: string[] = [];
    
    Object.keys(organigrama).forEach(key => {
      if (key.startsWith('supervisor')) {
        const supervisor = organigrama[key];
        if (supervisor && supervisor !== 'No configurado' && supervisor !== null) {
          supervisors.push(supervisor);
        }
      }
    });

    return supervisors;
  }

  public getSupervisorsText(organigrama: Organigrama): string {
    const supervisors = this.getAllSupervisors(organigrama);
    
    if (supervisors.length === 0) {
      return 'No configurado';
    } else if (supervisors.length === 1) {
      return supervisors[0];
    } else {
      return `${supervisors[0]} (+${supervisors.length - 1} más)`;
    }
  }

  refreshData() {
    this.getUsers();
  }



async openBlockMenu(userInfo: Organigrama) {
  try {
    const originalEncryptedId = this.originalEncryptedIds.get(userInfo.idUsuario!);
    
    if (!originalEncryptedId) {
      console.error('No se encontró el ID encriptado original para:', userInfo.idUsuario);
      return;
    }

    const currentUserIdFromStorage = localStorage.getItem('idusuario')!;
    const currentDecryptedId = await this._encrypt.decrypt(currentUserIdFromStorage);
    
    
    let freshUserData: UserResponse | undefined;
    
    try {

      const freshUsersResponse: UsersResponse = await lastValueFrom(
        this._usersProfilesService.getUsers(currentUserIdFromStorage, 1)
      );
      
      if (!freshUsersResponse.error) {
        freshUserData = freshUsersResponse.response.find(user => user.IDUSUARIO === originalEncryptedId);
        
        if (freshUserData) {
          console.log('Datos frescos del usuario obtenidos:', {
            estatus: freshUserData.ESTATUS,
            fechaInicioBloqueo: freshUserData.FECHA_INICIO_BLOQUEO,
            fechaFinBloqueo: freshUserData.FECHA_FIN_BLOQUEO
          });
          

          const cacheIndex = this.cachedUsers.findIndex(user => user.IDUSUARIO === originalEncryptedId);
          if (cacheIndex !== -1) {
            this.cachedUsers[cacheIndex] = freshUserData;
          }
        } else {
          console.warn('No se encontraron datos frescos, usando cache');
          freshUserData = this.cachedUsers.find(user => user.IDUSUARIO === originalEncryptedId);
        }
      } else {
        console.warn('Error al obtener datos frescos, usando cache');
        freshUserData = this.cachedUsers.find(user => user.IDUSUARIO === originalEncryptedId);
      }
    } catch (error) {
      console.error('Error al recargar datos del usuario, usando cache:', error);
      freshUserData = this.cachedUsers.find(user => user.IDUSUARIO === originalEncryptedId);
    }
    
    if (!freshUserData) {
      console.error('No se encontró el usuario ni en datos frescos ni en cache');
      return;
    }

    let currentUserEncryptedId = '';
    for (const [decryptedId, encryptedId] of this.originalEncryptedIds.entries()) {
      if (decryptedId === currentDecryptedId) {
        const currentUser = this.cachedUsers.find(user => {
          return this._encrypt.decrypt(user.IDUSUARIO).then(id => id === currentDecryptedId);
        });
        if (currentUser) {
          currentUserEncryptedId = currentUser.IDUSUARIO;
          break;
        }
      }
    }

    const userToBlock: UserToBlock = {
      idUsuario: userInfo.idUsuario!,              
      idUsuarioEncriptado: originalEncryptedId,    
      nombre_completo: userInfo.nombre_completo,
      userData: freshUserData  
    };


    let dialogRef = this._matDialog.open(BlockUserComponent, {
      width: '700px',
      minWidth: '700px',
      maxHeight: '90vh',
      disableClose: true,
      data: {
        userToBlock: userToBlock,
        currentUserEncryptedId: currentUserEncryptedId 
      }
    });

    dialogRef.afterClosed().subscribe(result => {
      if (result && result.success) {
        console.log('Operación completada exitosamente:', result.message);

        this.getUsers();
      }
    });

  } catch (error) {
    console.error('Error al abrir el menú de bloqueo:', error);
  }
}

}