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

@Component({
  selector: 'app-create-task',
  templateUrl: './create-task.component.html',
  styleUrls: ['./create-task.component.css']
})
export class CreateTaskComponent implements OnInit {
  baseUrl: string;
  taskForm: FormGroup;
  availableCommandGroups: any[] = [];
  selectedGroupCommands: any[] = [];
  availableIndividualCommands: any[] = [];
  apiUrl: string;
  editing: boolean = false;
  availableOrganizationalUnits: any[] = [];
  selectedUnitChildren: any[] = [];
  selectedClients: any[] = [];
  selectedClientIds: Set<string> = new Set();

  constructor(
    private fb: FormBuilder,
    private http: HttpClient,
    private configService: ConfigService,
    private toastr: ToastrService,
    public dialogRef: MatDialogRef<CreateTaskComponent>,
    @Inject(MAT_DIALOG_DATA) public data: any
  ) {
    this.baseUrl = this.configService.apiUrl;
    this.apiUrl = `${this.baseUrl}/command-tasks`;
    this.taskForm = this.fb.group({
      commandGroup: ['', Validators.required],
      extraCommands: [[]],
      date: ['', Validators.required],
      time: ['', Validators.required],
      notes: [''],
      organizationalUnit: ['', Validators.required],
      selectedChild: [''],
      selectedClients: [[]]
    });
  }

  ngOnInit(): void {
    this.loadCommandGroups();
    this.loadIndividualCommands();
    this.loadOrganizationalUnits();
    if (this.data && this.data.task) {
      this.editing = true;
      this.loadTaskData(this.data.task);
    }
  }

  loadCommandGroups(): void {
    this.http.get<any>(`${this.baseUrl}/command-groups`).subscribe(
      (data) => {
        this.availableCommandGroups = data['hydra:member'];
      },
      (error) => {
        this.toastr.error('Error al cargar los grupos de comandos');
      }
    );
  }

  loadIndividualCommands(): void {
    this.http.get<any>(`${this.baseUrl}/commands`).subscribe(
      (data) => {
        this.availableIndividualCommands = data['hydra:member'];
      },
      (error) => {
        this.toastr.error('Error al cargar los comandos individuales');
      }
    );
  }

  loadOrganizationalUnits(): void {
    this.http.get<any>(`${this.baseUrl}/organizational-units?page=1&itemsPerPage=30`).subscribe(
      (data) => {
        this.availableOrganizationalUnits = data['hydra:member'].filter((unit: any) => unit['type'] === 'organizational-unit');
      },
      (error) => {
        this.toastr.error('Error al cargar las unidades organizacionales');
      }
    );
  }

  loadTaskData(task: any): void {
    this.taskForm.patchValue({
      commandGroup: task.commandGroup ? task.commandGroup['@id'] : '',
      extraCommands: task.commands ? task.commands.map((cmd: any) => cmd['@id']) : [],
      date: task.dateTime ? task.dateTime.split('T')[0] : '',
      time: task.dateTime ? task.dateTime.split('T')[1].slice(0, 5) : '',
      notes: task.notes || '',
      organizationalUnit: task.organizationalUnit ? task.organizationalUnit['@id'] : ''
    });

    if (task.commandGroup) {
      this.selectedGroupCommands = task.commandGroup.commands;
    }
  }

  private collectClassrooms(unit: any): any[] {
    let classrooms = [];
    if (unit.type === 'classroom') {
      classrooms.push(unit);
    }
    if (unit.children && unit.children.length > 0) {
      for (let child of unit.children) {
        classrooms = classrooms.concat(this.collectClassrooms(child));
      }
    }
    return classrooms;
  }

  onOrganizationalUnitChange(): void {
    const selectedUnitId = this.taskForm.get('organizationalUnit')?.value;
    const selectedUnit = this.availableOrganizationalUnits.find(unit => unit['@id'] === selectedUnitId);

    if (selectedUnit) {
      this.selectedUnitChildren = this.collectClassrooms(selectedUnit);
    } else {
      this.selectedUnitChildren = [];
    }

    this.taskForm.patchValue({ selectedChild: '', selectedClients: [] });
    this.selectedClients = [];
    this.selectedClientIds.clear();
  }

  onChildChange(): void {
    const selectedChildId = this.taskForm.get('selectedChild')?.value;

    if (!selectedChildId) {
      this.selectedClients = [];
      return;
    }

    const url = `${this.baseUrl}${selectedChildId}`.replace(/([^:]\/)\/+/g, '$1');

    this.http.get<any>(url).subscribe(
      (data) => {
        if (Array.isArray(data.clients) && data.clients.length > 0) {
          this.selectedClients = data.clients;
        } else {
          this.selectedClients = [];
          this.toastr.warning('El aula seleccionada no tiene clientes.');
        }

        this.taskForm.patchValue({ selectedClients: [] });
        this.selectedClientIds.clear();
      },
      (error) => {
        this.toastr.error('Error al cargar los detalles del aula seleccionada');
      }
    );
  }

  toggleSelectAll() {
    const allSelected = this.areAllSelected();
    if (allSelected) {
      this.selectedClientIds.clear();
    } else {
      this.selectedClients.forEach(client => this.selectedClientIds.add(client.uuid));
    }
    this.taskForm.get('selectedClients')!.setValue(Array.from(this.selectedClientIds));
  }

  areAllSelected(): boolean {
    return this.selectedClients.length > 0 && this.selectedClients.every(client => this.selectedClientIds.has(client.uuid));
  }

  onCommandGroupChange(): void {
    const selectedGroupId = this.taskForm.get('commandGroup')?.value;
    this.http.get<any>(`${this.baseUrl}/command-groups/${selectedGroupId}`).subscribe(
      (data) => {
        this.selectedGroupCommands = data.commands;
      },
      (error) => {
        this.toastr.error('Error al cargar los comandos del grupo seleccionado');
      }
    );
  }

  saveTask(): void {
    if (this.taskForm.invalid) {
      this.toastr.error('Por favor, rellene todos los campos obligatorios');
      return;
    }

    const formData = this.taskForm.value;
    const dateTime = this.combineDateAndTime(formData.date, formData.time);
    const selectedCommands = formData.extraCommands && formData.extraCommands.length > 0
      ? formData.extraCommands.map((id: any) => `/commands/${id}`)
      : null;

    const payload: any = {
      commandGroups: formData.commandGroup ? [`/command-groups/${formData.commandGroup}`] : null,
      dateTime: dateTime,
      notes: formData.notes || '',
      clients: Array.from(this.selectedClientIds).map((uuid: string) => `/clients/${uuid}`),
    };

    if (selectedCommands) {
      payload.commands = selectedCommands;
    }

    if (this.editing) {
      const taskId = this.data.task.uuid;
      this.http.patch<any>(`${this.apiUrl}/${taskId}`, payload).subscribe({
        next: () => {
          this.toastr.success('Tarea actualizada con éxito');
          this.dialogRef.close(true);
        },
        error: () => {
          this.toastr.error('Error al actualizar la tarea');
        }
      });
    } else {
      this.http.post<any>(this.apiUrl, payload).subscribe({
        next: () => {
          this.toastr.success('Tarea creada con éxito');
          this.dialogRef.close(true);
        },
        error: () => {
          this.toastr.error('Error al crear la tarea');
        }
      });
    }
  }

  combineDateAndTime(date: string, time: string): string {
    const dateObj = new Date(date);
    const [hours, minutes] = time.split(':').map(Number);
    dateObj.setHours(hours, minutes, 0);
    return dateObj.toISOString();
  }

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