import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
import { DataService } from '../../../services/data.service';
import { ConfigService } from '@services/config.service';

@Component({
  selector: 'app-manage-client',
  templateUrl: './manage-client.component.html',
  styleUrls: ['./manage-client.component.css']
})
export class ManageClientComponent implements OnInit {
  baseUrl: string;
  clientForm!: FormGroup;
  parentUnits: any[] = [];
  parentUnitsWithPaths: { id: string, name: string, path: string }[] = [];
  hardwareProfiles: any[] = [];
  ogLives: any[] = [];
  menus: any[] = [];
  templates: any[] = [];
  repositories: any[] = [];
  loading: boolean = false;
  displayedColumns: string[] = ['name', 'ip'];
  dialogTitle: string;
  protected netifaceTypes = [
    { name: 'Eth0', value: 'eth0' },
    { name: 'Eth1', value: 'eth1' },
    { name: 'Eth2', value: 'eth2' }
  ];
  protected netDriverTypes = [
    { name: 'Generic', value: 'generic' }
  ];
  isEditMode: boolean;

  constructor(
    private fb: FormBuilder,
    private dialogRef: MatDialogRef<ManageClientComponent>,
    private http: HttpClient,
    private configService: ConfigService,
    private toastService: ToastrService,
    private dataService: DataService,
    @Inject(MAT_DIALOG_DATA) public data: any
  ) {
    this.baseUrl = this.configService.apiUrl;
    this.isEditMode = !!data?.uuid;
    this.dialogTitle = this.isEditMode ? 'editClientDialogTitle' : 'addClientDialogTitle';
  }

  ngOnInit(): void {
    this.loading = true;
    this.initForm();
    const observables = [
      this.loadParentUnits(),
      this.loadHardwareProfiles(),
      this.loadOgLives(),
      this.loadPxeTemplates(),
      this.loadRepositories(),
      this.loadMenus()
    ];

    Promise.all(observables).then(() => {
      if (this.isEditMode) {
        this.loadData(this.data.uuid).then(() => {
          this.loading = false;
        });
      } else {
        this.loading = false;
      }
    }).catch(error => {
      console.error('Error loading data:', error);
      this.loading = false;
    });
  }

  initForm(): void {
    this.clientForm = this.fb.group({
      organizationalUnit: [
        this.data.organizationalUnit ? this.data.organizationalUnit['@id'] : null,
        Validators.required
      ],
      name: ['', Validators.required],
      serialNumber: [''],
      netiface: null,
      netDriver: null,
      mac: ['', Validators.pattern(/^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$/)],
      ip: ['', Validators.required],
      template: [null],
      hardwareProfile: [null],
      ogLive: [null],
      repository: [null],
      menu: [null],
      maintenance: [false]
    });
  }

  loadParentUnits(): Promise<void> {
    return new Promise((resolve, reject) => {
      const url = `${this.baseUrl}/organizational-units?page=1&itemsPerPage=10000`;

      this.http.get<any>(url).subscribe(
        response => {
          this.parentUnits = response['hydra:member'];
          this.parentUnitsWithPaths = this.parentUnits.map(unit => ({
            id: unit['@id'],
            name: unit.name,
            path: this.dataService.getOrganizationalUnitPath(unit, this.parentUnits),
            repository: unit.networkSettings?.repository?.['@id'],
            hardwareProfile: unit.networkSettings?.hardwareProfile?.['@id'],
            ogLive: unit.networkSettings?.ogLive?.['@id'],
            menu: unit.networkSettings?.menu?.['@id']
          }));

          const initialUnitId = this.clientForm.get('organizationalUnit')?.value;
          if (initialUnitId) {
            this.setOrganizationalUnitDefaults(initialUnitId);
          }

          resolve();
        },
        error => {
          console.error('Error fetching parent units:', error);
          reject(error);
        }
      );
    });
  }

  getSelectedParentName(): string | undefined {
    const parentId = this.clientForm.get('organizationalUnit')?.value;
    return this.parentUnitsWithPaths.find(unit => unit.id === parentId)?.name;
  }

  loadHardwareProfiles(): Promise<void> {
    return new Promise((resolve, reject) => {
      this.dataService.getHardwareProfiles().subscribe(
        (data: any[]) => {
          this.hardwareProfiles = data;
          resolve();
        },
        error => {
          console.error('Error fetching hardware profiles:', error);
          reject(error);
        }
      );
    });
  }

