import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ReactiveFormsModule, FormBuilder, FormGroup, Validators, FormsModule } from '@angular/forms';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { AuthService } from 'app/core/auth/auth.service';
import { environment } from '@environments/environment';

interface Role {
  id: number;
  name: string;
  description: string;
  permissions: string[];
  created_at: string;
  updated_at: string;
}

interface Permission {
  id: string;
  name: string;
  description: string;
  module: string;
}

@Component({
  selector: 'app-role-management',
  templateUrl: './role-management.component.html',
  styleUrls: ['./role-management.component.scss'],
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule, FormsModule]
})
export class RoleManagementComponent implements OnInit {
  roles: Role[] = [];
  filteredRoles: Role[] = [];
  roleForm: FormGroup;
  isEditing = false;
  currentRoleId: number | null = null;
  searchTerm = '';
  showAddRoleForm = false;
  isLoading = false;
  errorMessage: string | null = null;
  successMessage: string | null = null;
  
  availablePermissions: Permission[] = [];
  modules: string[] = [];
  permissionMap: { [key: string]: Permission } = {};

  private apiUrl = environment.apiUrl;

  constructor(
    private fb: FormBuilder,
    private http: HttpClient,
    private authService: AuthService
  ) {
    this.roleForm = this.fb.group({
      name: ['', [Validators.required, Validators.minLength(3)]],
      description: [''],
      permissions: [[], Validators.required]
    });
  }

  ngOnInit(): void {
    this.loadPermissions();
    this.loadRoles();
  }

  private getHeaders(): HttpHeaders {
    const token = this.authService.accessToken;
    return new HttpHeaders({
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    });
  }

  loadPermissions(): void {
    this.http.get<Permission[]>(`${this.apiUrl}/permissions`, { headers: this.getHeaders() })
      .subscribe({
        next: (permissions) => {
          this.availablePermissions = permissions;
          this.extractModules();
          permissions.forEach(p => {
            this.permissionMap[p.id] = p;
          });
        },
        error: (error) => {
          console.error('Error loading permissions:', error);
          this.showError('Failed to load permissions');
        }
      });
  }

  extractModules(): void {
    this.modules = [...new Set(this.availablePermissions.map(p => p.module))];
  }

  loadRoles(): void {
    this.isLoading = true;
    this.http.get<Role[]>(`${this.apiUrl}/roles`, { headers: this.getHeaders() })
      .subscribe({
        next: (roles) => {
          this.roles = roles;
          this.filteredRoles = [...roles];
          this.isLoading = false;
        },
        error: (error) => {
          console.error('Error loading roles:', error);
          this.showError('Failed to load roles');
          this.isLoading = false;
        }
      });
  }

  onSearch(): void {
    if (!this.searchTerm.trim()) {
      this.filteredRoles = [...this.roles];
      return;
    }
    
    const searchTermLower = this.searchTerm.toLowerCase();
    this.filteredRoles = this.roles.filter(role => 
      role.name.toLowerCase().includes(searchTermLower) || 
      role.description.toLowerCase().includes(searchTermLower)
    );
  }

  onSubmit(): void {
    if (this.roleForm.invalid) {
      return;
    }

    const formValue = this.roleForm.value;
    this.isLoading = true;
    
    if (this.isEditing && this.currentRoleId !== null) {
      // Update existing role
      this.http.put<Role>(
        `${this.apiUrl}/roles/${this.currentRoleId}`,
        formValue,
        { headers: this.getHeaders() }
      ).subscribe({
        next: (updatedRole) => {
          const index = this.roles.findIndex(r => r.id === this.currentRoleId);
          if (index !== -1) {
            this.roles[index] = updatedRole;
          }
          this.filteredRoles = [...this.roles];
          this.showSuccess('Role updated successfully');
          this.resetForm();
          this.showAddRoleForm = false;
          this.isLoading = false;
        },
        error: (error) => {
          console.error('Error updating role:', error);
          this.showError(error.error?.error || 'Failed to update role');
          this.isLoading = false;
        }
      });
    } else {
      // Create new role
      this.http.post<Role>(
        `${this.apiUrl}/roles`,
        formValue,
        { headers: this.getHeaders() }
      ).subscribe({
        next: (newRole) => {
          this.roles.push(newRole);
          this.filteredRoles = [...this.roles];
          this.showSuccess('Role created successfully');
          this.resetForm();
          this.showAddRoleForm = false;
          this.isLoading = false;
        },
        error: (error) => {
          console.error('Error creating role:', error);
          this.showError(error.error?.error || 'Failed to create role');
          this.isLoading = false;
        }
      });
    }
  }

