import { MatCardModule } from '@angular/material/card';
import { ChangeDetectionStrategy, Component, Inject, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { MatDialog } from '@angular/material/dialog';
import { MatTableDataSource } from '@angular/material/table';
import { UsersProfilesService } from '../../../../services/users-profiles.service';
import { EncService } from '../../../../services/enc.service';
import { FunctionsService } from '../../../../services/functions.service';
import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
import { lastValueFrom } from 'rxjs';
import { UserResponse, UsersResponse } from '../../../../interfaces/users.interface';
import { Organigrama, Usuario } from '../organization.component';

export interface SupervisorOption {
  value: string;
  display: string;
  idUsuario: string;
}

export interface SupervisorItem {
  id: string;
  value: string | null;
  level: number;
  required: boolean;
}

@Component({
  selector: 'app-edit-organization',
  templateUrl: './edit-organization.component.html',
  styleUrl: './edit-organization.component.css',
  standalone: false
})
export class EditOrganizationComponent implements OnInit {
  
  usuario: Usuario;
  isLoading: boolean = false;
  hasError: boolean = false;
  errorMessage: string = '';
  listaSupervisores: SupervisorOption[] = [];
  originalUsuario: Usuario;
  supervisores: SupervisorItem[] = [];
  
  constructor(
    @Inject(MAT_DIALOG_DATA) public data: {usuarioDATA: Usuario},
    private dialogRef: MatDialogRef<EditOrganizationComponent>,
    private _usersProfilesService: UsersProfilesService,
    private _encrypt: EncService,
    private _functionService: FunctionsService
  ) {
    this.usuario = {
      ...data.usuarioDATA,
      organigrama: data.usuarioDATA.organigrama ? 
        { ...data.usuarioDATA.organigrama } :
        {
          nombre_completo: data.usuarioDATA.nombre,
          supervisor1: 'No configurado',
          supervisor2: null,
          supervisor3: null,
          supervisor4: null,
          supervisor5: null,
          supervisor6: null
        }
    };
    
    this.originalUsuario = JSON.parse(JSON.stringify(this.usuario));
    this.initializeSupervisores();
  }
  
  private initializeSupervisores(): void {
    this.supervisores = [];
    
    this.supervisores.push({
      id: this.generateUniqueId(),
      value: this.usuario.organigrama?.supervisor1 || 'No configurado',
      level: 1,
      required: true
    });

    const supervisoresConfigurados = this.getAllConfiguredSupervisors();
    
    supervisoresConfigurados.forEach((supervisor, index) => {
      if (supervisor && supervisor !== 'No configurado' && supervisor !== null) {
        this.supervisores.push({
          id: this.generateUniqueId(),
          value: supervisor,
          level: index + 2, 
          required: false
        });
      }
    });

    if (this.supervisores.length === 1) {
      this.supervisores.push({
        id: this.generateUniqueId(),
        value: 'No configurado',
        level: 2,
        required: false
      });
    }
  }

  private getAllConfiguredSupervisors(): (string | null)[] {
    const supervisores: (string | null)[] = [];
    
    if (!this.usuario.organigrama) return supervisores;

    const supervisorFields = [
      this.usuario.organigrama.supervisor2,
      this.usuario.organigrama.supervisor3,
      this.usuario.organigrama.supervisor4,
      this.usuario.organigrama.supervisor5,
      this.usuario.organigrama.supervisor6
    ];

    const organigramaKeys = Object.keys(this.usuario.organigrama);
    const additionalSupervisors = organigramaKeys
      .filter(key => key.startsWith('supervisor') && !['supervisor1', 'supervisor2', 'supervisor3', 'supervisor4', 'supervisor5', 'supervisor6'].includes(key))
      .map(key => (this.usuario.organigrama as any)[key]);

    return [...supervisorFields, ...additionalSupervisors];
  }

  private generateUniqueId(): string {
    return 'supervisor_' + Math.random().toString(36).substr(2, 9) + '_' + Date.now();
  }
  
  async ngOnInit(): Promise<void> {
    if (!this.usuario.organigrama) {
      this.hasError = true;
      this.errorMessage = 'No se pudieron cargar los datos del organigrama';
      return;
    }
    
    await this.loadSupervisores();
  }
  
  private async loadSupervisores(): Promise<void> {
    try {
      this.isLoading = true;
      
      let idUser = localStorage.getItem('idusuario')!;
      let users: UsersResponse = await lastValueFrom(this._usersProfilesService.getUsers(idUser, 1));
      
      if (!users.error) {
        this.listaSupervisores = [];
        
        for (const user of users.response) {
          if (user.PERFIL.includes('Super usuario') && user.ESTATUS !== 'Eliminado') {
            let idDesencrypt = await this._encrypt.decrypt(user.IDUSUARIO);
            let username = this._functionService.buildName(user.NOMBRE, user.APEPAT, user.APEMAT);
            let displayName = `${username} (${idDesencrypt})`;
            
            if (displayName !== this.usuario.organigrama?.nombre_completo) {
              this.listaSupervisores.push({
                value: displayName,
                display: displayName,
                idUsuario: idDesencrypt
              });
            }
          }
        }
      } else {
        this.hasError = true;
        this.errorMessage = 'Error al cargar la lista de supervisores';
      }
      
    } catch (error) {
      console.error('Error loading supervisores:', error);
      this.hasError = true;
      this.errorMessage = 'Error al cargar la lista de supervisores';
    } finally {
      this.isLoading = false;
    }
  }

  agregarSupervisor(): void {
    const nuevoNivel = this.getNextAvailableLevel();
    
    const nuevoSupervisor: SupervisorItem = {
      id: this.generateUniqueId(),
      value: 'No configurado',
      level: nuevoNivel,
      required: false
    };
    
    this.supervisores.push(nuevoSupervisor);
    this.reorderSupervisores();
  }

  private getNextAvailableLevel(): number {
    const nivelesUsados = this.supervisores.map(s => s.level);
    const maxNivel = Math.max(...nivelesUsados);
    return maxNivel + 1;
  }

  eliminarSupervisor(id: string): void {
    const supervisor = this.supervisores.find(s => s.id === id);
    
    if (supervisor && supervisor.level > 1) {
      this.supervisores = this.supervisores.filter(supervisor => supervisor.id !== id);
      this.reorderSupervisores();
    }
  }

  private reorderSupervisores(): void {
    this.supervisores.sort((a, b) => a.level - b.level);
    
    this.supervisores.forEach((supervisor, index) => {
      if (supervisor.required) {
        supervisor.level = 1; 
      } else {
        supervisor.level = index + 1; 
      }
    });
  }

  onSupervisorChange(supervisorId: string, newValue: string): void {
    const supervisor = this.supervisores.find(s => s.id === supervisorId);
    if (supervisor) {
      supervisor.value = newValue;
    }
  }

  getAvailableSupervisores(currentSupervisorId: string): SupervisorOption[] {
    const selectedValues = this.supervisores
      .filter(s => s.id !== currentSupervisorId && s.value && s.value !== 'No configurado')
      .map(s => s.value);
    
    return this.listaSupervisores.filter(supervisor => 
      !selectedValues.includes(supervisor.value)
    );
  }

  canAddSupervisor(): boolean {
    return this.listaSupervisores.length > 0 && this.getAvailableSupervisores('').length > 0;
  }

  canRemoveSupervisor(supervisor: SupervisorItem): boolean {
    return !supervisor.required && this.supervisores.length > 1;
  }

  getSupervisorLabel(supervisor: SupervisorItem): string {
    if (supervisor.level === 1) {
      return 'Supervisor Principal';
    } else {
      return `Supervisor ${supervisor.level}`;
    }
  }

  getSupervisorHint(supervisor: SupervisorItem): string {
    if (supervisor.level === 1) {
      return 'Supervisor principal (obligatorio)';
    } else {
      return 'Supervisor adicional (opcional)';
    }
  }

  async guardarCambios(): Promise<void> {
    const supervisorPrincipal = this.supervisores.find(s => s.required);
    if (!supervisorPrincipal || !supervisorPrincipal.value || supervisorPrincipal.value === 'No configurado') {
      this.hasError = true;
      this.errorMessage = 'El Supervisor Principal es obligatorio';
      return;
    }
    
    try {
      this.isLoading = true;
      this.hasError = false;
      this.errorMessage = '';
      
      if (!this.usuario.userData) {
        throw new Error('No se encontraron los datos completos del usuario');
      }
      
      const userData: UserResponse = this.usuario.userData;
      const encryptedUserIdToModify = userData.IDUSUARIO; 
      
      
      const organigramaArray = [];
      
      for (const supervisor of this.supervisores) {
        if (supervisor.value && supervisor.value !== 'No configurado') {
          const supervisorMatch = supervisor.value.match(/\((\d+)\)$/);
          if (supervisorMatch) {
            const supervisorId = supervisorMatch[1];
            const encryptedSupervisorId = await this._encrypt.encrypt(supervisorId);
            organigramaArray.push({
              level: supervisor.level.toString(),
              id_chief: encryptedSupervisorId
            });
          }
        }
      }
      
      const formData = new FormData();
      const currentUserIdFromStorage = localStorage.getItem('idusuario')!;
      
      formData.append('configured_user', encryptedUserIdToModify);     
      formData.append('id_user', currentUserIdFromStorage);
      const lineaValue = 1;
      formData.append('linea', lineaValue.toString());
      
      if (userData.APEMAT) formData.append('sApe', userData.APEMAT);
      if (userData.ESTATUS) formData.append('estatus', userData.ESTATUS);
      
      formData.append('organization', JSON.stringify(organigramaArray));
      
      const result = await lastValueFrom(this._usersProfilesService.ConfigureUserOrganization(formData));
      
      if (result.error) {
        throw new Error(result.msg || 'Error al actualizar el usuario');
      }
      
      this.actualizarUsuarioConSupervisores();
      this.dialogRef.close(this.usuario);
      
    } catch (error) {
      console.error('Error al guardar cambios:', error);
      this.hasError = true;
      this.errorMessage = error instanceof Error ? error.message : 'Error al guardar los cambios. Intente nuevamente.';
    } finally {
      this.isLoading = false;
    }
  }

  private actualizarUsuarioConSupervisores(): void {
    if (this.usuario.organigrama) {
      const nuevoOrganigrama: any = {
        nombre_completo: this.usuario.organigrama.nombre_completo,
        idUsuario: this.usuario.organigrama.idUsuario
      };

      nuevoOrganigrama.supervisor1 = 'No configurado';
      nuevoOrganigrama.supervisor2 = null;
      nuevoOrganigrama.supervisor3 = null;
      nuevoOrganigrama.supervisor4 = null;
      nuevoOrganigrama.supervisor5 = null;
      nuevoOrganigrama.supervisor6 = null;

      this.supervisores.forEach(supervisor => {
        if (supervisor.value && supervisor.value !== 'No configurado') {
          if (supervisor.level <= 6) {
            nuevoOrganigrama[`supervisor${supervisor.level}`] = supervisor.value;
          } else {
            nuevoOrganigrama[`supervisor${supervisor.level}`] = supervisor.value;
          }
        }
      });

      this.usuario.organigrama = nuevoOrganigrama;
    }
  }

  cancelar(): void {
    this.dialogRef.close();
  }
  
  hasChanges(): boolean {
    const currentState = this.supervisores
      .filter(s => s.value && s.value !== 'No configurado')
      .map(s => ({
        level: s.level,
        value: s.value
      }))
      .sort((a, b) => a.level - b.level);
    
    const originalSupervisores = [];
    
    if (this.originalUsuario.organigrama?.supervisor1 && this.originalUsuario.organigrama.supervisor1 !== 'No configurado') {
      originalSupervisores.push({
        level: 1,
        value: this.originalUsuario.organigrama.supervisor1
      });
    }

    const originalAdditional = this.getAllConfiguredSupervisors();
    originalAdditional.forEach((supervisor, index) => {
      if (supervisor && supervisor !== 'No configurado' && supervisor !== null) {
        originalSupervisores.push({
          level: index + 2,
          value: supervisor
        });
      }
    });

    const originalState = originalSupervisores.sort((a, b) => a.level - b.level);
    
    return JSON.stringify(currentState) !== JSON.stringify(originalState);
  }

  trackBySupervisor(index: number, supervisor: SupervisorItem): string {
    return supervisor.id;
  }


}