import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { DatePipe } from "@angular/common";
import { MatTableDataSource } from "@angular/material/table";
import { MatDialog } from "@angular/material/dialog";
import { Router } from "@angular/router";
import { ToastrService } from "ngx-toastr";
import { ManageClientComponent } from "../../shared/clients/manage-client/manage-client.component";
import { ConfigService } from '@services/config.service';

interface ClientInfo {
  property: string;
  value: any;
}

@Component({
  selector: 'app-client-main-view',
  templateUrl: './client-main-view.component.html',
  styleUrl: './client-main-view.component.css'
})
export class ClientMainViewComponent implements OnInit {
  baseUrl: string;
  @ViewChild('assistantContainer') assistantContainer!: ElementRef;
  clientUuid: string;
  clientData: any = {};
  isPartitionAssistantVisible: boolean = false;
  isBootImageVisible: boolean = false;
  isDiskUsageVisible: boolean = true;
  dataSource = new MatTableDataSource<any>();
  generalData: ClientInfo[] = [];
  networkData: ClientInfo[] = [];
  classroomData: ClientInfo[] = [];
  diskUsageData: any[] = [];
  partitions: any[] = [];
  commands: any[] = [];
  chartDisk: any[] = [];
  view: [number, number] = [300, 200];
  showLegend: boolean = true;

  arrayCommands: any[] = [
    { name: 'Enceder', slug: 'power-on' },
    { name: 'Apagar', slug: 'power-off' },
    { name: 'Reiniciar', slug: 'reboot' },
    { name: 'Iniciar Sesión', slug: 'login' },
    { name: 'Crear imagen', slug: 'create-image' },
    { name: 'Clonar/desplegar imagen', slug: 'deploy-image' },
    { name: 'Eliminar Imagen Cache', slug: 'delete-image-cache' },
    { name: 'Particionar y Formatear', slug: 'partition' },
    { name: 'Inventario Software', slug: 'software-inventory' },
    { name: 'Inventario Hardware', slug: 'hardware-inventory' },
    { name: 'Ejecutar script', slug: 'run-script' },
  ];

  datePipe: DatePipe = new DatePipe('es-ES');
  columns = [
    {
      columnDef: 'diskNumber',
      header: 'Disco',
      cell: (partition: any) => `${partition.diskNumber}`,
    },
    {
      columnDef: 'partitionNumber',
      header: 'Particion',
      cell: (partition: any) => `${partition.partitionNumber}`
    },
    {
      columnDef: 'description',
      header: 'Sistema de ficheros',
      cell: (partition: any) => `${partition.filesystem}`
    },
    {
      columnDef: 'size',
      header: 'Tamaño',
      cell: (partition: any) => `${(partition.size / 1024).toFixed(2)} GB`
    },
    {
      columnDef: 'memoryUsage',
      header: 'Uso',
      cell: (partition: any) => `${partition.memoryUsage} %`
    },
    {
      columnDef: 'operativeSystem',
      header: 'SO',
      cell: (partition: any) => `${partition.operativeSystem?.name}`
    },
  ];
  displayedColumns = [...this.columns.map(column => column.columnDef)];
  isDiskUsageEmpty: boolean = true;
  loading: boolean = true;

  constructor(
    private http: HttpClient,
    private dialog: MatDialog,
    private configService: ConfigService,
    private router: Router,
    private toastService: ToastrService
  ) {
    this.baseUrl = this.configService.apiUrl;
    const url = window.location.href;
    const segments = url.split('/');
    this.clientUuid = segments[segments.length - 1];
  }

  ngOnInit() {
    this.clientData = history.state.clientData['@id'];
    this.loadClient(this.clientData)
    this.loadCommands()
    this.calculateDiskUsage();
    this.loading = false;
  }


  loadClient = (uuid: string) => {
    this.http.get<any>(`${this.baseUrl}${uuid}`).subscribe({
      next: data => {
        this.clientData = data;
        this.updateGeneralData();
        this.updateNetworkData();
        this.loadPartitions()
        this.loading = false;
      },
      error: error => {
        console.error('Error al obtener el cliente:', error);
      }
    });
  }

  navigateToGroups() {
    this.router.navigate(['/groups']);
  }

  updateGeneralData() {
    this.generalData = [
      { property: 'Nombre', value: this.clientData?.name || '' },
      { property: 'IP', value: this.clientData?.ip || '' },
      { property: 'MAC', value: this.clientData?.mac || '' },
      { property: 'Nº de serie', value: this.clientData?.serialNumber || '' },
      { property: 'Netiface', value: this.clientData?.netiface || this.clientData?.organizationalUnit?.networkSettings?.netiface || '' },
      { property: 'Perfil hardware', value: this.clientData?.hardwareProfile?.description || '' },
    ];
  }

