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

@Component({
  selector: 'app-manage-organizational-unit',
  templateUrl: './manage-organizational-unit.component.html',
  styleUrls: ['./manage-organizational-unit.component.css']
})
export class ManageOrganizationalUnitComponent implements OnInit {
  baseUrl: string;
  isLinear = true;
  generalFormGroup: FormGroup;
  additionalInfoFormGroup: FormGroup;
  networkSettingsFormGroup: FormGroup;
  classroomInfoFormGroup: FormGroup;
  types: string[] = ['organizational-unit', 'classrooms-group', 'classroom', 'clients-group'];
  typeTranslations: { [key: string]: string } = {
    'organizational-unit': 'Centro',
    'classrooms-group': 'Grupo de aulas',
    'classroom': 'Aula',
    'clients-group': 'Grupo de clientes'
  };
  parentUnits: any[] = [];
  hardwareProfiles: any[] = [];
  isEditMode: boolean;
  currentCalendar: any = [];
  ogLives: any[] = [];
  menus: any[] = [];
  repositories: any[] = [];
  parentUnitsWithPaths: { id: string, name: string, path: string }[] = [];
  protected p2pModeOptions = [
    { "name": 'Leecher', "value": "leecher" },
    { "name": 'Peer', "value": "peer" },
    { "name": 'Seeder', "value": "seeder" },
  ];
  protected multicastModeOptions = [
    { "name": 'Half duplex', "value": "half" },
    { "name": 'Full duplex', "value": "full" },
  ];
  protected netifaceTypes = [
    { name: 'Eth0', value: 'eth0' },
    { name: 'Eth1', value: 'eth1' },
    { name: 'Eth2', value: 'eth2' }
  ];
  @Output() unitAdded = new EventEmitter();
  calendars: any;
  loading: boolean = false;

  constructor(
    private _formBuilder: FormBuilder,
    private dialogRef: MatDialogRef<ManageOrganizationalUnitComponent>,
    private http: HttpClient,
    private dataService: DataService,
    private configService: ConfigService,
    private toastService: ToastrService,
    @Inject(MAT_DIALOG_DATA) public data: any
  ) {
    this.isEditMode = !!data?.uuid;
    this.baseUrl = this.configService.apiUrl;
    this.generalFormGroup = this._formBuilder.group({
      name: [null, Validators.required],
      parent: [data?.parent ? data.parent['@id'] : null],
      description: [null],
      type: [null, Validators.required],
      excludeParentChanges: [false],
    });

    this.additionalInfoFormGroup = this._formBuilder.group({
      comments: [null],
    });

    this.networkSettingsFormGroup = this._formBuilder.group({
      ogLive: [ null],
      repository: [null],
      proxy: [null],
      dns: [null],
      netmask: [null],
      router: [null],
      ntp: [null],
      netiface: [null],
      p2pMode: [null],
      p2pTime: [null],
      mcastIp: [null],
      mcastSpeed: [null],
      mcastPort: [null],
      mcastMode: [null],
      menu: [null],
      hardwareProfile: [null]
    });

    this.classroomInfoFormGroup = this._formBuilder.group({
      location: [null],
      projector: [false],
      board: [false],
      capacity: [null, [Validators.required, Validators.min(0)]],
      remoteCalendar: [null]
    });

    if (this.isEditMode) {
      this.loadData(data.uuid);
    }
  }

  ngOnInit() {
    this.loadParentUnits();
    this.loadHardwareProfiles();
    this.loadCalendars();
    this.loadOgLives();
    this.loadRepositories();
    this.loadMenus()
  }

  get filteredTypes(): string[] {
    return this.generalFormGroup.get('parent')?.value ? this.types.filter(type => type !== 'organizational-unit') : this.types;
  }

