import { Component, OnInit, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Router } from '@angular/router';
import { Subscription } from 'rxjs';

import { NotificationsService, NotificationDto } from '../../services/notifications.service';
import { VigenciaService } from '../../services/vigencia.service';

@Component({
  selector: 'app-notificacoes',
  standalone: true,
  imports: [CommonModule, FormsModule],
  templateUrl: './notificacoes.html',
  styleUrls: ['./notificacoes.scss'],
})
export class Notificacoes implements OnInit, OnDestroy {
  notifications: NotificationDto[] = [];
  filter: 'todas' | 'vencidas' | 'aVencer' | 'lidas' = 'todas';
  search = '';
  loading = false;
  error = false;
  bulkLoading = false;
  bulkUnreadLoading = false;
  exportLoading = false;
  selectedIds = new Set<string>();
  renewingKey: string | null = null;
  private readonly subs = new Subscription();

  constructor(
    private notificationsService: NotificationsService,
    private router: Router,
    private vigenciaService: VigenciaService
  ) {}

  ngOnInit(): void {
    this.loadNotifications();

    this.subs.add(
      this.notificationsService.events$.subscribe((ev) => {
        if (ev.type === 'read') {
          const ids = new Set(ev.ids);
          this.notifications.forEach((n) => {
            if (ids.has(n.id)) {
              n.lida = true;
              n.lidaEm = ev.readAtIso;
            }
          });
          return;
        }
        if (ev.type === 'readAll') {
          this.notifications.forEach((n) => {
            if (!n.lida) {
              n.lida = true;
              n.lidaEm = ev.readAtIso;
            }
          });
          return;
        }
        if (ev.type === 'unread') {
          const ids = new Set(ev.ids);
          this.notifications.forEach((n) => {
            if (ids.has(n.id)) {
              n.lida = false;
              n.lidaEm = null;
            }
          });
          return;
        }
        if (ev.type === 'unreadAll') {
          this.notifications.forEach((n) => {
            if (n.lida) {
              n.lida = false;
              n.lidaEm = null;
            }
          });
          return;
        }
        if (ev.type === 'reload') {
          this.loadNotifications();
        }
      })
    );
  }

  ngOnDestroy(): void {
    this.subs.unsubscribe();
  }

  markAsRead(notification: NotificationDto) {
    if (notification.lida) return;
    this.notificationsService.markAsRead(notification.id).subscribe({
      next: () => {
        notification.lida = true;
        notification.lidaEm = new Date().toISOString();
      },
    });
  }

  markAsUnread(notification: NotificationDto) {
    if (!notification.lida) return;
    this.notificationsService.markAsUnread(notification.id).subscribe({
      next: () => {
        notification.lida = false;
        notification.lidaEm = null;
      },
    });
  }

  setFilter(value: 'todas' | 'vencidas' | 'aVencer' | 'lidas') {
    this.filter = value;
    this.clearSelection();
  }

  get filteredNotifications() {
    const base = this.getBaseFilteredNotifications();
    const q = (this.search || '').trim().toLowerCase();
    if (!q) return base;
    return base.filter(n => this.buildSearchText(n).includes(q));
  }

  clearSearch() {
    this.search = '';
    this.clearSelection();
  }

  formatDateLabel(date?: string | null): string {
    if (!date) return '-';
    const parsed = this.parseDateOnly(date);
    if (!parsed) return '-';
    return parsed.toLocaleDateString('pt-BR');
  }

  getNotificationTipo(notification: NotificationDto): string {
    if (notification.tipo === 'RenovacaoAutomatica') {
      return 'RenovacaoAutomatica';
    }

    const reference = notification.dtTerminoFidelizacao ?? notification.referenciaData;
    const parsed = this.parseDateOnly(reference);
    if (!parsed) return notification.tipo;

    const today = this.startOfDay(new Date());
    return parsed < today ? 'Vencido' : 'AVencer';
  }

  isVencido(notification: NotificationDto): boolean {
    return this.getNotificationTipo(notification) === 'Vencido';
  }

  isAVencer(notification: NotificationDto): boolean {
    return this.getNotificationTipo(notification) === 'AVencer';
  }

  isAutoRenew(notification: NotificationDto): boolean {
    return this.getNotificationTipo(notification) === 'RenovacaoAutomatica';
  }

  getStatusLabel(notification: NotificationDto): string {
    if (this.isAutoRenew(notification)) return 'Renovação automática';
    return this.isVencido(notification) ? 'Vencido' : 'A vencer';
  }

