import { Component, Inject, PLATFORM_ID, OnInit, OnDestroy } from '@angular/core';
import { CommonModule, isPlatformBrowser } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { ChipsControleService, ChipVirgemListDto, ControleRecebidoListDto, SortDir, UpdateChipVirgemRequest, UpdateControleRecebidoRequest, CreateChipVirgemRequest, CreateControleRecebidoRequest } from '../../services/chips-controle.service';
import { CustomSelectComponent } from '../../components/custom-select/custom-select';
import { AuthService } from '../../services/auth.service';
import { confirmDeletionWithTyping } from '../../utils/destructive-confirmation';

// Interface para o Agrupamento
interface ChipGroup {
  observacao: string;
  total: number;
  items: ChipVirgemListDto[];
}

interface ControleGroup {
  conteudo: string;
  total: number;
  items: ControleRecebidoListDto[];
}

interface ChipVirgemCreateModel {
  id: string;
  item: number | null;
  numeroDoChip: string | null;
  observacoes: string | null;
}

type ChipsSortKey = 'item' | 'numeroDoChip' | 'observacoes';
type ControleSortKey =
  | 'ano' | 'item' | 'notaFiscal' | 'chip' | 'serial' | 'conteudoDaNf' | 'numeroDaLinha'
  | 'valorUnit' | 'valorDaNf' | 'dataDaNf' | 'dataDoRecebimento' | 'quantidade' | 'isResumo';

@Component({
  selector: 'app-chips-controle-recebidos',
  standalone: true,
  imports: [CommonModule, FormsModule, CustomSelectComponent],
  templateUrl: './chips-controle-recebidos.html',
  styleUrls: ['./chips-controle-recebidos.scss']
})
export class ChipsControleRecebidos implements OnInit, OnDestroy {
  activeTab: 'chips' | 'controle' = 'chips';

  // --- Chips ---
  chipsRows: ChipVirgemListDto[] = [];
  chipsGroups: ChipGroup[] = [];
  pagedChipsGroups: ChipGroup[] = [];
  expandedGroupObservacao: string | null = null;

  chipsLoading = false;
  chipsSearch = '';
  chipsPage = 1;
  chipsPageSize = 10;
  chipsTotal = 0;
  chipsSortBy: ChipsSortKey = 'item';
  chipsSortDir: SortDir = 'asc';
  private chipsSearchTimer: any = null;

  // --- Controle ---
  controleRows: ControleRecebidoListDto[] = [];
  controleGroups: ControleGroup[] = [];
  pagedControleGroups: ControleGroup[] = [];
  expandedControleConteudo: string | null = null;
  controleLoading = false;
  controleSearch = '';
  controlePage = 1;
  controlePageSize = 10;
  controleTotal = 0;
  controleSortBy: ControleSortKey = 'ano';
  controleSortDir: SortDir = 'desc';
  controleAno: number | '' = '';
  controleResumo: '' | 'true' | 'false' = '';
  private controleSearchTimer: any = null;

  // --- Opções ---
  pageSizeOptions = [10, 20, 50, 100];
  anoOptions = [
    { label: 'Todos', value: '' },
    { label: '2022', value: 2022 },
    { label: '2023', value: 2023 },
    { label: '2024', value: 2024 },
    { label: '2025', value: 2025 }
  ];

  toastOpen = false;
  toastMessage = '';
  toastType: 'success' | 'danger' = 'success';
  private toastTimer: any = null;

  chipDetailOpen = false;
  chipDetailLoading = false;
  chipDetailData: ChipVirgemListDto | null = null;
  chipCreateOpen = false;
  chipCreateSaving = false;
  chipCreateModel: ChipVirgemCreateModel | null = null;
  chipEditOpen = false;
  chipEditSaving = false;
  chipEditModel: ChipVirgemListDto | null = null;
  chipEditingId: string | null = null;
  chipDeleteOpen = false;
  chipDeleteTarget: ChipVirgemListDto | null = null;

