import {
  Component,
  Input,
  forwardRef,
  OnInit,
  ElementRef,
  ViewChild,
} from "@angular/core";
import {
  ControlValueAccessor,
  NG_VALUE_ACCESSOR,
  FormsModule,
  ReactiveFormsModule,
} from "@angular/forms";
import { CommonModule } from "@angular/common";

@Component({
  selector: "app-currency-input",
  standalone: true,
  templateUrl: "./currency-input.component.html",
  styleUrls: ["./currency-input.component.scss"],
  imports: [CommonModule, FormsModule, ReactiveFormsModule],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CurrencyInputComponent),
      multi: true,
    },
  ],
})
export class CurrencyInputComponent implements ControlValueAccessor, OnInit {
  @Input() field!: {
    key: string;
    label: string;
    placeholder?: string;
    min?: number;
    max?: number;
    disabled?: boolean;
    readOnly?: boolean;
    required?: boolean;
    currency?: string; // Default: 'BRL'
    locale?: string; // Default: 'pt-BR'
  };

  @ViewChild('inputElement') inputElement!: ElementRef<HTMLInputElement>;

  displayValue: string = "";
  internalValue: number = 0; // Valor numérico em centavos para precisão
  disabled = false;
  isFocused = false;

  // Configurações padrão para moeda brasileira
  private currency = 'BRL';
  private locale = 'pt-BR';

  private onChange: any = () => {};
  private onTouched: any = () => {};

  ngOnInit() {
    // Configurar moeda e locale se fornecidos
    if (this.field?.currency) {
      this.currency = this.field.currency;
    }
    if (this.field?.locale) {
      this.locale = this.field.locale;
    }
  }

  // Getter para verificar se há valor
  get hasValue(): boolean {
    return this.displayValue !== "";
  }

  // Métodos do ControlValueAccessor
  writeValue(value: any): void {
    if (value !== null && value !== undefined) {
      // 🎯 CORREÇÃO: Se recebe em reais, converter para centavos para precisão
      this.internalValue = Math.round(Number(value) * 100) || 0;
      this.updateDisplayValue();
    } else {
      this.internalValue = 0;
      this.displayValue = "";
    }
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }

  // Formatação do valor para exibição
  private updateDisplayValue(): void {
    if (this.internalValue === 0) {
      this.displayValue = "";
      return;
    }

    try {
      // 🎯 FORMATAÇÃO ROBUSTA: Forçar locale brasileiro
      let formatted = new Intl.NumberFormat('pt-BR', {
        style: 'currency',
        currency: this.currency,
        minimumFractionDigits: 2,
        maximumFractionDigits: 2,
      }).format(this.internalValue / 100); // Dividir por 100 pois armazenamos em centavos

      // 🔧 CORREÇÃO BROWSER: Garantir símbolo R$ independente do idioma do browser
      if (this.currency === 'BRL') {
        if (formatted.startsWith('B$') || formatted.includes('B$')) {
          formatted = formatted.replace(/B\$/g, 'R$');
        }
        // Garantir que sempre comece com R$ para Real Brasileiro
        if (!formatted.startsWith('R$') && !formatted.includes('R$')) {
          const numericPart = formatted.replace(/[^\d.,]/g, '');
          formatted = `R$ ${numericPart}`;
        }
      }
      
      this.displayValue = formatted;
    } catch (error) {
      console.warn('Erro ao formatar moeda:', error);
      // 🛡️ FALLBACK SEGURO: Garantir formatação brasileira
      const valueInReais = this.internalValue / 100;
      this.displayValue = `R$ ${valueInReais.toLocaleString('pt-BR', {
        minimumFractionDigits: 2,
        maximumFractionDigits: 2
      })}`;
    }
  }

  // Parse do valor digitado para número
  private parseInputValue(value: string): number {
    if (!value) return 0;

    // Remove todos os caracteres não numéricos exceto vírgula e ponto
    let cleanValue = value.replace(/[^\d,.-]/g, '');
    
    // Substitui vírgula por ponto para parsing
    cleanValue = cleanValue.replace(',', '.');
    
    // Se tem múltiplos pontos, considera apenas o último como decimal
    const parts = cleanValue.split('.');
    if (parts.length > 2) {
      cleanValue = parts.slice(0, -1).join('') + '.' + parts[parts.length - 1];
    }

    const parsedValue = parseFloat(cleanValue) || 0;
    
    // Converte para centavos e arredonda para evitar problemas de ponto flutuante
    return Math.round(parsedValue * 100);
  }

  // Eventos do input
  onInput(event: Event): void {
    const target = event.target as HTMLInputElement;
    const inputValue = target.value;

    // Parse do valor
    this.internalValue = this.parseInputValue(inputValue);
    
    // Validações
    if (this.field?.min !== undefined && this.internalValue < this.field.min * 100) {
      this.internalValue = this.field.min * 100;
    }
    if (this.field?.max !== undefined && this.internalValue > this.field.max * 100) {
      this.internalValue = this.field.max * 100;
    }

    // Emitir o valor em reais para o formulário
    this.onChange(this.internalValue / 100);
  }

  onFocus(): void {
    this.isFocused = true;
    
    // Quando foca, mostra apenas o número para facilitar edição
    if (this.internalValue > 0) {
      const numericValue = (this.internalValue / 100).toFixed(2).replace('.', ',');
      this.inputElement.nativeElement.value = numericValue;
    }
  }

  onBlur(): void {
    this.isFocused = false;
    this.onTouched();
    
    // Quando perde o foco, aplica a formatação completa
    this.updateDisplayValue();
    if (this.displayValue) {
      this.inputElement.nativeElement.value = this.displayValue;
    }
  }

  // Validação de teclas permitidas
  onKeyPress(event: KeyboardEvent): void {
    const allowedKeys = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ',', '.', 'Backspace', 'Delete', 'Tab', 'Escape', 'Enter', 'ArrowLeft', 'ArrowRight'];
    
    if (!allowedKeys.includes(event.key)) {
      event.preventDefault();
    }
  }

  // Método para obter o valor formatado (útil para exibição)
  getFormattedValue(): string {
    return this.displayValue;
  }

  // Método para obter o valor numérico (útil para cálculos)
  getNumericValue(): number {
    return this.internalValue / 100;
  }

  // Método para formatar valores de moeda (usado no template)
  formatCurrency(value: number): string {
    try {
      let formatted = new Intl.NumberFormat('pt-BR', {
        style: 'currency',
        currency: this.currency,
        minimumFractionDigits: 2,
        maximumFractionDigits: 2,
      }).format(value);

      // 🔧 CORREÇÃO BROWSER: Garantir símbolo R$ independente do idioma do browser
      if (this.currency === 'BRL') {
        if (formatted.startsWith('B$') || formatted.includes('B$')) {
          formatted = formatted.replace(/B\$/g, 'R$');
        }
        // Garantir que sempre comece com R$ para Real Brasileiro
        if (!formatted.startsWith('R$') && !formatted.includes('R$')) {
          const numericPart = formatted.replace(/[^\d.,]/g, '');
          formatted = `R$ ${numericPart}`;
        }
      }

      return formatted;
    } catch (error) {
      console.warn('Erro ao formatar moeda:', error);
      // 🛡️ FALLBACK SEGURO: Garantir formatação brasileira
      return `R$ ${value.toLocaleString('pt-BR', {
        minimumFractionDigits: 2,
        maximumFractionDigits: 2
      })}`;
    }
  }
} 