import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { CustomSelectComponent } from '../../../../components/custom-select/custom-select';

export type MonthOption = { value: number; label: string };

export type ParcelamentoCreateModel = {
  anoRef: number | null;
  linha: string;
  cliente: string;
  item: number | null;
  qtParcelas: string;
  parcelaAtual: number | null;
  totalParcelas: number | null;
  valorCheio: string;
  desconto: string;
  valorComDesconto: string;
  competenciaAno: number | null;
  competenciaMes: number | null;
  monthValues: Array<{ competencia: string; valor: string }>;
};

type PreviewRow = {
  competencia: string;
  label: string;
  parcela: number;
  valor: string;
};

@Component({
  selector: 'app-parcelamento-create-modal',
  standalone: true,
  imports: [CommonModule, FormsModule, CustomSelectComponent],
  templateUrl: './parcelamento-create-modal.html',
  styleUrls: ['./parcelamento-create-modal.scss'],
})
export class ParcelamentoCreateModalComponent implements OnChanges {
  @Input() open = false;
  @Input() monthOptions: MonthOption[] = [];
  @Input() model!: ParcelamentoCreateModel;
  @Input() title = 'Novo Parcelamento';
  @Input() submitLabel = 'Salvar';
  @Input() loading = false;
  @Input() errorMessage = '';

  @Output() close = new EventEmitter<void>();
  @Output() save = new EventEmitter<ParcelamentoCreateModel>();

  touched = false;
  previewRows: PreviewRow[] = [];

  ngOnChanges(changes: SimpleChanges): void {
    if (changes['model'] && this.model) {
      this.syncMonthValues();
      return;
    }
    if (changes['open'] && this.model) {
      this.rebuildPreviewRows();
    }
  }

  onValueChange(): void {
    const cheio = this.toNumber(this.model.valorCheio);
    const desconto = this.toNumber(this.model.desconto);
    if (cheio === null) {
      this.model.valorComDesconto = '';
      this.syncMonthValues();
      return;
    }
    const calc = Math.max(0, cheio - (desconto ?? 0));
    this.model.valorComDesconto = this.formatInput(calc);
    this.syncMonthValues();
  }

  onCompetenciaChange(): void {
    this.syncMonthValues();
  }

  onValorComDescontoChange(): void {
    this.syncMonthValues();
  }

  onParcelaChange(): void {
    this.syncQtParcelas();
    this.syncMonthValues();
  }

  onQtParcelasChange(): void {
    const parsed = this.parseQtParcelas(this.model.qtParcelas);
    if (parsed) {
      this.model.parcelaAtual = parsed.atual;
      this.model.totalParcelas = parsed.total;
    }
    this.syncMonthValues();
  }

  get competenciaFinalLabel(): string {
    if (this.model.monthValues?.length) {
      const last = this.model.monthValues[this.model.monthValues.length - 1];
      return this.formatCompetenciaLabel(last.competencia);
    }
    const total = this.model.totalParcelas ?? 0;
    const ano = this.model.competenciaAno ?? 0;
    const mes = this.model.competenciaMes ?? 0;
    if (!total || !ano || !mes) return '-';

    const index = (mes - 1) + (total - 1);
    const finalAno = ano + Math.floor(index / 12);
    const finalMes = (index % 12) + 1;
    return `${String(finalMes).padStart(2, '0')}/${finalAno}`;
  }

  onPreviewValueChange(competencia: string, value: string): void {
    const list = this.model.monthValues ?? [];
    const item = list.find((entry) => entry.competencia === competencia);
    if (item) item.valor = value ?? '';

    const row = this.previewRows.find((entry) => entry.competencia === competencia);
    if (row) row.valor = value ?? '';
  }

  trackByPreview(_: number, row: PreviewRow): string {
    return row.competencia;
  }

  get isValid(): boolean {
    return !!(
      this.model.anoRef &&
      this.model.item &&
      this.model.linha?.trim() &&
      this.model.cliente?.trim() &&
      this.model.totalParcelas &&
      this.model.totalParcelas > 0 &&
      this.model.valorCheio &&
      this.model.competenciaAno &&
      this.model.competenciaMes
    );
  }

