/**
 * Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
 */
import { Channel, Channels } from '@techniker-me/pcast-api';
import PCastApiService from './PCastApi.service';
import LoggerFactory from './logger/LoggerFactory';

const logger = LoggerFactory.getLogger('services/channel.service');

export interface CreateChannelParams {
  name: string;
  description?: string;
  options?: string[];
}

export interface UpdateChannelParams {
  channelId: string;
  name?: string;
  alias?: string;
  description?: string;
  tags?: string[];
  capabilities?: string[];
}

export interface ForkChannelParams {
  sourceChannelId: string;
  destinationChannelId: string;
  streamCapabilities?: string[];
  streamTags?: string[];
  options?: string[];
}

export interface DeleteChannelParams {
  channelId: string;
  alias: string;
}

export interface KillChannelParams {
  channelId: string;
  reason?: string;
  options?: string[];
  enteredAlias?: string;
}

/**
 * Channel Service providing CRUD operations for channels
 */
class ChannelService {
  private phenixChannelService: PhenixChannelService | null = null;


  public async initializeWithPCastApi(channels: Channels) {
    try {
      // Wait for PCastApiService to be initialized
           this.phenixChannelService = channels;

    } catch (error) {
      logger.error('Failed to initialize ChannelService', error);
    }
  }

  /**
   * Get all channels
   */
  async listChannels(): Promise<Channel[]> {
    try {
      logger.debug('Fetching channel list');
      
      if (!this.phenixChannelService) {
        return PCastApiService.channels.list();
      }
      
      return await this.phenixChannelService.list();
    } catch (error) {
      logger.error('Failed to list channels', error);
      throw error;
    }
  }

  /**
   * Create a new channel
   */
  async createChannel(params: CreateChannelParams): Promise<Channel> {
    try {
      logger.debug('Creating channel', params);
      
      const channelData = {
        name: params.name,
        alias: params.alias,
        description: params.description || '',
        tags: params.tags || [],
        capabilities: params.capabilities || []
      };

      if (!this.phenixChannelService) {
        return PCastApiService.channels.create(name, description, options);
      }
      
      return await this.phenixChannelService.create(channelData);
    } catch (error) {
      logger.error('Failed to create channel', error);
      throw error;
    }
  }

  /**
   * Update an existing channel
   */
  async updateChannel(params: UpdateChannelParams): Promise<Channel> {
    try {
      logger.debug('Updating channel', params);
      
      const updateData = {
        ...params.name && { name: params.name },
        ...params.alias && { alias: params.alias },
        ...params.description && { description: params.description },
        ...params.tags && { tags: params.tags },
        ...params.capabilities && { capabilities: params.capabilities }
      };

      if (!this.phenixChannelService) {
        return PCastApiService.channels.update(params.channelId, updateData);
      }
      
      return await this.phenixChannelService.update(params.channelId, updateData);
    } catch (error) {
      logger.error('Failed to update channel', error);
      throw error;
    }
  }

  /**
   * Delete a channel
   */
  async deleteChannel(params: DeleteChannelParams): Promise<void> {
    try {
      logger.debug('Deleting channel', params);
      
      if (!this.phenixChannelService) {
        return PCastApiService.channels.delete(params.channelId);
      }
      
      await this.phenixChannelService.delete(params.channelId);
    } catch (error) {
      logger.error('Failed to delete channel', error);
      throw error;
    }
  }

  /**
   * Fork a channel
   */
  async forkChannel(params: ForkChannelParams): Promise<void> {
    try {
      logger.debug('Forking channel', params);
      
      const forkData = {
        destinationChannelId: params.destinationChannelId,
        streamCapabilities: params.streamCapabilities || [],
        streamTags: params.streamTags || [],
        options: params.options || []
      };

      // Phenix SDK fork method
      if (!this.phenixChannelService) {
        return PCastApiService.channels.fork(params.sourceChannelId, forkData);
      }
      
      await this.phenixChannelService.fork(params.sourceChannelId, forkData);
    } catch (error) {
      logger.error('Failed to fork channel', error);
      throw error;
    }
  }

  /**
   * Kill a channel
   */
  async killChannel(params: KillChannelParams): Promise<void> {
    try {
      logger.debug('Killing channel', params);
      
      const killData = {
        reason: params.reason || 'portal:killed',
        options: params.options || []
      };

      if (!this.phenixChannelService) {
        return PCastApiService.channels.kill(params.channelId, killData);
      }
      
      await this.phenixChannelService.kill(params.channelId, killData);
    } catch (error) {
      logger.error('Failed to kill channel', error);
      throw error;
    }
  }

  /**
   * Get channel by ID
   */
  async getChannel(channelId: string): Promise<Channel | null> {
    try {
      logger.debug('Getting channel', { channelId });
      
      if (!this.phenixChannelService) {
        return PCastApiService.channels.get(channelId);
      }
      
      return await this.phenixChannelService.get(channelId);
    } catch (error) {
      logger.error('Failed to get channel', error);
      throw error;
    }
  }

  /**
   * Get publisher count for a channel
   */
  async getPublisherCount(channelId: string): Promise<number> {
    try {
      logger.debug('Getting publisher count', { channelId });
      
      if (!this.phenixChannelService) {
        return PCastApiService.channels.getPublisherCount(channelId);
      }
      
      return await this.phenixChannelService.getPublisherCount(channelId);
    } catch (error) {
      logger.error('Failed to get publisher count', error);
      return 0;
    }
  }
}

// Export singleton instance
const channelService = new ChannelService();

// Named exports for individual operations
export const listChannels = channelService.listChannels.bind(channelService);
export const createChannel = channelService.createChannel.bind(channelService);
export const updateChannel = channelService.updateChannel.bind(channelService);
export const deleteChannel = channelService.deleteChannel.bind(channelService);
export const forkChannel = channelService.forkChannel.bind(channelService);
export const killChannel = channelService.killChannel.bind(channelService);
export const getChannel = channelService.getChannel.bind(channelService);
export const getPublisherCount = channelService.getPublisherCount.bind(channelService);

export default channelService;