import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { ConfigService } from '@services/config.service';
import { MatTabChangeEvent } from '@angular/material/tabs';

@Component({
  selector: 'app-global-status',
  templateUrl: './global-status.component.html',
  styleUrl: './global-status.component.css'
})
export class GlobalStatusComponent implements OnInit {
  baseUrl: string;
  loading: boolean = false;
  errorOgBoot: boolean = false;
  errorDhcp: boolean = false;
  errorRepositories: { [key: string]: boolean } = {};
  installedOgLives: any[] = [];
  subnets: any[] = [];
  showLabels: boolean = true;
  isDoughnut: boolean = true;
  colorScheme: any = {
    domain: ['#df200d', '#26a700']
  };
  view: [number, number] = [400, 220];
  repositoriesUrl: string;
  repositories: any[] = [];
  repositoryStatuses: { [key: string]: any } = {};

  ogBootApiUrl: string;
  ogBootDiskUsage: any = {};
  ogBootServicesStatus: any = {};
  ogBootDiskUsageChartData: any[] = [];

  dhcpApiUrl: string;
  dhcpDiskUsage: any = {};
  dhcpServicesStatus: any = {};
  dhcpDiskUsageChartData: any[] = [];
  isDhcp: boolean = false;
  isRepository: boolean = false;

  constructor(
    private configService: ConfigService,
    private http: HttpClient
  ) {
    this.baseUrl = this.configService.apiUrl;
    this.ogBootApiUrl = `${this.baseUrl}/og-boot/status`;
    this.dhcpApiUrl = `${this.baseUrl}/og-dhcp/status`;
    this.repositoriesUrl = `${this.baseUrl}/image-repositories`;
  }

  ngOnInit(): void {
    this.loadOgBootStatus();
  }

  [key: string]: any;

  loadStatus(apiUrl: string, diskUsage: any, servicesStatus: any, diskUsageChartData: any[], installedOgLives: any[], isDhcp: boolean, errorState: string): void {
    this.loading = true;
    this[errorState] = false;
    const timeoutId = setTimeout(() => {
      this.loading = false;
      this[errorState] = true;
    }, 3500);
    this.http.get<any>(apiUrl).subscribe({
      next: data => {
        diskUsage.used = data.message.disk_usage.used;
        diskUsage.available = data.message.disk_usage.available;
        diskUsage.total = data.message.disk_usage.total;
        diskUsage.percentage = data.message.disk_usage.percentage;

        Object.assign(servicesStatus, data.message.services_status);

        if (isDhcp) {
          this.subnets.length = 0;
          if (data.message.subnets) {
            this.subnets.push(...data.message.subnets);
          }
        } else {
          installedOgLives.length = 0;
          if (data.message.installed_oglives) {
            installedOgLives.push(...data.message.installed_oglives);
          }
        }

        diskUsageChartData.length = 0;
        diskUsageChartData.push(
          { name: 'Usado', value: parseFloat(diskUsage.used) },
          { name: 'Disponible', value: parseFloat(diskUsage.available) }
        );

        this.loading = false;
        clearTimeout(timeoutId);
      },
      error: error => {
        console.log(error);
        this.loading = false;
        this[errorState] = true;
        clearTimeout(timeoutId);
      }
    });
  }

  loadRepositories(): void {
    this.loading = true;
    this.errorRepositories = {};
    const timeoutId = setTimeout(() => {
      this.loading = false;
      this.repositories.forEach(repository => {
        if (!(repository.uuid in this.errorRepositories)) {
          this.errorRepositories[repository.uuid] = true;
        }
      });
    }, 5000);

    this.http.get<any>(`${this.repositoriesUrl}?page=1&itemsPerPage=10`).subscribe(
      data => {
        this.repositories = data['hydra:member'];
        let remainingRepositories = this.repositories.length;

        this.repositories.forEach(repository => {
          this.loadRepositoryStatus(repository.uuid, (errorOccurred: boolean) => {
            remainingRepositories--;

            this.errorRepositories[repository.uuid] = errorOccurred;

            if (remainingRepositories === 0) {
              this.loading = false;
              clearTimeout(timeoutId);
            }
          });
        });
      },
      error => {
        console.error('Error fetching repositories', error);
        this.loading = false;
        this.repositories.forEach(repository => {
          this.errorRepositories[repository.uuid] = true;
        });
        clearTimeout(timeoutId);
      }
    );
  }

  loadRepositoryStatus(repositoryUuid: string, callback: (errorOccurred: boolean) => void): void {
    const timeoutId = setTimeout(() => {
      callback(true);
    }, 5000);
    this.http.get<any>(`${this.baseUrl}/image-repositories/server/${repositoryUuid}/status`).subscribe(
      data => {
        const output = data.output;
        this.repositoryStatuses[repositoryUuid] = {
          ...output,
          disk: {
            ...output.disk,
            used: parseFloat(output.disk.used),
            available: parseFloat(output.disk.available)
          },
          ram: {
            ...output.ram,
            used: parseFloat(output.ram.used),
            available: parseFloat(output.ram.available)
          }
        };
        clearTimeout(timeoutId);
        callback(false);
      },
      error => {
        console.error(`Error fetching status for repository ${repositoryUuid}`, error);
        clearTimeout(timeoutId);
        callback(true);
      }
    );
  }

  loadOgBootStatus(): void {
    this.isDhcp = false;
    this.loadStatus(this.ogBootApiUrl, this.ogBootDiskUsage, this.ogBootServicesStatus, this.ogBootDiskUsageChartData, this.installedOgLives, this.isDhcp, 'errorOgBoot');
  }

  loadDhcpStatus(): void {
    this.isDhcp = true;
    this.loadStatus(this.dhcpApiUrl, this.dhcpDiskUsage, this.dhcpServicesStatus, this.dhcpDiskUsageChartData, this.installedOgLives, this.isDhcp, 'errorDhcp');
  }

  onTabChange(event: MatTabChangeEvent): void {
    if (event.tab.textLabel === 'OgBoot') {
      this.loadOgBootStatus();
    } else if (event.tab.textLabel === 'Dhcp') {
      this.loadDhcpStatus();
    } else if (event.tab.textLabel === 'Repositorios') {
      if (this.repositories.length === 0) {
        this.loadRepositories();
      }
    }
  }
}