  controleDetailOpen = false;
  controleDetailLoading = false;
  controleDetailData: ControleRecebidoListDto | null = null;
  controleCreateOpen = false;
  controleCreateSaving = false;
  controleCreateModel: ControleRecebidoListDto | null = null;
  controleCreateDataNf = '';
  controleCreateRecebimento = '';
  controleEditOpen = false;
  controleEditSaving = false;
  controleEditModel: ControleRecebidoListDto | null = null;
  controleEditDataNf = '';
  controleEditRecebimento = '';
  controleEditingId: string | null = null;
  controleDeleteOpen = false;
  controleDeleteTarget: ControleRecebidoListDto | null = null;

  isSysAdmin = false;

  constructor(
    @Inject(PLATFORM_ID) private platformId: object,
    private service: ChipsControleService,
    private http: HttpClient,
    private authService: AuthService
  ) {}

  ngOnInit(): void {
    if (!isPlatformBrowser(this.platformId)) return;
    this.isSysAdmin = this.authService.hasRole('sysadmin');
    this.fetchChips();
    this.fetchControle();
  }

  ngOnDestroy(): void {
    if (this.chipsSearchTimer) clearTimeout(this.chipsSearchTimer);
    if (this.controleSearchTimer) clearTimeout(this.controleSearchTimer);
    if (this.toastTimer) clearTimeout(this.toastTimer);
  }

  setTab(tab: 'chips' | 'controle') {
    this.activeTab = tab;

    if (tab === 'chips') {
      this.expandedGroupObservacao = null;
      this.applyChipsPagination();
      this.closeControleDetail();
    } else {
      this.expandedControleConteudo = null;
      this.applyControlePagination();
      this.closeChipDetail();
    }
  }

  // =====================
  // Chips Virgens
  // =====================
  fetchChips() {
    this.chipsLoading = true;

    this.service.getChipsVirgens({
      search: this.chipsSearch,
      page: 1,
      pageSize: 5000,
      sortBy: this.chipsSortBy,
      sortDir: this.chipsSortDir
    }).subscribe({
      next: (res) => {
        const items = (res as any)?.items ?? [];
        this.chipsRows = items.map((x: any, idx: number) => this.normalizeChip(x, idx));
        this.buildChipsGroups();
        this.chipsTotal = this.chipsGroups.length;
        this.applyChipsPagination();
        this.chipsLoading = false;
      },
      error: () => {
        this.chipsLoading = false;
        this.showToast('Erro ao carregar Chips Virgens.', 'danger');
      }
    });
  }

  private buildChipsGroups() {
    const groupsMap = new Map<string, ChipVirgemListDto[]>();

    this.chipsRows.forEach(row => {
      const key = row.observacoes && row.observacoes.trim() !== ''
        ? row.observacoes.trim()
        : '(Sem Observações)';

      if (!groupsMap.has(key)) groupsMap.set(key, []);
      groupsMap.get(key)?.push(row);
    });

    this.chipsGroups = [];
    groupsMap.forEach((items, key) => {
      this.chipsGroups.push({ observacao: key, total: items.length, items });
    });

    this.chipsGroups.sort((a, b) => a.observacao.localeCompare(b.observacao));
    this.expandedGroupObservacao = null;
  }

  private applyChipsPagination() {
    const start = (this.chipsPage - 1) * this.chipsPageSize;
    const end = start + this.chipsPageSize;
    this.pagedChipsGroups = this.chipsGroups.slice(start, end);

    if (this.expandedGroupObservacao && !this.pagedChipsGroups.some(g => g.observacao === this.expandedGroupObservacao)) {
      this.expandedGroupObservacao = null;
    }
  }

  toggleGroup(obs: string) {
    this.expandedGroupObservacao = this.expandedGroupObservacao === obs ? null : obs;
  }