  loadOgLives(): Promise<void> {
    return new Promise((resolve, reject) => {
      const url = `${this.baseUrl}/og-lives?page=1&itemsPerPage=30`;

      this.http.get<any>(url).subscribe(
        response => {
          this.ogLives = response['hydra:member'];
          resolve();
        },
        error => {
          console.error('Error fetching ogLives:', error);
          reject(error);
        }
      );
    });
  }

  loadPxeTemplates(): Promise<void> {
    return new Promise((resolve, reject) => {
      const url = `${this.baseUrl}/pxe-templates?page=1&itemsPerPage=10000`;

      this.http.get<any>(url).subscribe(
        response => {
          this.templates = response['hydra:member'];
          resolve();
        },
        error => {
          console.error('Error fetching PXE templates:', error);
          reject(error);
        }
      );
    });
  }

  loadMenus(): Promise<void> {
    return new Promise((resolve, reject) => {
      const url = `${this.baseUrl}/menus?page=1&itemsPerPage=10000`;

      this.http.get<any>(url).subscribe(
        response => {
          this.menus = response['hydra:member'];
          resolve();
        },
        error => {
          console.error('Error fetching menus:', error);
          reject(error);
        }
      );
    });
  }

  loadRepositories(): Promise<void> {
    return new Promise((resolve, reject) => {
      const url = `${this.baseUrl}/image-repositories?page=1&itemsPerPage=10000`;

      this.http.get<any>(url).subscribe(
        response => {
          this.repositories = response['hydra:member'];
          resolve();
        },
        error => {
          console.error('Error fetching ogLives:', error);
          reject(error);
        }
      );
    });
  }

  onParentChange(event: any): void {
    this.setOrganizationalUnitDefaults(event.value);
  }

  setOrganizationalUnitDefaults(unitId: string): void {
    const selectedUnit: any = this.parentUnitsWithPaths.find(unit => unit.id === unitId);
    if (selectedUnit) {
      this.clientForm.patchValue({
        repository: selectedUnit.repository || null,
        hardwareProfile: selectedUnit.hardwareProfile || null,
        ogLive: selectedUnit.ogLive || null,
        menu: selectedUnit.menu || null
      });
    }
  }

  loadData(uuid: string): Promise<void> {
    return new Promise((resolve, reject) => {
      const url = `${this.baseUrl}/clients/${uuid}`;

      this.http.get<any>(url).subscribe(
        data => {
          this.clientForm.patchValue({
            name: data.name,
            ip: data.ip,
            mac: data.mac,
            netiface: data.netiface,
            netDriver: data.netDriver,
            serialNumber: data.serialNumber,
            hardwareProfile: data.hardwareProfile ? data.hardwareProfile['@id'] : null,
            organizationalUnit: data.organizationalUnit ? data.organizationalUnit['@id'] : null,
            repository: data.repository ? data.repository['@id'] : null,
            ogLive: data.ogLive ? data.ogLive['@id'] : null,
            template: data.template ? data.template['@id'] : null,
            menu: data.menu ? data.menu['@id'] : null,
            maintenance: data.maintenance
          });
          resolve();
        },
        error => {
          console.error('Error al cargar datos del cliente:', error);
          reject(error);
        }
      );
    });
  }

  onSubmit(): void {
    if (this.clientForm.valid) {
      const formData = this.clientForm.value;

      if (this.isEditMode) {
        const putUrl = `${this.baseUrl}/clients/${this.data.uuid}`;
        const headers = new HttpHeaders({ 'Content-Type': 'application/json' });

        this.http.patch<any>(putUrl, formData, { headers }).subscribe(
          response => {
            this.dialogRef.close();
            this.toastService.success('Cliente actualizado exitosamente', 'Éxito');
          },
          error => {
            console.error('Error al realizar PUT:', error);
            this.toastService.error('Error al actualizar el cliente: ' + error.error['hydra:description'], 'Error');
          }
        );
      } else {
        this.http.post(`${this.baseUrl}/clients`, formData).subscribe(
          (response) => {
            this.toastService.success('Cliente creado exitosamente', 'Éxito');
            this.dialogRef.close({
              client: response,
              organizationalUnit: formData.organizationalUnit,
            });
          },
          (error) => {
            this.toastService.error(error.error['hydra:description'], 'Error al crear el cliente');
          }
        );
      }
    } else {
      this.toastService.error('Formulario inválido. Por favor, revise los campos obligatorios.', 'Error');
    }
  }

  onNoClick(): void {
    this.dialogRef.close();
  }
}
