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

import { API_ORIGIN } from '../config/api.tokens';
import { DEFAULT_PAGE_LIMIT } from '../config/app.tokens';
import type {
  CreateSessionRequest,
  CreateSessionResponse,
  FingerprintHeartbeatsResponse,
  ParsedEventsResponse,
  SessionDetailResponse,
  SessionListResponse,
  StreamType,
  TelemetryEvent,
} from '../models/api.types';

@Injectable({ providedIn: 'root' })
export class SessionsApiService {
  private readonly http = inject(HttpClient);
  private readonly apiOrigin = inject(API_ORIGIN);
  private readonly defaultLimit = inject(DEFAULT_PAGE_LIMIT);

  listSessions(limit = this.defaultLimit, offset = 0): Observable<SessionListResponse> {
    const params = new HttpParams()
      .set('limit', String(limit))
      .set('offset', String(offset));
    return this.http.get<SessionListResponse>('/sessions', { params });
  }

  createSession(body: CreateSessionRequest): Observable<CreateSessionResponse> {
    return this.http.post<CreateSessionResponse>('/sessions', body);
  }

  getSession(id: number): Observable<SessionDetailResponse> {
    return this.http.get<SessionDetailResponse>(`/sessions/${id}`);
  }

  getTelemetry(sessionId: number): Observable<TelemetryEvent[]> {
    return this.http.get<TelemetryEvent[]>(`/sessions/${sessionId}/telemetry`);
  }

  getParsedEvents(sessionId: number, from?: number, to?: number): Observable<ParsedEventsResponse> {
    let params = new HttpParams();
    if (typeof from === 'number') {
      params = params.set('from', String(from));
    }
    if (typeof to === 'number') {
      params = params.set('to', String(to));
    }
    return this.http.get<ParsedEventsResponse>(`/sessions/${sessionId}/events`, { params });
  }

  getFingerprintFull(sessionId: number): Observable<unknown> {
    return this.http.get<unknown>(`/sessions/${sessionId}/fingerprint/full`);
  }

  getFingerprintSummary(sessionId: number): Observable<unknown> {
    return this.http.get<unknown>(`/sessions/${sessionId}/fingerprint/summary`);
  }

  getFingerprintHeartbeats(sessionId: number, from?: number, to?: number, limit?: number): Observable<FingerprintHeartbeatsResponse> {
    let params = new HttpParams();
    if (typeof from === 'number') params = params.set('from', String(from));
    if (typeof to === 'number') params = params.set('to', String(to));
    if (typeof limit === 'number') params = params.set('limit', String(limit));
    
    return this.http.get<FingerprintHeartbeatsResponse>(`/sessions/${sessionId}/fingerprint/heartbeats`, { params });
  }

  resolvePlaylistUrl(playlistUrl: string): string {
    if (/^https?:\/\//i.test(playlistUrl)) {
      return playlistUrl;
    }
    return new URL(playlistUrl, `${this.apiOrigin}/`).href;
  }

  uploadChunk(
    sessionId: number,
    chunkIdx: number,
    file: File,
    streamType: StreamType = 'screen',
    bearerToken: string,
  ): Observable<void> {
    const form = new FormData();
    form.set('session_id', String(sessionId));
    form.set('chunk_idx', String(chunkIdx));
    form.set('stream_type', streamType);
    form.set('file', file, file.name);
    return this.http.post<void>('/upload', form, {
      headers: { Authorization: `Bearer ${bearerToken}` },
    });
  }
}