  openChipDetail(row: ChipVirgemListDto) {
    if (!row?.id) return;
    this.chipDetailOpen = true;
    this.chipDetailLoading = true;
    this.chipDetailData = null;

    this.service.getChipVirgemById(row.id).subscribe({
      next: (data) => {
        this.chipDetailData = data ?? row;
        this.chipDetailLoading = false;
      },
      error: () => {
        this.chipDetailLoading = false;
        this.chipDetailData = row;
      }
    });
  }

  openChipCreate() {
    if (!this.isSysAdmin) return;
    this.chipCreateModel = {
      id: '',
      item: null,
      numeroDoChip: '',
      observacoes: ''
    };
    this.chipCreateOpen = true;
    this.chipCreateSaving = false;
  }

  closeChipCreate() {
    this.chipCreateOpen = false;
    this.chipCreateSaving = false;
    this.chipCreateModel = null;
  }

  saveChipCreate() {
    if (!this.chipCreateModel) return;
    this.chipCreateSaving = true;

    const payload: CreateChipVirgemRequest = {
      item: this.toNullableNumber(this.chipCreateModel.item),
      numeroDoChip: this.chipCreateModel.numeroDoChip,
      observacoes: this.chipCreateModel.observacoes
    };

    this.service.createChipVirgem(payload).subscribe({
      next: () => {
        this.chipCreateSaving = false;
        this.closeChipCreate();
        this.fetchChips();
        this.showToast('Chip criado com sucesso!', 'success');
      },
      error: () => {
        this.chipCreateSaving = false;
        this.showToast('Erro ao criar chip.', 'danger');
      }
    });
  }

  openChipEdit(row: ChipVirgemListDto) {
    if (!this.isSysAdmin) return;
    this.service.getChipVirgemById(row.id).subscribe({
      next: (data) => {
        this.chipEditingId = data.id;
        this.chipEditModel = { ...data };
        this.chipEditOpen = true;
      },
      error: () => this.showToast('Erro ao abrir edição.', 'danger')
    });
  }

  closeChipEdit() {
    this.chipEditOpen = false;
    this.chipEditSaving = false;
    this.chipEditModel = null;
    this.chipEditingId = null;
  }

  saveChipEdit() {
    if (!this.chipEditModel || !this.chipEditingId) return;
    this.chipEditSaving = true;
    const payload: UpdateChipVirgemRequest = {
      item: this.toNullableNumber(this.chipEditModel.item),
      numeroDoChip: this.chipEditModel.numeroDoChip,
      observacoes: this.chipEditModel.observacoes
    };
    this.service.updateChipVirgem(this.chipEditingId, payload).subscribe({
      next: () => {
        this.chipEditSaving = false;
        this.closeChipEdit();
        this.fetchChips();
        this.showToast('Chip atualizado!', 'success');
      },
      error: () => {
        this.chipEditSaving = false;
        this.showToast('Erro ao salvar.', 'danger');
      }
    });
  }

  openChipDelete(row: ChipVirgemListDto) {
    if (!this.isSysAdmin) return;
    this.chipDeleteTarget = row;
    this.chipDeleteOpen = true;
  }

  cancelChipDelete() {
    this.chipDeleteOpen = false;
    this.chipDeleteTarget = null;
  }

  async confirmChipDelete() {
    if (!this.chipDeleteTarget) return;
    if (!(await confirmDeletionWithTyping('este chip virgem'))) return;
    const id = this.chipDeleteTarget.id;
    this.service.removeChipVirgem(id).subscribe({
      next: () => {
        this.chipDeleteOpen = false;
        this.chipDeleteTarget = null;
        this.fetchChips();
        this.showToast('Chip removido.', 'success');
      },
      error: () => {
        this.chipDeleteOpen = false;
        this.chipDeleteTarget = null;
        this.showToast('Erro ao remover.', 'danger');
      }
    });
  }