  editRole(role: Role): void {
    this.isEditing = true;
    this.currentRoleId = role.id;
    this.roleForm.patchValue({
      name: role.name,
      description: role.description,
      permissions: role.permissions
    });
    this.showAddRoleForm = true;
  }

  deleteRole(id: number): void {
    if (!confirm('Are you sure you want to delete this role? This action cannot be undone.')) {
      return;
    }

    this.isLoading = true;
    this.http.delete(`${this.apiUrl}/roles/${id}`, { headers: this.getHeaders() })
      .subscribe({
        next: () => {
          this.roles = this.roles.filter(r => r.id !== id);
          this.filteredRoles = this.filteredRoles.filter(r => r.id !== id);
          this.showSuccess('Role deleted successfully');
          this.isLoading = false;
        },
        error: (error) => {
          console.error('Error deleting role:', error);
          this.showError(error.error?.error || 'Failed to delete role');
          this.isLoading = false;
        }
      });
  }

  resetForm(): void {
    this.roleForm.reset({
      name: '',
      description: '',
      permissions: []
    });
    this.isEditing = false;
    this.currentRoleId = null;
  }

  cancelEdit(): void {
    this.resetForm();
    this.showAddRoleForm = false;
  }

  toggleAddRoleForm(): void {
    this.showAddRoleForm = !this.showAddRoleForm;
    if (!this.showAddRoleForm) {
      this.resetForm();
    }
  }

  hasPermission(role: Role, permissionId: string): boolean {
    return role.permissions.includes(permissionId);
  }
  
  toggleAllModulePermissions(module: string, checked: boolean): void {
    const modulePermissionIds = this.availablePermissions
      .filter(p => p.module === module)
      .map(p => p.id);
      
    const currentPermissions = this.roleForm.get('permissions')?.value || [];
    
    if (checked) {
      const newPermissions = [
        ...currentPermissions,
        ...modulePermissionIds.filter(id => !currentPermissions.includes(id))
      ];
      this.roleForm.get('permissions')?.setValue(newPermissions);
    } else {
      const newPermissions = currentPermissions.filter(id => !modulePermissionIds.includes(id));
      this.roleForm.get('permissions')?.setValue(newPermissions);
    }
  }
  
  isModuleFullySelected(module: string): boolean {
    const modulePermissionIds = this.availablePermissions
      .filter(p => p.module === module)
      .map(p => p.id);
    
    const currentPermissions = this.roleForm.get('permissions')?.value || [];
    return modulePermissionIds.every(id => currentPermissions.includes(id));
  }
  
  getPermissionsByModule(module: string): Permission[] {
    return this.availablePermissions.filter(p => p.module === module);
  }
  
  getPermissionById(id: string): Permission | undefined {
    return this.permissionMap[id];
  }

  updatePermissions(permissionId: string, isChecked: boolean): void {
    const permissions = [...(this.roleForm.get('permissions')?.value || [])];
    
    if (isChecked && !permissions.includes(permissionId)) {
      permissions.push(permissionId);
    } else if (!isChecked) {
      const index = permissions.indexOf(permissionId);
      if (index !== -1) {
        permissions.splice(index, 1);
      }
    }
    
    this.roleForm.get('permissions')?.setValue(permissions);
  }

  togglePermission(role: Role, permissionId: string, checked: boolean): void {
    const updatedPermissions = [...role.permissions];
    if (checked) {
      if (!updatedPermissions.includes(permissionId)) {
        updatedPermissions.push(permissionId);
      }
    } else {
      const index = updatedPermissions.indexOf(permissionId);
      if (index !== -1) {
        updatedPermissions.splice(index, 1);
      }
    }
    
    // Update role on backend
    this.http.put<Role>(
      `${this.apiUrl}/roles/${role.id}`,
      { permissions: updatedPermissions },
      { headers: this.getHeaders() }
    ).subscribe({
      next: (updatedRole) => {
        const roleIndex = this.roles.findIndex(r => r.id === role.id);
        if (roleIndex !== -1) {
          this.roles[roleIndex] = updatedRole;
          this.filteredRoles = [...this.roles];
        }
      },
      error: (error) => {
        console.error('Error updating permissions:', error);
        this.showError('Failed to update permissions');
      }
    });
  }

  private showSuccess(message: string): void {
    this.successMessage = message;
    setTimeout(() => this.successMessage = null, 3000);
  }

  private showError(message: string): void {
    this.errorMessage = message;
    setTimeout(() => this.errorMessage = null, 5000);
  }
}