import { HttpClient } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { Observable } from 'rxjs';
import type {
  PluginEventDefinitionSummary,
  PluginRequirementStatus,
  PluginRequirementSummary,
  PluginRequirementsSnapshot,
  TojuPluginManifest
} from '../../../../shared-kernel';

export interface UpsertPluginRequirementRequest {
  actorUserId: string;
  installUrl?: string;
  manifest?: TojuPluginManifest;
  reason?: string;
  sourceUrl?: string;
  status: PluginRequirementStatus;
  versionRange?: string;
}

export interface UpsertPluginEventDefinitionRequest {
  actorUserId: string;
  direction: 'clientToServer' | 'serverRelay' | 'p2pHint';
  maxPayloadBytes?: number;
  rateLimitJson?: string;
  schemaJson?: string;
  scope: 'server' | 'channel' | 'user' | 'plugin';
}

@Injectable({ providedIn: 'root' })
export class PluginRequirementService {
  private readonly http = inject(HttpClient);

  getSnapshot(apiBaseUrl: string, serverId: string): Observable<PluginRequirementsSnapshot> {
    return this.http.get<PluginRequirementsSnapshot>(`${this.apiBase(apiBaseUrl)}/servers/${encodeURIComponent(serverId)}/plugins`);
  }

  upsertRequirement(
    apiBaseUrl: string,
    serverId: string,
    pluginId: string,
    request: UpsertPluginRequirementRequest
  ): Observable<{ requirement: PluginRequirementSummary }> {
    return this.http.put<{ requirement: PluginRequirementSummary }>(
      `${this.apiBase(apiBaseUrl)}/servers/${encodeURIComponent(serverId)}/plugins/${encodeURIComponent(pluginId)}/requirement`,
      request
    );
  }

  deleteRequirement(apiBaseUrl: string, serverId: string, pluginId: string, actorUserId: string): Observable<{ ok: boolean }> {
    return this.http.delete<{ ok: boolean }>(
      `${this.apiBase(apiBaseUrl)}/servers/${encodeURIComponent(serverId)}/plugins/${encodeURIComponent(pluginId)}/requirement`,
      { body: { actorUserId } }
    );
  }

  upsertEventDefinition(
    apiBaseUrl: string,
    serverId: string,
    pluginId: string,
    eventName: string,
    request: UpsertPluginEventDefinitionRequest
  ): Observable<{ eventDefinition: PluginEventDefinitionSummary }> {
    const eventUrl = `${this.apiBase(apiBaseUrl)}/servers/${encodeURIComponent(serverId)}`
      + `/plugins/${encodeURIComponent(pluginId)}/events/${encodeURIComponent(eventName)}`;

    return this.http.put<{ eventDefinition: PluginEventDefinitionSummary }>(
      eventUrl,
      request
    );
  }

  private apiBase(apiBaseUrl: string): string {
    return apiBaseUrl.replace(/\/$/, '');
  }
}