  closeChipDetail() {
    this.chipDetailOpen = false;
    this.chipDetailLoading = false;
    this.chipDetailData = null;
  }

  onChipsSearch() {
    if (this.chipsSearchTimer) clearTimeout(this.chipsSearchTimer);
    this.chipsSearchTimer = setTimeout(() => {
      this.chipsPage = 1;
      this.fetchChips();
    }, 300);
  }

  clearChipsSearch() {
    this.chipsSearch = '';
    this.chipsPage = 1;
    this.fetchChips();
  }

  onChipsPageSizeChange() {
    this.chipsPage = 1;
    this.applyChipsPagination();
  }

  // =====================
  // Controle Recebidos
  // =====================
  fetchControle() {
    this.controleLoading = true;

    this.service.getControleRecebidos({
      search: this.controleSearch,
      page: 1,
      pageSize: 5000,
      sortBy: this.controleSortBy,
      sortDir: this.controleSortDir,
      ano: this.controleAno,
      isResumo: this.controleResumo
    }).subscribe({
      next: (res) => {
        const items = (res as any)?.items ?? [];
        this.controleRows = items.map((x: any, idx: number) => this.normalizeControle(x, idx));
        this.buildControleGroups();
        this.controleTotal = this.controleGroups.length;
        this.applyControlePagination();
        this.controleLoading = false;
      },
      error: () => {
        this.controleLoading = false;
        this.showToast('Erro ao carregar Controle.', 'danger');
      }
    });
  }

  onControleSearch() {
    if (this.controleSearchTimer) clearTimeout(this.controleSearchTimer);
    this.controleSearchTimer = setTimeout(() => {
      this.controlePage = 1;
      this.fetchControle();
    }, 300);
  }

  clearControleSearch() {
    this.controleSearch = '';
    this.controlePage = 1;
    this.fetchControle();
  }

  setControleSort(key: ControleSortKey) {
    if (this.controleSortBy === key) {
      this.controleSortDir = this.controleSortDir === 'asc' ? 'desc' : 'asc';
    } else {
      this.controleSortBy = key;
      this.controleSortDir = 'asc';
    }
    this.controlePage = 1;
    this.fetchControle();
  }

  onControlePageSizeChange() {
    this.controlePage = 1;
    this.applyControlePagination();
  }

  onControleAnoChange() {
    this.controlePage = 1;
    this.fetchControle();
  }

  setControleResumo(val: '' | 'true' | 'false') {
    this.controleResumo = val;
    this.controlePage = 1;
    this.fetchControle();
  }

  private buildControleGroups() {
    const groupsMap = new Map<string, ControleRecebidoListDto[]>();

    this.controleRows.forEach(row => {
      const key = row.conteudoDaNf && row.conteudoDaNf.trim() !== ''
        ? row.conteudoDaNf.trim()
        : '(Sem Conteúdo)';

      if (!groupsMap.has(key)) groupsMap.set(key, []);
      groupsMap.get(key)?.push(row);
    });

    this.controleGroups = [];
    groupsMap.forEach((items, key) => {
      this.controleGroups.push({ conteudo: key, total: items.length, items });
    });

    this.controleGroups.sort((a, b) => a.conteudo.localeCompare(b.conteudo));
    this.expandedControleConteudo = null;
  }

  private applyControlePagination() {
    const start = (this.controlePage - 1) * this.controlePageSize;
    const end = start + this.controlePageSize;
    this.pagedControleGroups = this.controleGroups.slice(start, end);

    if (this.expandedControleConteudo && !this.pagedControleGroups.some(g => g.conteudo === this.expandedControleConteudo)) {
      this.expandedControleConteudo = null;
    }
  }

  toggleControleGroup(conteudo: string) {
    this.expandedControleConteudo = this.expandedControleConteudo === conteudo ? null : conteudo;
  }

