import { Injectable, inject, signal } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Subject, interval } from 'rxjs';
import { startWith, switchMap } from 'rxjs/operators';
import { NotificationItem } from '../../models/notification.model';
import { NotificationsApi } from './notifications-api';

const POLL_INTERVAL_MS = 30000;
const DROPDOWN_PAGE_SIZE = 20;

@Injectable({ providedIn: 'root' })
export class NotificationsStore {
  private readonly api = inject(NotificationsApi);

  private readonly unreadCountSignal = signal(0);
  private readonly notificationsSignal = signal<NotificationItem[]>([]);
  private readonly loadingSignal = signal(false);
  private readonly pollingTeamId = signal<number | null>(null);
  private readonly pollRequests = new Subject<number>();

  readonly unreadCount = this.unreadCountSignal.asReadonly();
  readonly notifications = this.notificationsSignal.asReadonly();
  readonly loading = this.loadingSignal.asReadonly();

  constructor() {
    this.pollRequests
      .pipe(
        switchMap((teamId) =>
          interval(POLL_INTERVAL_MS).pipe(
            startWith(-1),
            switchMap(() => this.api.loadUnreadCount(teamId)),
          ),
        ),
        takeUntilDestroyed(),
      )
      .subscribe((result) => this.unreadCountSignal.set(result.count));
  }

  startPolling(teamId: number): void {
    if (this.pollingTeamId() === teamId) return;
    this.pollingTeamId.set(teamId);
    this.pollRequests.next(teamId);
  }

  loadRecent(teamId: number): void {
    this.loadingSignal.set(true);
    this.api.loadNotifications(teamId, { page: 1, limit: DROPDOWN_PAGE_SIZE }).subscribe({
      next: (page) => {
        this.notificationsSignal.set(page.data);
        this.loadingSignal.set(false);
      },
      error: () => this.loadingSignal.set(false),
    });
  }

  markRead(teamId: number, id: number): void {
    this.api.markRead(teamId, id).subscribe(() => {
      this.notificationsSignal.update((items) =>
        items.map((item) => (item.id === id ? { ...item, read: true } : item)),
      );
      this.unreadCountSignal.update((count) => Math.max(0, count - 1));
    });
  }

  markAllRead(teamId: number): void {
    this.api.markAllRead(teamId).subscribe(() => {
      this.notificationsSignal.update((items) => items.map((item) => ({ ...item, read: true })));
      this.unreadCountSignal.set(0);
    });
  }
}