  goToVigencia(notification: NotificationDto): void {
    const id = (notification.vigenciaLineId ?? '').trim();
    const linha = (notification.linha ?? '').trim();
    if (!id && !linha) return;

    this.router.navigate(['/vigencia'], {
      queryParams: { lineId: id || null, linha: linha || null, open: 'edit' }
    });
  }

  renewFromNotification(notification: NotificationDto): void {
    if (!this.isAVencer(notification)) return;
    const years = 2;
    const lockKey = notification.id;
    if (this.renewingKey === lockKey) return;
    this.renewingKey = lockKey;

    const vigenciaLineId = (notification.vigenciaLineId ?? '').trim();
    if (vigenciaLineId) {
      this.scheduleByVigenciaId(vigenciaLineId);
      return;
    }

    const linha = (notification.linha ?? '').trim();
    if (!linha) {
      this.renewingKey = null;
      return;
    }

    const onlyDigits = linha.replace(/\D/g, '');
    const lookup = onlyDigits || linha;
    this.vigenciaService.getVigencia({
      search: lookup,
      page: 1,
      pageSize: 20,
      sortBy: 'item',
      sortDir: 'asc'
    }).subscribe({
      next: (res) => {
        const rows = res?.items ?? [];
        const found = rows.find(r => (r.linha ?? '').replace(/\D/g, '') === onlyDigits) ?? rows[0];
        const id = (found?.id ?? '').trim();
        if (!id) {
          this.renewingKey = null;
          return;
        }
        this.scheduleByVigenciaId(id);
      },
      error: () => {
        this.renewingKey = null;
      }
    });
  }

  isRenewing(notification: NotificationDto): boolean {
    return this.renewingKey === notification.id;
  }

  private scheduleByVigenciaId(id: string): void {
    const years = 2;
    this.vigenciaService.configureAutoRenew(id, { years }).subscribe({
      next: () => {
        this.renewingKey = null;
        this.loadNotifications();
      },
      error: () => {
        this.renewingKey = null;
      }
    });
  }

  private loadNotifications() {
    this.loading = true;
    this.error = false;
    this.notificationsService.list().subscribe({
      next: (data) => {
        this.notifications = data || [];
        this.loading = false;
      },
      error: () => {
        this.error = true;
        this.loading = false;
      },
    });
  }

  countByType(tipo: 'Vencido' | 'AVencer'): number {
    return this.notifications.filter(n => this.getNotificationTipo(n) === tipo && !n.lida).length;
  }

  markAllAsRead() {
    if (this.filter === 'lidas' || this.bulkLoading) return;
    this.bulkLoading = true;

    const selectedIds = Array.from(this.selectedIds);
    const scopedIds = selectedIds.length
      ? selectedIds
      : (this.filter !== 'todas' ? this.filteredNotifications.map(n => n.id) : []);
    const filterParam = scopedIds.length ? undefined : this.getFilterParam();
    this.notificationsService.markAllAsRead(filterParam, scopedIds.length ? scopedIds : undefined).subscribe({
      next: () => {
        const now = new Date().toISOString();
        this.notifications = this.notifications.map((n) => {
          if (scopedIds.length ? scopedIds.includes(n.id) : this.shouldMarkRead(n)) {
            return { ...n, lida: true, lidaEm: now };
          }
          return n;
        });
        this.clearSelection();
        this.bulkLoading = false;
      },
      error: () => {
        this.bulkLoading = false;
      }
    });
  }

  markAllAsUnread() {
    if (this.filter !== 'lidas' || this.bulkUnreadLoading) return;
    this.bulkUnreadLoading = true;

    const selectedIds = Array.from(this.selectedIds);
    const scopedIds = selectedIds.length
      ? selectedIds
      : this.filteredNotifications.map(n => n.id);

    this.notificationsService.markAllAsUnread(undefined, scopedIds.length ? scopedIds : undefined).subscribe({
      next: () => {
        this.notifications = this.notifications.map((n) => {
          if (scopedIds.length ? scopedIds.includes(n.id) : n.lida) {
            return { ...n, lida: false, lidaEm: null };
          }
          return n;
        });
        this.clearSelection();
        this.bulkUnreadLoading = false;
      },
      error: () => {
        this.bulkUnreadLoading = false;
      }
    });
  }

  exportNotifications() {
    if (this.filter === 'lidas' || this.exportLoading) return;
    this.exportLoading = true;

    const selectedIds = Array.from(this.selectedIds);
    const scopedIds = selectedIds.length
      ? selectedIds
      : (this.filter !== 'todas' ? this.filteredNotifications.map(n => n.id) : []);
    const filterParam = scopedIds.length ? undefined : this.getFilterParam();
    this.notificationsService.export(filterParam, scopedIds.length ? scopedIds : undefined).subscribe({
      next: (res) => {
        const blob = res.body;
        if (!blob) {
          this.exportLoading = false;
          return;
        }

        const filename = this.extractFilename(res.headers.get('content-disposition')) || this.buildDefaultFilename();
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        a.remove();
        URL.revokeObjectURL(url);
        this.clearSelection();
        this.exportLoading = false;
      },
      error: () => {
        this.exportLoading = false;
      }
    });
  }