  openControleDetail(row: ControleRecebidoListDto) {
    if (!row?.id) return;
    this.controleDetailOpen = true;
    this.controleDetailLoading = true;
    this.controleDetailData = null;

    this.service.getControleRecebidoById(row.id).subscribe({
      next: (data) => {
        this.controleDetailData = data ?? row;
        this.controleDetailLoading = false;
      },
      error: () => {
        this.controleDetailLoading = false;
        this.controleDetailData = row;
      }
    });
  }

  openControleCreate() {
    if (!this.isSysAdmin) return;
    this.controleCreateModel = {
      id: '',
      ano: new Date().getFullYear(),
      item: null,
      notaFiscal: '',
      chip: '',
      serial: '',
      conteudoDaNf: '',
      numeroDaLinha: '',
      valorUnit: null,
      valorDaNf: null,
      dataDaNf: null,
      dataDoRecebimento: null,
      quantidade: null,
      isResumo: false
    } as ControleRecebidoListDto;
    this.controleCreateDataNf = '';
    this.controleCreateRecebimento = '';
    this.controleCreateOpen = true;
    this.controleCreateSaving = false;
  }

  closeControleCreate() {
    this.controleCreateOpen = false;
    this.controleCreateSaving = false;
    this.controleCreateModel = null;
    this.controleCreateDataNf = '';
    this.controleCreateRecebimento = '';
  }

  onControleCreateValueChange() {
    if (!this.controleCreateModel) return;
    this.recalculateControleTotals(this.controleCreateModel);
  }

  onControleEditValueChange() {
    if (!this.controleEditModel) return;
    this.recalculateControleTotals(this.controleEditModel);
  }

  onControleCreateDateChange() {
    if (!this.controleCreateModel) return;
    if (!this.controleCreateModel.ano && this.controleCreateDataNf) {
      const year = new Date(this.controleCreateDataNf).getFullYear();
      if (Number.isFinite(year)) this.controleCreateModel.ano = year;
    }
  }

  onControleEditDateChange() {
    if (!this.controleEditModel) return;
    if (!this.controleEditModel.ano && this.controleEditDataNf) {
      const year = new Date(this.controleEditDataNf).getFullYear();
      if (Number.isFinite(year)) this.controleEditModel.ano = year;
    }
  }

  private recalculateControleTotals(model: ControleRecebidoListDto) {
    const quantidade = this.toNullableNumber(model.quantidade);
    const valorUnit = this.toNullableNumber(model.valorUnit);
    const valorDaNf = this.toNullableNumber(model.valorDaNf);

    if (quantidade != null && valorUnit != null && (valorDaNf == null || valorDaNf === 0)) {
      model.valorDaNf = Number((valorUnit * quantidade).toFixed(2));
    } else if (quantidade != null && valorDaNf != null && (valorUnit == null || valorUnit === 0)) {
      model.valorUnit = Number((valorDaNf / quantidade).toFixed(2));
    }
  }

  saveControleCreate() {
    if (!this.controleCreateModel) return;
    this.recalculateControleTotals(this.controleCreateModel);
    this.controleCreateSaving = true;

    const payload: CreateControleRecebidoRequest = {
      ano: this.toNullableNumber(this.controleCreateModel.ano),
      item: this.toNullableNumber(this.controleCreateModel.item),
      notaFiscal: this.controleCreateModel.notaFiscal,
      chip: this.controleCreateModel.chip,
      serial: this.controleCreateModel.serial,
      conteudoDaNf: this.controleCreateModel.conteudoDaNf,
      numeroDaLinha: this.controleCreateModel.numeroDaLinha,
      valorUnit: this.toNullableNumber(this.controleCreateModel.valorUnit),
      valorDaNf: this.toNullableNumber(this.controleCreateModel.valorDaNf),
      dataDaNf: this.dateInputToIso(this.controleCreateDataNf),
      dataDoRecebimento: this.dateInputToIso(this.controleCreateRecebimento),
      quantidade: this.toNullableNumber(this.controleCreateModel.quantidade),
      isResumo: this.controleCreateModel.isResumo ?? false
    };

    this.service.createControleRecebido(payload).subscribe({
      next: () => {
        this.controleCreateSaving = false;
        this.closeControleCreate();
        this.fetchControle();
        this.showToast('Recebimento criado com sucesso!', 'success');
      },
      error: () => {
        this.controleCreateSaving = false;
        this.showToast('Erro ao criar recebimento.', 'danger');
      }
    });
  }

