import { Component } from '@angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { PermissionNode } from '../utils/app.interfaces';
import { Observable } from 'rxjs';
import { CredentialService } from '../services/credential.service';
import { I18NService } from '../services/i18n.service';
import { HttpURIService } from '../app.http.uri.service';
import { TranslateModule } from '@ngx-translate/core';
import { URIKey } from '../utils/uri-enums';
import { HttpErrorResponse, HttpParams } from '@angular/common/http';
import { FormConstants, HiddenValues, SuccessMessages } from '../utils/enums';
import { CommonModule } from '@angular/common';
import { NgSelectModule } from '@ng-select/ng-select';

@Component({
  selector: 'app-user-permissions',
  imports: [TranslateModule, ReactiveFormsModule, CommonModule, TranslateModule, NgSelectModule],
  templateUrl: './user-permissions.component.html',
  styleUrl: './user-permissions.component.scss'
})
export class UserPermissionsComponent {
  dropdownOptions: { [key: string]: any[] } = {};
  users: any[] = [];
  permission: FormGroup;
  showPermissions = false;
  permissions: PermissionNode[] = [];

  constructor(private credentialService: CredentialService, private fb: FormBuilder, private httpService: HttpURIService, private i18nService: I18NService) {
    this.permission = this.fb.group({
      allocation: [''],
      userCode: [null],
      userRole: [''],
    });

    this.defaultPermissions().subscribe((data: PermissionNode[]) => {
      this.permissions = data;
    });
  }

  ngOnInit(){
    this.getAllUsers();
  }

  defaultPermissions(): Observable<PermissionNode[]> {
    return this.httpService.requestGET<PermissionNode[]>('assets/data/sideMenu.json');
  }

  toggleNode(node: PermissionNode, event: Event): void {
    node.checked = (event.target as HTMLInputElement).checked;
    if (node.children) {
      this.toggleChildren(node.children, node.checked);
    }
    if (node.buttons) {
      this.toggleButtons(node.buttons, node.checked);
    }
    this.updateParentState(node);
  }

  toggleChildren(children: PermissionNode[], isChecked: boolean): void {
    children.forEach(child => {
      child.checked = isChecked;
      if (child.children) {
        this.toggleChildren(child.children, isChecked);
      }
      if (child.buttons) {
        this.toggleButtons(child.buttons, child.checked);
      }
    });
  }

  toggleButtons(buttons: PermissionNode[], isChecked: boolean): void {
    buttons.forEach(button => {
      button.checked = isChecked;
    });
  }

  updateParentState(node: PermissionNode): void {
    const parent = this.findParent(node, this.permissions);
    if (parent) {
      parent.checked = parent.children?.some(child => child.checked) || false;
      this.updateParentState(parent); // Recursively update ancestors
    }
  }

  findParent(target: PermissionNode, nodes: PermissionNode[]): PermissionNode | null {
    for (let node of nodes) {
      if (node.children?.includes(target)) {
        return node;
      }
      if (node.children) {
        const parent = this.findParent(target, node.children);
        if (parent) return parent;
      }
    }
    return null;
  }

  toggleExpand(node: PermissionNode): void {
    node.expanded = !node.expanded;
  }
  populateDropdowns(data: any) {
    data.forEach((control: any) => {
      this.dropdownOptions[control.controlId] = control.options;
    });
  }

  onAllocationChange(event: Event): void {
    this.showPermissions = false;
    const selectedValue = (event.target as HTMLInputElement).value;
    if (selectedValue === "R") {
      this.permission.get('userCode')?.reset();
    }
    else if (selectedValue === "U") {
      this.permission.get('userRole')?.reset();
    }
  }

  getAllUsers() {
    this.httpService.requestGET<any[]>(URIKey.GET_ALL_USER_URI).subscribe((response) => {
      if (!(response instanceof HttpErrorResponse)) {
        this.users = response.map(item => ({
          userName: item.userFullname,
          userId: item.userId,
        }));
      }
    });
  }

  onUserChange() {
    this.showPermissions = true;
    const params = new HttpParams().set('userId', this.permission.get('userCode')?.value);
    this.httpService.requestGET(URIKey.USER_GET_PERMISSIONS, params).subscribe((response: any) => {
      if (!(response instanceof HttpErrorResponse)) {
        if (response.permissions) {
          this.updatePermissions(JSON.parse(response.permissions), this.permissions);
        }
        else {
          this.defaultPermissions().subscribe((data: PermissionNode[]) => {
            this.permissions = data;
          });
        }
      }
    })
  }

  savePermissions() {
    let payload = {
      // porOrgacode: this.credentialService.getPorOrgacode(),
      userId: this.permission.get('userCode')?.value,
      permissions: JSON.stringify(this.permissions)
    }
    this.httpService.requestPUT(URIKey.USER_SAVE_PERMISSION, payload).subscribe((response: any) => {
      if (!(response instanceof HttpErrorResponse)) {
        this.i18nService.success(SuccessMessages.SAVED_SUCCESSFULLY, []);
        this.permission.reset();
        this.permission.get('userCode')?.setValue(null);
        this.showPermissions = false;
        this.collapseAll(this.permissions)
      }
    })
  }

  updatePermissions(savedPermissions: PermissionNode[], existingPermissions: PermissionNode[]): void {
    for (const existingNode of existingPermissions) {
      const savedNode = savedPermissions.find(node => node.name === existingNode.name);

      if (savedNode) {
        // Update state from saved node
        existingNode.checked = savedNode.checked;
        //existingNode.expanded = savedNode.expanded;

        // Recursively update children if they exist
        if (existingNode.children) {
          this.updatePermissions(savedNode.children || [], existingNode.children);
        }
        if (existingNode.buttons) {
          this.updatePermissions(savedNode.buttons || [], existingNode.buttons);
        }
      }
    }
  }

  collapseAll(nodes: PermissionNode[]): void {
    nodes.forEach(node => {
      node.expanded = false;

      if (node.children) {
        this.collapseAll(node.children);
      }

      if (node.buttons) {
        this.collapseAll(node.buttons);
      }
    });
  }

}
