import { Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
import { DataService as SoftwareService } from '../../software/data.service';
import { DataService } from '../data.service';
import { Observable, startWith } from 'rxjs';
import { debounceTime, switchMap, map } from 'rxjs/operators';
import { ConfigService } from '@services/config.service';

@Component({
  selector: 'app-create-software-profile',
  templateUrl: './create-software-profile.component.html',
  styleUrls: ['./create-software-profile.component.css']
})
export class CreateSoftwareProfileComponent implements OnInit {
  baseUrl: string;
  private apiUrl: string;
  formGroup: FormGroup;
  softwareCollection: any[] = [];
  organizationalUnits: any[] = [];
  operativeSystems: any[] = [];
  softwareProfileId: string | null = null;
  selectedSoftware: any;
  selectedSoftwares: any[] = [];
  softwareControl = new FormControl();
  filteredSoftware!: Observable<any[]>;

  constructor(
    private fb: FormBuilder,
    private http: HttpClient,
    public dialogRef: MatDialogRef<CreateSoftwareProfileComponent>,
    private toastService: ToastrService,
    private softwareDataService: SoftwareService,
    private dataService: DataService,
    private configService: ConfigService,
    @Inject(MAT_DIALOG_DATA) public data: any
  ) {
    this.baseUrl = this.configService.apiUrl;
    this.apiUrl = `${this.baseUrl}/software-profiles`;
    this.formGroup = this.fb.group({
      description: [''],
      comments: [''],
      organizationalUnit: [null, Validators.required],
      operativeSystem: [null]
    });
  }

  ngOnInit(): void {
    if (this.data) {
      this.softwareProfileId = this.data['@id'];
      this.patchFormData();
    }

    this.loadSoftware();
    this.loadOrganizationalUnits();
    this.loadOperativeSystems();

    this.filteredSoftware = this.softwareControl.valueChanges.pipe(
      startWith(''),
      debounceTime(300),
      switchMap(value => this._filterSoftware(value))
    );
  }

  patchFormData(): void {
    this.formGroup.patchValue({
      description: this.data.description || '',
      comments: this.data.comments || '',
      organizationalUnit: this.data.organizationalUnit ? this.data.organizationalUnit['@id'] : null,
      operativeSystem: this.data.operativeSystem ? this.data.operativeSystem['@id'] : null,
    });
  }

  loadSoftware() {
    this.http.get<any>(`${this.baseUrl}/software?page=1&itemsPerPage=10`).subscribe(
      response => {
        this.softwareCollection = response['hydra:member'];
      },
      error => {
        console.error('Error fetching software:', error);
      }
    );
  }

  loadOrganizationalUnits() {
    this.http.get<any>(`${this.baseUrl}/organizational-units?page=1&itemsPerPage=10000`).subscribe(
      response => {
        this.organizationalUnits = response['hydra:member'];
      },
      error => {
        console.error('Error fetching organizational units:', error);
      }
    );
  }

  loadOperativeSystems() {
    this.http.get<any>(`${this.baseUrl}/operative-systems?page=1&itemsPerPage=10000`).subscribe(
      response => {
        this.operativeSystems = response['hydra:member'];
      },
      error => {
        console.error('Error fetching operative systems:', error);
      }
    );
  }

  private _filterSoftware(value: string): Observable<any[]> {
    return this.softwareDataService.getSoftwareCollection({ name: value }).pipe(
      map(response => response || [])
    );
  }

  displayFnClient(client: any): string {
    return client && client.name ? client.name : '';
  }

  onOptionClientSelected(software: any) {
    if (!this.selectedSoftwares.find(s => s.id === software.id)) {
      this.selectedSoftwares.push(software);
    }
    this.softwareControl.setValue('');
  }

  addSoftware() {
    const software = this.softwareCollection.find(s => s.id === this.selectedSoftware);
    if (software && !this.selectedSoftwares.includes(software)) {
      this.selectedSoftwares.push(software);
    }
  }

  removeSoftware(software: any) {
    this.selectedSoftwares = this.selectedSoftwares.filter(s => s.id !== software.id);
  }

  onCancel(event: Event): void {
    event.preventDefault();
    this.dialogRef.close();
  }

  onSubmit(): void {
    if (this.formGroup.valid) {
      const payload = {
        description: this.formGroup.value.description,
        comments: this.formGroup.value.comments,
        softwareCollection: this.selectedSoftwares.map(s => s['@id']),
        organizationalUnit: this.formGroup.value.organizationalUnit,
        operativeSystem: this.formGroup.value.operativeSystem
      };

      if (this.softwareProfileId) {
        this.http.put(`${this.baseUrl}${this.softwareProfileId}`, payload).subscribe(
          () => {
            this.toastService.success('Software editado correctamente');
            this.dialogRef.close();
          },
          (error) => {
            this.toastService.error(error.error['hydra:description']);
            console.error('Error al editar el software', error);
          }
        );
      } else {
        this.http.post(`${this.apiUrl}`, payload).subscribe(
          () => {
            this.toastService.success('Software añadido correctamente');
            this.dialogRef.close();
          },
          (error) => {
            this.toastService.error(error.error['hydra:description']);
            console.error('Error al añadir software', error);
          }
        );
      }
    }
  }
}