  openControleEdit(row: ControleRecebidoListDto) {
    if (!this.isSysAdmin) return;
    this.service.getControleRecebidoById(row.id).subscribe({
      next: (data) => {
        this.controleEditingId = data.id;
        this.controleEditModel = { ...data };
        this.controleEditDataNf = this.toDateInput(data.dataDaNf);
        this.controleEditRecebimento = this.toDateInput(data.dataDoRecebimento);
        this.controleEditOpen = true;
      },
      error: () => this.showToast('Erro ao abrir edição.', 'danger')
    });
  }

  closeControleEdit() {
    this.controleEditOpen = false;
    this.controleEditSaving = false;
    this.controleEditModel = null;
    this.controleEditDataNf = '';
    this.controleEditRecebimento = '';
    this.controleEditingId = null;
  }

  saveControleEdit() {
    if (!this.controleEditModel || !this.controleEditingId) return;
    this.recalculateControleTotals(this.controleEditModel);
    this.controleEditSaving = true;
    const payload: UpdateControleRecebidoRequest = {
      ano: this.toNullableNumber(this.controleEditModel.ano),
      item: this.toNullableNumber(this.controleEditModel.item),
      notaFiscal: this.controleEditModel.notaFiscal,
      chip: this.controleEditModel.chip,
      serial: this.controleEditModel.serial,
      conteudoDaNf: this.controleEditModel.conteudoDaNf,
      numeroDaLinha: this.controleEditModel.numeroDaLinha,
      valorUnit: this.toNullableNumber(this.controleEditModel.valorUnit),
      valorDaNf: this.toNullableNumber(this.controleEditModel.valorDaNf),
      dataDaNf: this.dateInputToIso(this.controleEditDataNf),
      dataDoRecebimento: this.dateInputToIso(this.controleEditRecebimento),
      quantidade: this.toNullableNumber(this.controleEditModel.quantidade),
      isResumo: this.controleEditModel.isResumo ?? false
    };
    this.service.updateControleRecebido(this.controleEditingId, payload).subscribe({
      next: () => {
        this.controleEditSaving = false;
        this.closeControleEdit();
        this.fetchControle();
        this.showToast('Registro atualizado!', 'success');
      },
      error: () => {
        this.controleEditSaving = false;
        this.showToast('Erro ao salvar.', 'danger');
      }
    });
  }

  openControleDelete(row: ControleRecebidoListDto) {
    if (!this.isSysAdmin) return;
    this.controleDeleteTarget = row;
    this.controleDeleteOpen = true;
  }

  cancelControleDelete() {
    this.controleDeleteOpen = false;
    this.controleDeleteTarget = null;
  }

  async confirmControleDelete() {
    if (!this.controleDeleteTarget) return;
    if (!(await confirmDeletionWithTyping('este registro de controle recebido'))) return;
    const id = this.controleDeleteTarget.id;
    this.service.removeControleRecebido(id).subscribe({
      next: () => {
        this.controleDeleteOpen = false;
        this.controleDeleteTarget = null;
        this.fetchControle();
        this.showToast('Registro removido.', 'success');
      },
      error: () => {
        this.controleDeleteOpen = false;
        this.controleDeleteTarget = null;
        this.showToast('Erro ao remover.', 'danger');
      }
    });
  }

  private toDateInput(value: string | null): string {
    if (!value) return '';
    const d = new Date(value);
    if (isNaN(d.getTime())) return '';
    return d.toISOString().slice(0, 10);
  }

