import { Component, computed, input, output, signal } from '@angular/core';

export interface <%= classify(name) %>Value {
  barcode: string;
  amount: string;
  dueDate: string;
}

const INITIAL_VALUE: <%= classify(name) %>Value = {
  barcode: '',
  amount: '',
  dueDate: '',
};

let nextId = 0;

@Component({
  selector: '<%= selector %>',
  imports: [],
  templateUrl: './<%= dasherize(name) %>.html',
  styleUrl: './<%= dasherize(name) %>.css',
})
export class <%= classify(name) %> {
  protected readonly instanceId = `<%= dasherize(name) %>-${nextId++}`;
  protected readonly submitted = signal(false);
  protected readonly payment = signal<<%= classify(name) %>Value>({ ...INITIAL_VALUE });
  protected readonly statusMessage = signal('');

  readonly title = input('Boleto de pagamento');
  readonly barcodeLabel = input('Código de barras ou linha digitável');
  readonly amountLabel = input('Valor');
  readonly dueDateLabel = input('Vencimento');
  readonly submitLabel = input('Revisar pagamento');
  readonly resetLabel = input('Limpar pagamento');
  readonly barcodeMessage = input('Informe o código de barras ou a linha digitável.');
  readonly amountMessage = input('Informe um valor maior que zero.');
  readonly dueDateMessage = input('Escolha a data de vencimento do pagamento.');
  readonly successMessage = input('O boleto está pronto para revisão.');
  readonly paymentSubmit = output<<%= classify(name) %>Value>();
  readonly paymentReset = output<void>();

  protected readonly titleId = computed(() => `${this.instanceId}-title`);
  protected readonly barcodeId = computed(() => `${this.instanceId}-barcode`);
  protected readonly amountId = computed(() => `${this.instanceId}-amount`);
  protected readonly dueDateId = computed(() => `${this.instanceId}-due-date`);
  protected readonly barcodeDigits = computed(() => this.payment().barcode.replace(/\D/g, ''));
  protected readonly paymentSummary = computed(() => {
    const value = this.payment();
    if (!value.barcode && !value.amount && !value.dueDate) {
      return '';
    }

    return `Boleto terminando em ${this.barcodeDigits().slice(-6) || 'não informado'} no valor de ${value.amount || 'valor não informado'} com vencimento em ${value.dueDate || 'data não informada'}.`;
  });

  protected errorId(field: keyof <%= classify(name) %>Value): string {
    return `${this.instanceId}-${field}-error`;
  }

  protected fieldError(field: keyof <%= classify(name) %>Value): string {
    if (!this.submitted()) {
      return '';
    }

    const value = this.payment()[field].trim();

    if (field === 'barcode') {
      return this.barcodeDigits().length >= 10 ? '' : this.barcodeMessage();
    }

    if (field === 'amount') {
      return Number(value) > 0 ? '' : this.amountMessage();
    }

    return value ? '' : this.dueDateMessage();
  }

  protected describedBy(field: keyof <%= classify(name) %>Value): string | null {
    return this.fieldError(field) ? this.errorId(field) : null;
  }

  protected updateField(field: keyof <%= classify(name) %>Value, event: Event): void {
    const value = (event.target as HTMLInputElement).value;
    this.payment.update((current) => ({ ...current, [field]: value }));
  }

  protected submit(event: SubmitEvent): void {
    event.preventDefault();
    this.submitted.set(true);

    const hasError = (['barcode', 'amount', 'dueDate'] as const).some((field) => this.fieldError(field));
    if (hasError) {
      this.statusMessage.set('Verifique os campos do boleto e tente novamente.');
      return;
    }

    this.statusMessage.set(this.successMessage());
    this.paymentSubmit.emit(this.payment());
  }

  protected reset(): void {
    this.submitted.set(false);
    this.payment.set({ ...INITIAL_VALUE });
    this.statusMessage.set('');
    this.paymentReset.emit();
  }
}