  onSave(): void {
    this.touched = true;
    if (!this.isValid) return;
    this.save.emit(this.model);
  }

  private syncQtParcelas(): void {
    const atual = this.model.parcelaAtual;
    const total = this.model.totalParcelas;
    if (atual && total) {
      this.model.qtParcelas = `${atual}/${total}`;
    }
  }

  private syncMonthValues(): void {
    const total = this.model.totalParcelas ?? 0;
    const ano = this.model.competenciaAno ?? 0;
    const mes = this.model.competenciaMes ?? 0;
    if (!total || !ano || !mes) {
      this.model.monthValues = [];
      this.previewRows = [];
      return;
    }

    const existing = new Map<string, string>();
    (this.model.monthValues ?? []).forEach((m) => {
      if (m?.competencia) existing.set(m.competencia, m.valor ?? '');
    });

    const valorTotal = this.toNumber(this.model.valorComDesconto) ?? this.toNumber(this.model.valorCheio);
    const valorParcela = valorTotal !== null ? valorTotal / total : null;
    const defaultValor = valorParcela !== null ? this.formatInput(valorParcela) : '';

    const list: Array<{ competencia: string; valor: string }> = [];
    for (let i = 0; i < total; i++) {
      const index = (mes - 1) + i;
      const y = ano + Math.floor(index / 12);
      const m = (index % 12) + 1;
      const competencia = `${y}-${String(m).padStart(2, '0')}-01`;
      list.push({
        competencia,
        valor: existing.get(competencia) ?? defaultValor,
      });
    }

    this.model.monthValues = list;
    this.rebuildPreviewRows();
  }

  private rebuildPreviewRows(): void {
    const list = this.model?.monthValues ?? [];
    if (!list.length) {
      this.previewRows = [];
      return;
    }

    this.previewRows = list.slice(0, 36).map((item, idx) => ({
      competencia: item.competencia,
      label: this.formatCompetenciaLabel(item.competencia),
      parcela: idx + 1,
      valor: item.valor ?? '',
    }));
  }

  private formatCompetenciaLabel(value: string): string {
    const match = value.match(/^(\d{4})-(\d{2})/);
    if (!match) return value || '-';
    return `${match[2]}/${match[1]}`;
  }

  private parseQtParcelas(raw: string | null | undefined): { atual: number; total: number } | null {
    if (!raw) return null;
    const parts = raw.split('/');
    if (parts.length < 2) return null;
    const atualStr = this.onlyDigits(parts[0]);
    const totalStr = this.onlyDigits(parts[1]);
    if (!atualStr || !totalStr) return null;
    return { atual: Number(atualStr), total: Number(totalStr) };
  }

  private toNumber(value: any): number | null {
    if (value === null || value === undefined || value === '') return null;
    if (typeof value === 'number') return Number.isFinite(value) ? value : null;
    const raw = String(value).trim();
    if (!raw) return null;
    let cleaned = raw.replace(/[^\d,.-]/g, '');
    if (cleaned.includes(',') && cleaned.includes('.')) {
      if (cleaned.lastIndexOf(',') > cleaned.lastIndexOf('.')) {
        cleaned = cleaned.replace(/\./g, '').replace(',', '.');
      } else {
        cleaned = cleaned.replace(/,/g, '');
      }
    } else if (cleaned.includes(',')) {
      cleaned = cleaned.replace(/\./g, '').replace(',', '.');
    } else {
      cleaned = cleaned.replace(/,/g, '');
    }
    const n = Number(cleaned);
    return Number.isNaN(n) ? null : n;
  }

  private onlyDigits(value: string): string {
    let out = '';
    for (const ch of value ?? '') {
      if (ch >= '0' && ch <= '9') out += ch;
    }
    return out;
  }

  private formatInput(value: number): string {
    return new Intl.NumberFormat('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(value);
  }
}