  loadParentUnits() {
    this.loading = true;
    const url = `${this.baseUrl}/organizational-units?page=1&itemsPerPage=1000`;
    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'],
          mcastIp: unit.networkSettings?.mcastIp,
          mcastSpeed: unit.networkSettings?.mcastSpeed,
          mcastPort: unit.networkSettings?.mcastPort,
          mcastMode: unit.networkSettings?.mcastMode,
          netiface: unit.networkSettings?.netiface,
          p2pMode: unit.networkSettings?.p2pMode,
          p2pTime: unit.networkSettings?.p2pTime,
          dns: unit.networkSettings?.dns,
          netmask: unit.networkSettings?.netmask,
          router: unit.networkSettings?.router,
          ntp: unit.networkSettings?.ntp
        }));

        const initialUnitId = this.generalFormGroup.get('parent')?.value;
        if (initialUnitId) {
          this.setOrganizationalUnitDefaults(initialUnitId);
        }
        this.loading = false;
      },
      error => {
        console.error('Error fetching parent units:', error);
        this.loading = false;
      }
    );
  }

  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.networkSettingsFormGroup.patchValue({
        repository: selectedUnit.repository || null,
        hardwareProfile: selectedUnit.hardwareProfile || null,
        ogLive: selectedUnit.ogLive || null,
        menu: selectedUnit.menu || null,
        mcastIp: selectedUnit.mcastIp || null,
        mcastSpeed: selectedUnit.mcastSpeed || null,
        mcastPort: selectedUnit.mcastPort || null,
        mcastMode: selectedUnit.mcastMode || null,
        netiface: selectedUnit.netiface || null,
        p2pMode: selectedUnit.p2pMode || null,
        p2pTime: selectedUnit.p2pTime || null,
        dns: selectedUnit.dns || null,
        netmask: selectedUnit.netmask || null,
        router: selectedUnit.router || null,
        ntp: selectedUnit.ntp || null
      });
    }
  }

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

  loadHardwareProfiles(): void {
    this.loading = true;
    this.dataService.getHardwareProfiles().subscribe(
      (data: any[]) => {
        this.hardwareProfiles = data;
        this.loading = false;
      },
      (error: any) => {
        console.error('Error fetching hardware profiles', error);
        this.loading = false;
      }
    );
  }

  loadMenus(): void {
    this.loading = true;
    const url = `${this.baseUrl}/menus?page=1&itemsPerPage=10000`;

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

  loadOgLives() {
    this.loading = true;
    this.dataService.getOgLives().subscribe(
      (data: any[]) => {
        this.ogLives = data;
        this.loading = false;
      },
      error => {
        console.error('Error fetching ogLives', error);
        this.loading = false;
      }
    );
  }

  loadRepositories() {
    this.loading = true;
    this.dataService.getRepositories().subscribe(
      (data: any[]) => {
        this.repositories = data;
        this.loading = false;
      },
      error => {
        console.error('Error fetching repositories', error);
        this.loading = false;
      }
    );
  }

  loadCalendars() {
    this.loading = true;
    const apiUrl = `${this.baseUrl}/remote-calendars?page=1&itemsPerPage=30`;
    this.http.get<any>(apiUrl).subscribe(
      response => {
        this.calendars = response['hydra:member'];
        this.loading = false;
      },
      error => {
        console.error('Error loading calendars', error);
        this.toastService.error('Error loading current calendar');
        this.loading = false;
      }
    );
  }

  loadCurrentCalendar(uuid: string): void {
    this.loading = true;
    const apiUrl = `${this.baseUrl}/remote-calendars/${uuid}`;
    this.http.get<any>(apiUrl).subscribe(
      response => {
        this.currentCalendar = response;
        this.loading = false;
      },
      error => {
        console.error('Error loading current calendar', error);
        this.toastService.error('Error loading current calendar');
        this.loading = false;
      }
    );
  }

  onCalendarChange(event: any) {
    this.generalFormGroup.value.remoteCalendar = event.value;
  }

  onOgLiveChange(event: any) {
    this.networkSettingsFormGroup.value.ogLive = event.value;
  }

  onRepositoryChange(event: any) {
    this.networkSettingsFormGroup.value.repository = event.value;
  }

  loadData(uuid: string) {
    this.loading = true;
    const url = `${this.baseUrl}/organizational-units/${uuid}`;

    this.http.get<any>(url).subscribe(
      data => {
        this.generalFormGroup.patchValue({
          name: data.name,
          parent: data.parent ? data.parent['@id'] : '',
          description: data.description,
          type: data.type,
          excludeParentChanges: data.excludeParentChanges
        });
        this.additionalInfoFormGroup.patchValue({
          comments: data.comments
        });
        this.networkSettingsFormGroup.patchValue({
          proxy: data.networkSettings.proxy,
          dns: data.networkSettings.dns,
          netmask: data.networkSettings.netmask,
          router: data.networkSettings.router,
          ntp: data.networkSettings.ntp,
          netiface: data.networkSettings.netiface,
          p2pMode: data.networkSettings.p2pMode,
          p2pTime: data.networkSettings.p2pTime,
          mcastIp: data.networkSettings.mcastIp,
          mcastSpeed: data.networkSettings.mcastSpeed,
          mcastPort: data.networkSettings.mcastPort,
          mcastMode: data.networkSettings.mcastMode,
          menu: data.networkSettings.menu ? data.networkSettings.menu['@id'] : null,
          hardwareProfile: data.networkSettings.hardwareProfile ? data.networkSettings.hardwareProfile['@id'] : null,
          ogLive: data.networkSettings.ogLive ? data.networkSettings.ogLive['@id'] : null,
          repository: data.networkSettings.repository ? data.networkSettings.repository['@id'] : null
        });
        this.classroomInfoFormGroup.patchValue({
          location: data.location,
          projector: data.projector,
          board: data.board,
          capacity: data.capacity,
          remoteCalendar: data.remoteCalendar ? data.remoteCalendar['@id'] : null
        });
        this.loading = false;
      },

      error => {
        console.error('Error fetching data for edit:', error);
        this.toastService.error('Error fetching data');
        this.loading = false;
        this.onNoClick();
      }
    );
  }

  onSubmit() {
    if (this.generalFormGroup.valid && this.additionalInfoFormGroup.valid && this.networkSettingsFormGroup.valid) {
      const parentValue = this.generalFormGroup.value.parent;
      const formData = {
        name: this.generalFormGroup.value.name,
        excludeParentChanges: this.generalFormGroup.value.excludeParentChanges,
        parent: parentValue || null,
        description: this.generalFormGroup.value.description,
        comments: this.additionalInfoFormGroup.value.comments,
        remoteCalendar: this.generalFormGroup.value.remoteCalendar,
        type: this.generalFormGroup.value.type,
        networkSettings: this.networkSettingsFormGroup.value,
        location: this.classroomInfoFormGroup.value.location,
        projector: this.classroomInfoFormGroup.value.projector,
        board: this.classroomInfoFormGroup.value.board,
        capacity: this.classroomInfoFormGroup.value.capacity,
      };

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

        this.http.put<any>(putUrl, formData, { headers }).subscribe(
          response => {
            this.unitAdded.emit();
            this.dialogRef.close();
            this.toastService.success('Editado exitosamente', 'Éxito');
          },
          error => {
            console.error('Error al realizar PUT:', error);
            const errorMessages = error.error['hydra:description'].split('\n');
            errorMessages.forEach((message: string) => {
              const cleanedMessage = message.replace(/networkSettings\.(\w+):/, 'Error $1:');
              this.toastService.error(cleanedMessage);
            });
          }
        );
      } else {
        const postUrl = `${this.baseUrl}/organizational-units`;
        const headers = new HttpHeaders({ 'Content-Type': 'application/json' });

        this.http.post<any>(postUrl, formData, { headers }).subscribe(
          response => {
            this.unitAdded.emit(response);
            this.dialogRef.close(response);
            this.toastService.success('Creado exitosamente', 'Éxito');
          },
          error => {
            console.error('Error al realizar POST:', error);
            const errorMessages = error.error['hydra:description'].split('\n');
            errorMessages.forEach((message: string) => {
              const cleanedMessage = message.replace(/networkSettings\.(\w+):/, 'Error $1:');
              this.toastService.error(cleanedMessage);
            });
          }
        );
      }
    }
  }

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