  isSelected(notification: NotificationDto): boolean {
    return this.selectedIds.has(notification.id);
  }

  toggleSelection(notification: NotificationDto) {
    if (this.selectedIds.has(notification.id)) {
      this.selectedIds.delete(notification.id);
    } else {
      this.selectedIds.add(notification.id);
    }
  }

  get isAllSelected(): boolean {
    const list = this.filteredNotifications;
    return list.length > 0 && list.every(n => this.selectedIds.has(n.id));
  }

  toggleSelectAll() {
    const list = this.filteredNotifications;
    if (this.isAllSelected) {
      this.clearSelection();
      return;
    }
    list.forEach(n => this.selectedIds.add(n.id));
  }

  clearSelection() {
    this.selectedIds.clear();
  }

  private getFilterParam(): string | undefined {
    if (this.filter === 'aVencer') return 'a-vencer';
    if (this.filter === 'vencidas') return 'vencidas';
    if (this.filter === 'todas') return undefined;
    return undefined;
  }

  private shouldMarkRead(n: NotificationDto): boolean {
    if (this.filter === 'todas') return true;
    if (this.filter === 'aVencer') return this.isAVencer(n);
    if (this.filter === 'vencidas') return this.isVencido(n);
    return false;
  }

  private getBaseFilteredNotifications(): NotificationDto[] {
    if (this.filter === 'lidas') {
      return this.notifications.filter(n => n.lida);
    }
    if (this.filter === 'vencidas') {
      return this.notifications.filter(n => !n.lida && this.isVencido(n));
    }
    if (this.filter === 'aVencer') {
      return this.notifications.filter(n => !n.lida && this.isAVencer(n));
    }
    // "todas" aqui representa o inbox: pendentes (não lidas).
    return this.notifications.filter(n => !n.lida);
  }

  private buildSearchText(n: NotificationDto): string {
    const parts: string[] = [];
    const push = (v?: string | null) => {
      const t = (v ?? '').toString().trim();
      if (t) parts.push(t);
    };

    push(n.cliente);
    push(n.conta);
    push(n.linha);
    push(n.usuario);
    push(n.planoContrato);
    push(n.titulo);
    push(n.mensagem);
    push(n.data);
    push(n.referenciaData ?? null);
    push(n.dtEfetivacaoServico ?? null);
    push(n.dtTerminoFidelizacao ?? null);

    const efetivacao = this.formatDateSearch(n.dtEfetivacaoServico);
    const termino = this.formatDateSearch(n.dtTerminoFidelizacao);
    push(efetivacao);
    push(termino);

    return parts.join(' ').toLowerCase();
  }

  private formatDateSearch(raw?: string | null): string {
    if (!raw) return '';
    const parsed = this.parseDateOnly(raw);
    if (!parsed) return '';
    // Ex.: 12/02/2026 (facilita busca por padrão BR).
    return parsed.toLocaleDateString('pt-BR');
  }

  private parseDateOnly(raw?: string | null): Date | null {
    if (!raw) return null;
    const datePart = raw.split('T')[0];
    const parts = datePart.split('-');
    if (parts.length === 3) {
      const year = Number(parts[0]);
      const month = Number(parts[1]);
      const day = Number(parts[2]);
      if (Number.isFinite(year) && Number.isFinite(month) && Number.isFinite(day)) {
        return new Date(year, month - 1, day);
      }
    }

    const fallback = new Date(raw);
    if (Number.isNaN(fallback.getTime())) return null;
    return this.startOfDay(fallback);
  }

  private startOfDay(date: Date): Date {
    return new Date(date.getFullYear(), date.getMonth(), date.getDate());
  }

  private extractFilename(contentDisposition: string | null): string | null {
    if (!contentDisposition) return null;
    const utf8Match = contentDisposition.match(/filename\*=UTF-8''([^;]+)/i);
    if (utf8Match?.[1]) return decodeURIComponent(utf8Match[1]);
    const normalMatch = contentDisposition.match(/filename=\"?([^\";]+)\"?/i);
    return normalMatch?.[1] ?? null;
  }

  private buildDefaultFilename(): string {
    const stamp = new Date().toISOString().replace(/[-:]/g, '').replace('T', '').slice(0, 14);
    return `notificacoes-${stamp}.xlsx`;
  }
}