  updateNetworkData() {
    this.networkData = [
      { property: 'Padre', value: this.clientData?.organizationalUnit?.name || '' },
      { property: 'Pxe', value: this.clientData?.template?.name || '' },
      { property: 'Remote Pc', value: this.clientData.remotePc || '' },
      { property: 'Subred', value: this.clientData?.subnet || '' },
      { property: 'OGlive', value: this.clientData?.ogLive?.name || '' },
      { property: 'Repositorio', value: this.clientData?.repository?.name || '' },
    ];
  }

  calculateDiskUsage() {
    const diskUsageMap = new Map<number, { total: number, used: number, partitions: any[] }>();

    this.partitions.forEach((partition: any) => {
      const diskNumber = partition.diskNumber;

      if (!diskUsageMap.has(diskNumber)) {
        diskUsageMap.set(diskNumber, { total: 0, used: 0, partitions: [] });
      }

      const diskData = diskUsageMap.get(diskNumber);

      if (partition.partitionNumber === 0) {
        diskData!.total = Number((partition.size / 1024).toFixed(2));
      } else {
        diskData!.used += Number((partition.size / 1024).toFixed(2));
        diskData!.partitions.push(partition);
      }
    });

    this.chartDisk = Array.from(diskUsageMap.entries()).map(([diskNumber, { total, used, partitions }]) => {
      const partitionData = partitions.map(partition => ({
        name: `Partición ${partition.partitionNumber}`,
        value: Number((partition.size / 1024).toFixed(2))
      }));

      const freeSpace = total - used;
      if (freeSpace > 0) {
        partitionData.push({
          name: 'Espacio libre',
          value: Number(freeSpace.toFixed(2))
        });
      }

      return {
        diskNumber,
        chartData: partitionData,
        total,
        used,
        percentage: total > 0 ? Math.round((used / total) * 100) : 0
      };
    });

    this.diskUsageData = this.chartDisk;
    this.isDiskUsageEmpty = this.diskUsageData.length === 0;
  }

  onEditClick(event: MouseEvent, uuid: string): void {
    event.stopPropagation();
    const dialogRef = this.dialog.open(ManageClientComponent, { data: { uuid }, width: '900px' });
    dialogRef.afterClosed().subscribe();
  }

  loadPartitions(): void {
    this.http.get<any>(`${this.baseUrl}/partitions?client.id=${this.clientData?.id}&order[diskNumber, partitionNumber]=ASC`).subscribe({
      next: data => {
        const filteredPartitions = data['hydra:member'].filter((partition: any) => partition.partitionNumber !== 0);
        this.dataSource = filteredPartitions;
        this.partitions = filteredPartitions;
        this.calculateDiskUsage();
      },
      error: error => {
        console.error('Error al obtener las particiones:', error);
      }
    });
  }


  loadCommands(): void {
    this.http.get<any>(`${this.baseUrl}/commands?`).subscribe({
      next: data => {
        this.commands = data['hydra:member'];
      },
      error: error => {
        console.error('Error al obtener las particiones:', error);
      }
    });
  }

  onCommandSelect(action: any): void {
    if (action === 'partition') {
      this.openPartitionAssistant();
    }

    if (action === 'create-image') {
      this.openCreateImageAssistant();
    }

    if (action === 'deploy-image') {
      this.openDeployImageAssistant();
    }

    if (action === 'reboot') {
      this.rebootClient();
    }

    if (action === 'power-off') {
      this.powerOffClient();
    }

    if (action === 'power-on') {
      this.powerOnClient();
    }
  }

  rebootClient(): void {
    this.http.post(`${this.baseUrl}/clients/server/${this.clientData.uuid}/reboot`, {}).subscribe(
      response => {
        this.toastService.success('Cliente actualizado correctamente');
      },
      error => {
        this.toastService.error('Error de conexión con el cliente');
      }
    );
  }

  powerOnClient(): void {
    const payload = {
      client: this.clientData['@id']
    }

    this.http.post(`${this.baseUrl}${this.clientData.repository['@id']}/wol`, payload).subscribe(
      response => {
        this.toastService.success('Cliente actualizado correctamente');
      },
      error => {
        this.toastService.error('Error de conexión con el cliente');
      }
    );
  }

  powerOffClient(): void {
    this.http.post(`${this.baseUrl}/clients/server/${this.clientData.uuid}/power-off`, {}).subscribe(
      response => {
        this.toastService.success('Cliente actualizado correctamente');
      },
      error => {
        this.toastService.error('Error de conexión con el cliente');
      }
    );
  }

  openPartitionAssistant(): void {
    this.router.navigate([`/clients/${this.clientData.uuid}/partition-assistant`]).then(r => {
      console.log('navigated', r);
    });
  }

  openCreateImageAssistant(): void {
    this.router.navigate([`/clients/${this.clientData.uuid}/create-image`]).then(r => {
      console.log('navigated', r);
    });
  }

  openDeployImageAssistant(): void {
    this.router.navigate([`/clients/deploy-image`]).then(r => {
      console.log('navigated', r);
    });
  }
}
