import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { GridModule } from '@progress/kendo-angular-grid';
import { ButtonsModule } from '@progress/kendo-angular-buttons';
import { DropDownsModule } from '@progress/kendo-angular-dropdowns';
import { IndicatorsModule } from '@progress/kendo-angular-indicators';
import { PermissionApiService } from '../../services/permission-api.service';
import { PermissionService } from '../../../../core/services/permission.service';
import {
    ModulePermissionDto,
    PermissionMatrixDto,
    RolePermissionRow,
} from '../../../../core/models/permission.model';
import { PageHeaderActionsDirective } from '../../../../shared/directives/page-header-actions.directive';

@Component({
    selector: 'app-permissions-page',
    standalone: true,
    imports: [
        CommonModule, FormsModule, GridModule, ButtonsModule, DropDownsModule, IndicatorsModule,
        PageHeaderActionsDirective,
    ],
    templateUrl: './permissions-page.component.html',
    styleUrls: ['./permissions-page.component.scss'],
})
export class PermissionsPageComponent implements OnInit {
    matrix: PermissionMatrixDto | null = null;
    roleNames: string[] = [];

    selectedRole: string | null = null;
    selectedDescription: string | null = null;
    isSuperAdminSelected = false;

    /** Editable copy of the selected role's per-module grants. */
    rows: ModulePermissionDto[] = [];

    isLoading = false;
    isSaving = false;
    savedMessage: string | null = null;

    constructor(
        private api: PermissionApiService,
        private permissions: PermissionService
    ) { }

    ngOnInit(): void {
        this.loadMatrix();
    }

    loadMatrix(): void {
        this.isLoading = true;
        this.api.getMatrix().subscribe({
            next: matrix => {
                this.matrix = matrix;
                this.roleNames = matrix.roles.map(role => role.roleName);
                // Preserve the current selection across reloads, else pick the first editable role.
                const keep = this.selectedRole && this.roleNames.includes(this.selectedRole)
                    ? this.selectedRole
                    : matrix.roles.find(role => !role.isSuperAdmin)?.roleName ?? this.roleNames[0] ?? null;
                this.selectRole(keep);
                this.isLoading = false;
            },
            error: () => { this.isLoading = false; },
        });
    }

    selectRole(roleName: string | null): void {
        this.selectedRole = roleName;
        this.savedMessage = null;
        const row = this.findRow(roleName);
        this.selectedDescription = row?.description ?? null;
        this.isSuperAdminSelected = row?.isSuperAdmin ?? false;
        // Clone so edits aren't committed until Save.
        this.rows = (row?.modules ?? []).map(module => ({ ...module }));
    }

    save(): void {
        if (!this.selectedRole || this.isSuperAdminSelected) {
            return;
        }
        this.isSaving = true;
        this.api.updateRole(this.selectedRole, { modules: this.rows }).subscribe({
            next: () => {
                this.isSaving = false;
                this.savedMessage = `Saved permissions for "${this.selectedRole}".`;
                // Refresh the matrix and the current user's own permissions (in case they edited their effect).
                this.permissions.refresh().subscribe();
                this.loadMatrix();
            },
            error: () => { this.isSaving = false; },
        });
    }

    private findRow(roleName: string | null): RolePermissionRow | undefined {
        if (!roleName || !this.matrix) {
            return undefined;
        }
        return this.matrix.roles.find(role => role.roleName === roleName);
    }
}
