import { randomUUID } from 'crypto';

import { mediaConfig } from '../config';
import { SfuSessionRegistry } from './registry';
import type {
  SfuPublishTransportRequest,
  SfuPublishTransportResult,
  SfuService,
  SfuSessionDescriptor,
  SfuSessionStartInput,
  SfuSubscribeTransportRequest,
  SfuSubscribeTransportResult,
} from './types';

const toIceServers = (): Array<{ urls: string; username?: string; credential?: string }> => {
  if (mediaConfig.turn.urls.length === 0) {
    return [];
  }

  return mediaConfig.turn.urls.map((urls) => ({
    urls,
    ...(mediaConfig.turn.username ? { username: mediaConfig.turn.username } : {}),
    ...(mediaConfig.turn.credential ? { credential: mediaConfig.turn.credential } : {}),
  }));
};

export class NoopSfuService implements SfuService {
  mode: 'single_server_sfu' = 'single_server_sfu';
  private readonly registry = new SfuSessionRegistry();

  async startSession(input: SfuSessionStartInput): Promise<SfuSessionDescriptor> {
    const now = new Date().toISOString();
    const existing = this.registry.get(input.streamSessionId);
    if (existing) return existing;

    const descriptor: SfuSessionDescriptor = {
      streamSessionId: input.streamSessionId,
      ownerUserId: input.ownerUserId,
      cameraDeviceId: input.cameraDeviceId,
      requesterDeviceId: input.requesterDeviceId,
      state: 'starting',
      createdAt: now,
    };
    return this.registry.set(descriptor);
  }

  async setSessionState(streamSessionId: string, state: SfuSessionDescriptor['state']): Promise<void> {
    this.registry.updateState(streamSessionId, state);
  }

  async endSession(streamSessionId: string): Promise<void> {
    this.registry.updateState(streamSessionId, 'ending');
    this.registry.updateState(streamSessionId, 'ended');
  }

  async getSession(streamSessionId: string): Promise<SfuSessionDescriptor | null> {
    return this.registry.get(streamSessionId);
  }

  async listSessions(): Promise<SfuSessionDescriptor[]> {
    return this.registry.list();
  }

  async createPublishTransport(_input: SfuPublishTransportRequest): Promise<SfuPublishTransportResult> {
    return {
      transportId: `pub_${randomUUID()}`,
      iceServers: toIceServers(),
    };
  }

  async createSubscribeTransport(_input: SfuSubscribeTransportRequest): Promise<SfuSubscribeTransportResult> {
    return {
      transportId: `sub_${randomUUID()}`,
      iceServers: toIceServers(),
    };
  }
}
