import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { FormsModule } from '@angular/forms';
import { ZardFormModule } from '@shared/components/form/form.module';
import { ZardInputDirective } from '@shared/components/input/input.directive';
import { ZardCheckboxComponent } from '@shared/components/checkbox/checkbox.component';
import { Permission, Role } from 'src/app/core/interfaces/role';

@Component({
  selector: 'app-role-form',
  standalone: true,
  templateUrl: './role-form.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [
    CommonModule,
    ReactiveFormsModule,
    FormsModule,
    ZardFormModule,
    ZardInputDirective,
    ZardCheckboxComponent,
  ],
})
export class RoleForm {
  @Output() save = new EventEmitter<Role>();
  @Output() cancel = new EventEmitter<void>();

  private _permissions: Permission[] = [];
  @Input() set permissions(list: Permission[]) {
    this._permissions = list ?? [];
    this.buildPermissionControls();
  }
  get permissions(): Permission[] {
    return this._permissions;
  }

  private _value?: Role;
  @Input() set value(v: Role | undefined) {
    this._value = v;
    this.hydrateFromValue(v);
  }
  get value(): Role | undefined {
    return this._value;
  }

  form: FormGroup;
  submitted = false;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      name: ['', Validators.required],
      description: [''],
      permMap: this.fb.group({}),
    });
  }

  private buildPermissionControls() {
    const group = this.form.get('permMap') as FormGroup;
    if (!group) return;
    // Keep existing states where possible
    const current = (group.getRawValue?.() as Record<string, boolean>) || {};
    const selectedNames = new Set(
      (this._value?.permissions ?? []).map((p) => p.name)
    );
    // Rebuild controls for each permission (keyed by its name)
    const newGroup: Record<string, any> = {};
    for (const p of this._permissions) {
      const key = p.name;
      const initial = current[key] ?? selectedNames.has(key);
      newGroup[key] = this.fb.control(!!initial);
    }
    // Replace the group
    this.form.setControl('permMap', this.fb.group(newGroup));
  }

  private hydrateFromValue(v?: Role) {
    this.form.patchValue({ name: v?.name ?? '', description: v?.description ?? '' });
    // Rebuild permission map based on new value and available permissions
    this.buildPermissionControls();
  }

  onSubmit() {
    this.submitted = true;
    if (this.form.invalid || this.selectedPermissionsCount() === 0) {
      this.form.markAllAsTouched();
      return;
    }
    const raw = this.form.getRawValue() as any;
    const permMap: Record<string, boolean> = (this.form.get('permMap') as FormGroup).getRawValue();
    const selectedNames = Object.entries(permMap)
      .filter(([, v]) => !!v)
      .map(([k]) => k);
    const permissions = this._permissions.filter((p) => selectedNames.includes(p.name));
    const payload: Role = {
      id: this.value?.id ?? '',
      name: raw.name,
      description: raw.description,
      permissions,
    };
    this.save.emit(payload);
  }

  selectedPermissionsCount(): number {
    const permMap: Record<string, boolean> = (this.form.get('permMap') as FormGroup).getRawValue();
    return Object.values(permMap).filter(Boolean).length;
  }

  isInvalid(control: string): boolean {
    const ctrl = this.form.get(control);
    return !!(ctrl && ctrl.invalid && (ctrl.touched || this.submitted));
  }

  errorMessage(control: string): string | null {
    const c = this.form.get(control);
    if (!c || !c.errors) return null;
    if (c.errors['required']) return 'Ce champ est obligatoire';
    if (c.errors['minlength']) return `Minimum ${c.errors['minlength'].requiredLength} caractères`;
    return null;
  }
}
