import { Component, OnInit, ElementRef, ViewChild, ChangeDetectorRef, Inject, PLATFORM_ID } from '@angular/core';
import { CommonModule, isPlatformBrowser } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { HttpErrorResponse } from '@angular/common/http';

import { CustomSelectComponent } from '../../components/custom-select/custom-select';
import { HistoricoService, AuditLogDto, AuditChangeType, HistoricoQuery } from '../../services/historico.service';

interface SelectOption {
  value: string;
  label: string;
}

@Component({
  selector: 'app-historico',
  standalone: true,
  imports: [CommonModule, FormsModule, CustomSelectComponent],
  templateUrl: './historico.html',
  styleUrls: ['./historico.scss'],
})
export class Historico implements OnInit {
  @ViewChild('successToast', { static: false }) successToast!: ElementRef;

  logs: AuditLogDto[] = [];
  loading = false;
  error = false;
  errorMsg = '';
  toastMessage = '';

  expandedLogId: string | null = null;

  page = 1;
  pageSize = 10;
  pageSizeOptions = [10, 20, 50, 100];
  total = 0;

  filterPageName = '';
  filterAction = '';
  filterUser = '';
  filterSearch = '';
  dateFrom = '';
  dateTo = '';

  readonly pageOptions: SelectOption[] = [
    { value: '', label: 'Todas as páginas' },
    { value: 'Geral', label: 'Geral' },
    { value: 'Mureg', label: 'Mureg' },
    { value: 'Faturamento', label: 'Faturamento' },
    { value: 'Parcelamentos', label: 'Parcelamentos' },
    { value: 'Dados e Usuários', label: 'Dados PF/PJ' },
    { value: 'Vigência', label: 'Vigência' },
    { value: 'Chips Virgens e Recebidos', label: 'Chips Virgens e Recebidos' },
    { value: 'Troca de número', label: 'Troca de número' },
  ];

  readonly actionOptions: SelectOption[] = [
    { value: '', label: 'Todas as ações' },
    { value: 'CREATE', label: 'Criação' },
    { value: 'UPDATE', label: 'Atualização' },
    { value: 'DELETE', label: 'Exclusão' },
  ];

  private searchTimer: any = null;

  constructor(
    private historicoService: HistoricoService,
    private cdr: ChangeDetectorRef,
    @Inject(PLATFORM_ID) private platformId: object
  ) {}

  ngOnInit(): void {
    this.fetch(1);
  }

  refresh(): void {
    this.fetch(1);
  }

  applyFilters(): void {
    this.page = 1;
    this.fetch();
  }

  clearFilters(): void {
    this.filterPageName = '';
    this.filterAction = '';
    this.filterUser = '';
    this.filterSearch = '';
    this.dateFrom = '';
    this.dateTo = '';
    this.page = 1;
    this.fetch();
  }

  clearSearch(): void {
    this.filterSearch = '';
    this.page = 1;
    this.fetch();
  }

  onSearchChange(): void {
    if (this.searchTimer) clearTimeout(this.searchTimer);
    this.searchTimer = setTimeout(() => {
      this.page = 1;
      this.fetch();
    }, 300);
  }

  onPageSizeChange(): void {
    this.page = 1;
    this.fetch();
  }

  goToPage(p: number): void {
    this.page = Math.max(1, Math.min(this.totalPages, p));
    this.fetch();
  }

  get totalPages(): number {
    return Math.ceil((this.total || 0) / this.pageSize) || 1;
  }

  get pageNumbers(): number[] {
    const total = this.totalPages;
    const current = this.page;
    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: number[] = [];
    for (let i = start; i <= end; i++) pages.push(i);
    return pages;
  }

  get pageStart(): number {
    return this.total === 0 ? 0 : (this.page - 1) * this.pageSize + 1;
  }

  get pageEnd(): number {
    if (this.total === 0) return 0;
    return Math.min(this.page * this.pageSize, this.total);
  }