  private dateInputToIso(value: string): string | null {
    if (!value) return null;
    const d = new Date(`${value}T00:00:00`);
    if (isNaN(d.getTime())) return null;
    return d.toISOString();
  }

  private toNullableNumber(value: any): number | null {
    if (value === undefined || value === null || value === '') return null;
    const n = Number(value);
    return Number.isNaN(n) ? null : n;
  }

  closeControleDetail() {
    this.controleDetailOpen = false;
    this.controleDetailLoading = false;
    this.controleDetailData = null;
  }

  // =====================
  // Paginação e Helpers
  // =====================
  get activePage() { return this.activeTab === 'chips' ? this.chipsPage : this.controlePage; }
  get activeTotal() { return this.activeTab === 'chips' ? this.chipsTotal : this.controleTotal; }
  get activePageSize() { return this.activeTab === 'chips' ? this.chipsPageSize : this.controlePageSize; }
  get activeTotalPages() { return Math.max(1, Math.ceil((this.activeTotal || 0) / (this.activePageSize || 10))); }

  get activePageStart() { return this.activeTotal === 0 ? 0 : (this.activePage - 1) * this.activePageSize + 1; }
  get activePageEnd() { return this.activeTotal === 0 ? 0 : Math.min(this.activePage * this.activePageSize, this.activeTotal); }

  get activeLoading() { return this.activeTab === 'chips' ? this.chipsLoading : this.controleLoading; } // ✅ novo

  get activePageNumbers() {
    const total = this.activeTotalPages;
    const current = this.activePage;
    const max = 5;
    let start = Math.max(1, current - 2);
    let end = Math.min(total, start + (max - 1));
    start = Math.max(1, end - (max - 1));
    const pages = [];
    for (let i = start; i <= end; i++) pages.push(i);
    return pages;
  }

  goToPage(p: number) {
    const target = Math.max(1, Math.min(this.activeTotalPages, p));

    if (this.activeTab === 'chips') {
      this.chipsPage = target;
      this.applyChipsPagination();
    } else {
      this.controlePage = target;
      this.applyControlePagination();
    }
  }

  normalizeChip(x: any, idx: number): ChipVirgemListDto {
    return {
      id: String(x.id || idx),
      item: Number(x.item || 0),
      numeroDoChip: x.numeroDoChip || x.NumeroDoChip,
      observacoes: x.observacoes || x.Observacoes
    };
  }

  normalizeControle(x: any, idx: number): ControleRecebidoListDto {
    return {
      id: String(x.id || idx),
      ano: x.ano,
      item: x.item,
      notaFiscal: x.notaFiscal,
      chip: x.chip,
      serial: x.serial,
      conteudoDaNf: x.conteudoDaNf,
      numeroDaLinha: x.numeroDaLinha,
      valorUnit: x.valorUnit,
      valorDaNf: x.valorDaNf,
      dataDaNf: x.dataDaNf,
      dataDoRecebimento: x.dataDoRecebimento,
      quantidade: x.quantidade,
      isResumo: x.isResumo
    };
  }

  display(val: any) { return val ? String(val) : '-'; }
  formatMoney(val: any) {
    if (!val) return '-';
    return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(val);
  }
  formatDate(val: any) { if (!val) return '-'; return new Date(val).toLocaleDateString('pt-BR'); }
  isResumo(r: any) { return !!r.isResumo; }
  getResumoItems(items: ControleRecebidoListDto[]) { return (items || []).filter(r => this.isResumo(r)); }
  getDetalheItems(items: ControleRecebidoListDto[]) { return (items || []).filter(r => !this.isResumo(r)); }
  trackById(idx: number, item: any) { return item.id; }

  showToast(msg: string, type: 'success' | 'danger') {
    this.toastMessage = msg;
    this.toastType = type;
    this.toastOpen = true;
    setTimeout(() => this.toastOpen = false, 3000);
  }
}
