import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpErrorResponse } from '@angular/common/http';
import {
  AbstractControl,
  FormBuilder,
  FormGroup,
  ReactiveFormsModule,
  ValidationErrors,
  Validators,
} from '@angular/forms';
import { CustomSelectComponent } from '../../components/custom-select/custom-select';

import {
  SysadminService,
  SystemTenantDto,
  CreateSystemTenantUserResponse,
} from '../../services/sysadmin.service';

@Component({
  selector: 'app-system-provision-user',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule, CustomSelectComponent],
  templateUrl: './system-provision-user.html',
  styleUrls: ['./system-provision-user.scss'],
})
export class SystemProvisionUserPage implements OnInit {
  readonly sourceType = 'MobileLines.Cliente';

  provisionForm: FormGroup;
  tenants: SystemTenantDto[] = [];
  tenantOptions: Array<{ label: string; value: string }> = [];
  tenantsLoading = false;
  tenantsError = '';

  submitting = false;
  submitErrors: string[] = [];
  successMessage = '';
  createdUser: CreateSystemTenantUserResponse | null = null;

  constructor(
    private fb: FormBuilder,
    private sysadminService: SysadminService
  ) {
    this.provisionForm = this.fb.group(
      {
        tenantId: ['', [Validators.required]],
        name: [''],
        email: ['', [Validators.required, Validators.email]],
        password: ['', [Validators.required, Validators.minLength(6)]],
        confirmPassword: ['', [Validators.required, Validators.minLength(6)]],
        roles: this.fb.control<string[]>(['cliente'], [Validators.required]),
      },
      { validators: this.passwordsMatchValidator }
    );
  }

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

  loadTenants(): void {
    if (this.tenantsLoading) return;

    this.tenantsLoading = true;
    this.tenantsError = '';
    this.syncTenantControlAvailability();

    this.sysadminService
      .listTenants({ source: this.sourceType, active: true })
      .subscribe({
        next: (tenants) => {
          this.tenants = (tenants || []).slice().sort((a, b) =>
            (a.nomeOficial || '').localeCompare(b.nomeOficial || '', 'pt-BR', { sensitivity: 'base' })
          );
          this.tenantOptions = this.tenants.map((tenant) => ({
            label: tenant.nomeOficial || tenant.tenantId,
            value: tenant.tenantId,
          }));
          this.tenantsLoading = false;
          this.syncTenantControlAvailability();
        },
        error: (err: HttpErrorResponse) => {
          this.tenantsLoading = false;
          this.tenants = [];
          this.tenantOptions = [];
          this.tenantsError = this.extractErrorMessage(
            err,
            'Não foi possível carregar os clientes. Verifique se a conta possui role sysadmin.'
          );
          this.syncTenantControlAvailability();
        },
      });
  }

  onSubmit(): void {
    if (this.submitting) return;

    this.successMessage = '';
    this.submitErrors = [];
    this.createdUser = null;

    if (this.provisionForm.invalid) {
      this.provisionForm.markAllAsTouched();
      return;
    }

    const tenantId = String(this.provisionForm.get('tenantId')?.value ?? '').trim();
    const email = String(this.provisionForm.get('email')?.value ?? '').trim().toLowerCase();
    const nameRaw = String(this.provisionForm.get('name')?.value ?? '').trim();
    const password = String(this.provisionForm.get('password')?.value ?? '');

    this.submitting = true;
    this.setFormDisabled(true);

    this.sysadminService
      .createTenantUser(tenantId, {
        name: nameRaw,
        email,
        password,
        roles: ['cliente'],
        clientCredentialsOnly: true,
      })
      .subscribe({
        next: (created) => {
          this.submitting = false;
          this.setFormDisabled(false);

          this.createdUser = created;
          const tenant = this.findTenantById(created.tenantId) ?? this.findTenantById(tenantId);
          const tenantName = tenant?.nomeOficial || 'cliente selecionado';
          this.successMessage = `Credencial de acesso criada com sucesso para ${tenantName}.`;

          this.provisionForm.patchValue({
            name: '',
            email: '',
            password: '',
            confirmPassword: '',
            roles: ['cliente'],
          });
          this.provisionForm.markAsPristine();
          this.provisionForm.markAsUntouched();
        },
        error: (err: HttpErrorResponse) => {
          this.submitting = false;
          this.setFormDisabled(false);
          this.submitErrors = this.extractErrors(err);
        },
      });
  }

  trackByTenantId(_: number, tenant: SystemTenantDto): string {
    return tenant.tenantId;
  }

  hasFieldError(field: string, error?: string): boolean {
    const control = this.provisionForm.get(field);
    if (!control) return false;
    if (error) return !!(control.touched && control.hasError(error));
    return !!(control.touched && control.invalid);
  }

  get passwordMismatch(): boolean {
    const confirmTouched = this.provisionForm.get('confirmPassword')?.touched;
    return !!(confirmTouched && this.provisionForm.errors?.['passwordMismatch']);
  }

  private findTenantById(tenantId: string): SystemTenantDto | undefined {
    return this.tenants.find((tenant) => tenant.tenantId === tenantId);
  }

  private setFormDisabled(disabled: boolean): void {
    if (disabled) {
      this.provisionForm.disable({ emitEvent: false });
      return;
    }

    this.provisionForm.enable({ emitEvent: false });
    this.syncTenantControlAvailability();
  }

  private syncTenantControlAvailability(): void {
    const tenantControl = this.provisionForm.get('tenantId');
    if (!tenantControl) return;
    if (this.submitting) return;

    const shouldDisable = this.tenantsLoading || this.tenants.length === 0;
    if (shouldDisable) {
      tenantControl.disable({ emitEvent: false });
      return;
    }

    tenantControl.enable({ emitEvent: false });
  }

  private extractErrors(err: HttpErrorResponse): string[] {
    const apiError = err?.error;

    if (Array.isArray(apiError)) {
      const list = apiError.map((entry) => String(entry ?? '').trim()).filter(Boolean);
      if (list.length) return list;
    }

    if (Array.isArray(apiError?.errors)) {
      const list = apiError.errors
        .map((entry: unknown) => String((entry as { message?: string })?.message ?? entry ?? '').trim())
        .filter(Boolean);
      if (list.length) return list;
    }

    if (typeof apiError?.message === 'string' && apiError.message.trim()) {
      return [apiError.message.trim()];
    }

    if (typeof apiError === 'string' && apiError.trim()) {
      return [apiError.trim()];
    }

    if (err.status === 403) {
      return ['Acesso negado. Este recurso é exclusivo para sysadmin.'];
    }

    return ['Não foi possível criar a credencial para o cliente selecionado.'];
  }

  private extractErrorMessage(err: HttpErrorResponse, fallback: string): string {
    const messages = this.extractErrors(err);
    if (messages.length) return messages[0];
    return fallback;
  }

  private passwordsMatchValidator(group: AbstractControl): ValidationErrors | null {
    const password = group.get('password')?.value;
    const confirm = group.get('confirmPassword')?.value;
    if (!password || !confirm) return null;
    return password === confirm ? null : { passwordMismatch: true };
  }
}
