import { AsyncPipe, DatePipe } from '@angular/common';
import { HttpErrorResponse } from '@angular/common/http';
import { ChangeDetectionStrategy, Component, input, inject } from '@angular/core';
import { toObservable } from '@angular/core/rxjs-interop';
import { TuiLoader } from '@taiga-ui/core/components/loader';
import { TuiIcon } from '@taiga-ui/core/components/icon';
import { catchError, combineLatest, map, of, startWith, switchMap } from 'rxjs';

import { SessionsApiService } from '../../../../core/services/sessions-api.service';
import { UserErrorNotifyService } from '../../../../core/notifications/user-error-notify.service';
import type { FingerprintHeartbeat, FingerprintHeartbeatPayload } from '../../../../core/models/api.types';

export interface Anomaly {
  timestamp_ms: number;
  field: string;
  fieldLabel: string;
  oldValue: unknown;
  newValue: unknown;
}

@Component({
  selector: 'app-session-fingerprint-tab',
  imports: [AsyncPipe, DatePipe, TuiLoader, TuiIcon],
  templateUrl: './session-fingerprint-tab.html',
  styleUrl: './session-fingerprint-tab.css',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SessionFingerprintTabComponent {
  private readonly api = inject(SessionsApiService);
  private readonly userErrors = inject(UserErrorNotifyService);

  readonly sessionId = input.required<number>();

  protected readonly data$ = toObservable(this.sessionId).pipe(
    switchMap((id) => {
      // Параллельно запрашиваем все данные фингерпринта
      return combineLatest([
        this.api.getFingerprintSummary(id).pipe(catchError(() => of(null))),
        this.api.getFingerprintFull(id).pipe(catchError(() => of(null))),
        this.api.getFingerprintHeartbeats(id, undefined, undefined, 50).pipe(catchError(() => of(null)))
      ]).pipe(
        map(([summary, full, heartbeats]) => {
          const hbs = heartbeats?.heartbeats || [];
          const anomalies = this.detectAnomalies(hbs);
          const currentConfig = hbs.length > 0 ? hbs[hbs.length - 1].payload : null;

          return {
            status: 'ok' as const,
            summary,
            full,
            heartbeats: hbs,
            anomalies,
            currentConfig,
          };
        }),
        catchError((e: HttpErrorResponse) => {
          this.userErrors.notifyError(e, 'Фингерпринт');
          return of({ status: 'error' as const });
        }),
        startWith({ status: 'loading' as const })
      );
    })
  );

  private static readonly ANOMALY_FIELDS: ReadonlyArray<{
    key: keyof FingerprintHeartbeatPayload;
    label: string;
  }> = [
    { key: 'screen_layout', label: 'Конфигурация экранов' },
    { key: 'username', label: 'Пользователь системы' },
    { key: 'hostname', label: 'Имя компьютера' },
    { key: 'active_iface', label: 'Сетевой адаптер' },
    { key: 'hypervisor_present', label: 'Виртуализация / Hypervisor' },
  ];

  private detectAnomalies(heartbeats: FingerprintHeartbeat[]): Anomaly[] {
    if (!heartbeats || heartbeats.length < 2) {
      return [];
    }

    const anomalies: Anomaly[] = [];

    for (let i = 1; i < heartbeats.length; i++) {
      const prev = heartbeats[i - 1].payload;
      const curr = heartbeats[i].payload;
      const timestamp = heartbeats[i].timestamp_ms;

      for (const field of SessionFingerprintTabComponent.ANOMALY_FIELDS) {
        const oldValue = prev[field.key];
        const newValue = curr[field.key];

        if (oldValue !== newValue) {
          anomalies.push({
            timestamp_ms: timestamp,
            field: field.key,
            fieldLabel: field.label,
            oldValue,
            newValue,
          });
        }
      }
    }

    // Сортируем от новых к старым
    return anomalies.sort((a, b) => b.timestamp_ms - a.timestamp_ms);
  }
}
