import { Injectable } from '@angular/core';
import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http';
import { Observable, Subject, tap } from 'rxjs';

import { environment } from '../../environments/environment';

export type NotificationTipo = 'AVencer' | 'Vencido' | 'RenovacaoAutomatica' | string;

export type NotificationDto = {
  id: string;
  tipo: NotificationTipo;
  titulo: string;
  mensagem: string;
  data: string;
  referenciaData?: string | null;
  diasParaVencer?: number | null;
  lida: boolean;
  lidaEm?: string | null;
  vigenciaLineId?: string | null;
  cliente?: string | null;
  linha?: string | null;
  usuario?: string | null;
  conta?: string | null;
  planoContrato?: string | null;
  dtEfetivacaoServico?: string | null;
  dtTerminoFidelizacao?: string | null;
};

export type NotificationsEvent =
  | { type: 'read'; ids: string[]; readAtIso: string }
  | { type: 'unread'; ids: string[] }
  | { type: 'readAll'; readAtIso: string }
  | { type: 'unreadAll' }
  | { type: 'reload' };

@Injectable({ providedIn: 'root' })
export class NotificationsService {
  private readonly baseApi: string;
  private readonly eventsSubject = new Subject<NotificationsEvent>();
  readonly events$ = this.eventsSubject.asObservable();

  constructor(private http: HttpClient) {
    const raw = (environment.apiUrl || '').replace(/\/+$/, '');
    this.baseApi = raw.toLowerCase().endsWith('/api') ? raw : `${raw}/api`;
  }

  list(): Observable<NotificationDto[]> {
    return this.http.get<NotificationDto[]>(`${this.baseApi}/notifications`);
  }

  markAsRead(id: string): Observable<void> {
    const readAtIso = new Date().toISOString();
    return this.http.patch<void>(`${this.baseApi}/notifications/${id}/read`, {}).pipe(
      tap(() => this.eventsSubject.next({ type: 'read', ids: [id], readAtIso }))
    );
  }

  markAsUnread(id: string): Observable<void> {
    return this.http.patch<void>(`${this.baseApi}/notifications/${id}/unread`, {}).pipe(
      tap(() => this.eventsSubject.next({ type: 'unread', ids: [id] }))
    );
  }

  markAllAsRead(filter?: string, notificationIds?: string[]): Observable<void> {
    let params = new HttpParams();
    if (filter) params = params.set('filter', filter);
    const body = notificationIds && notificationIds.length ? { notificationIds } : {};
    const readAtIso = new Date().toISOString();
    return this.http.patch<void>(`${this.baseApi}/notifications/read-all`, body, { params }).pipe(
      tap(() => {
        if (notificationIds && notificationIds.length) {
          this.eventsSubject.next({ type: 'read', ids: notificationIds, readAtIso });
          return;
        }
        // Se não sabemos o escopo (sem IDs), preferimos sinalizar que "todas" foram lidas.
        // Para casos futuros de filtros sem IDs, o consumer pode optar por recarregar.
        this.eventsSubject.next(filter ? { type: 'reload' } : { type: 'readAll', readAtIso });
      })
    );
  }

  markAllAsUnread(filter?: string, notificationIds?: string[]): Observable<void> {
    let params = new HttpParams();
    if (filter) params = params.set('filter', filter);
    const body = notificationIds && notificationIds.length ? { notificationIds } : {};
    return this.http.patch<void>(`${this.baseApi}/notifications/unread-all`, body, { params }).pipe(
      tap(() => {
        if (notificationIds && notificationIds.length) {
          this.eventsSubject.next({ type: 'unread', ids: notificationIds });
          return;
        }
        this.eventsSubject.next(filter ? { type: 'reload' } : { type: 'unreadAll' });
      })
    );
  }

  export(filter?: string, notificationIds?: string[]): Observable<HttpResponse<Blob>> {
    let params = new HttpParams();
    if (filter) params = params.set('filter', filter);
    if (notificationIds && notificationIds.length) {
      return this.http.post(`${this.baseApi}/notifications/export`, { notificationIds }, {
        params,
        observe: 'response',
        responseType: 'blob'
      });
    }

    return this.http.get(`${this.baseApi}/notifications/export`, {
      params,
      observe: 'response',
      responseType: 'blob'
    });
  }
}