  toggleDetails(log: AuditLogDto, event?: Event): void {
    if (event) event.stopPropagation();
    this.expandedLogId = this.expandedLogId === log.id ? null : log.id;
  }

  formatDateTime(value?: string | null): string {
    if (!value) return '-';
    const d = new Date(value);
    if (isNaN(d.getTime())) return '-';
    return d.toLocaleString('pt-BR');
  }

  displayUserName(log: AuditLogDto): string {
    const name = (log.userName || '').trim();
    return name ? name : 'SISTEMA';
  }

  displayEntity(log: AuditLogDto): string {
    const label = (log.entityLabel || '').trim();
    if (label) return label;
    return log.entityName || '-';
  }

  formatAction(action?: string | null): string {
    const value = (action || '').toUpperCase();
    if (!value) return '-';
    if (value === 'CREATE') return 'Criação';
    if (value === 'UPDATE') return 'Atualização';
    if (value === 'DELETE') return 'Exclusão';
    return 'Outro';
  }

  actionClass(action?: string | null): string {
    const value = (action || '').toUpperCase();
    if (value === 'CREATE') return 'action-create';
    if (value === 'UPDATE') return 'action-update';
    if (value === 'DELETE') return 'action-delete';
    return 'action-default';
  }

  changeTypeLabel(type?: AuditChangeType | string | null): string {
    if (!type) return 'Alterado';
    if (type === 'added') return 'Adicionado';
    if (type === 'removed') return 'Removido';
    return 'Alterado';
  }

  changeTypeClass(type?: AuditChangeType | string | null): string {
    if (type === 'added') return 'change-added';
    if (type === 'removed') return 'change-removed';
    if (type === 'modified') return 'change-modified';
    return 'change-modified';
  }

  formatChangeValue(value?: string | null): string {
    if (value === undefined || value === null || value === '') return '-';
    return String(value);
  }

  trackByLog(_: number, log: AuditLogDto): string {
    return log.id;
  }

  trackByField(_: number, change: { field: string }): string {
    return change.field;
  }

  private fetch(goToPage?: number): void {
    if (goToPage) this.page = goToPage;
    this.loading = true;
    this.error = false;
    this.errorMsg = '';
    this.expandedLogId = null;

    const query: HistoricoQuery = {
      page: this.page,
      pageSize: this.pageSize,
      pageName: this.filterPageName || undefined,
      action: this.filterAction || undefined,
      user: this.filterUser?.trim() || undefined,
      search: this.filterSearch?.trim() || undefined,
      dateFrom: this.toIsoDate(this.dateFrom, false) || undefined,
      dateTo: this.toIsoDate(this.dateTo, true) || undefined,
    };

    this.historicoService.list(query).subscribe({
      next: (res) => {
        this.logs = res.items || [];
        this.total = res.total || 0;
        this.page = res.page || this.page;
        this.pageSize = res.pageSize || this.pageSize;
        this.loading = false;
      },
      error: (err: HttpErrorResponse) => {
        this.error = true;
        if (err?.status === 403) {
          this.errorMsg = 'Acesso restrito.';
        } else {
          this.errorMsg = 'Erro ao carregar histórico. Tente novamente.';
        }
        this.loading = false;
      },
    });
  }

  private toIsoDate(value: string, endOfDay: boolean): string | null {
    if (!value) return null;
    const time = endOfDay ? '23:59:59' : '00:00:00';
    const date = new Date(`${value}T${time}`);
    if (isNaN(date.getTime())) return null;
    return date.toISOString();
  }

  private async showToast(message: string) {
    if (!isPlatformBrowser(this.platformId)) return;
    this.toastMessage = message;
    this.cdr.detectChanges();
    if (!this.successToast?.nativeElement) return;

    try {
      const bs = await import('bootstrap');
      const toastInstance = bs.Toast.getOrCreateInstance(this.successToast.nativeElement, {
        autohide: true,
        delay: 3000
      });
      toastInstance.show();
    } catch (error) {
      console.error(error);
    }
  }
}
