import { BadRequestException, Injectable, Logger } from '@nestjs/common';
import { IFullUser } from 'src/modules/users/users.interface';
import { SubscriptionsService } from 'src/modules/subscriptions/subscriptions.service';
import { LanguageService } from 'src/shared/language/language.service';
import { GenerateImageService } from 'src/modules/image-history/services/generate-image.service';
import { RealTimeDataStreamService } from './real-time-data-stream.service';
import { CreateConversationDto } from '../chat-history.validation';
import { IDataToReturn } from 'src/shared/language/language.interface';
import { IChatResponseAdapter } from '../interfaces/chat-response-adapter.interface';
import { IStreamResponseObject } from '../interfaces/stream-response.interface';
import { CHAT_FUNCTION_CALL_TYPES } from '../chat-history.constant';
import { SUBSCRIPTIONS_ERROR_TYPES } from 'src/modules/subscriptions/subscriptions.constant';
import { Response } from 'express';

@Injectable()
export class FunctionCallHandlerService {
  private readonly logger = new Logger(FunctionCallHandlerService.name);

  constructor(
    private readonly realTimeDataService: RealTimeDataStreamService,
    private readonly subscriptionService: SubscriptionsService,
    private readonly languageService: LanguageService,
    private readonly generateImageService: GenerateImageService,
  ) {}

  async getFunctionCallResponseStream(
    functionCall: { name: string; arguments: any },
    createChatDto: CreateConversationDto,
    user: IFullUser,
    language_modification: IDataToReturn,
    regenerateMessageId: string,
    isRegenerate: boolean,
    skipBlockedReasons: string[],
    res?: Response,
    adapter?: IChatResponseAdapter,
  ): Promise<IStreamResponseObject | { type: 'image'; imageResult: any }> {
    this.logger.log(`getFunctionCallResponseStream: Handling function call ${functionCall.name}`);

    switch (functionCall.name) {
      case CHAT_FUNCTION_CALL_TYPES.GET_UPTO_DATE_DATA:
        const query = functionCall.arguments?.quary || functionCall.arguments?.query;
        return await this.realTimeDataService.generateRealTimeDataResponseStream(
          query,
          createChatDto,
          user,
          false,
          regenerateMessageId,
          isRegenerate,
          skipBlockedReasons,
        );

      case CHAT_FUNCTION_CALL_TYPES.GET_DATA_FROM_URL:
        const urlQuery = functionCall.arguments?.url;
        return await this.realTimeDataService.generateRealTimeDataResponseStream(
          urlQuery,
          createChatDto,
          user,
          true,
          regenerateMessageId,
          isRegenerate,
          skipBlockedReasons,
        );

      case CHAT_FUNCTION_CALL_TYPES.GENERATE_IMAGE:
        const checkSubscription = await this.subscriptionService.sendSubscriptionError(
          user,
          language_modification,
          'image',
        );

        const description = functionCall.arguments?.description;

        const translateDescription = (
          await this.languageService.translateText_v3_using_gpt(description)
        ).translatedContent;

        if (user?.subscription?.plan === 'free') {
          checkSubscription.cause = SUBSCRIPTIONS_ERROR_TYPES.GLOBAL_IMAGE_LIMIT_REACHED;
        }

        const preGenerateResult = await this.generateImageService.preGenerateChatForImages(
          {
            chat: {
              content: createChatDto.chat.content,
              type: 'image'
            },
            conversationId: createChatDto.conversationId,
            checkSubscription: checkSubscription || null,
          },
          language_modification,
          user,
          regenerateMessageId,
          isRegenerate
        );

        const imageData = {
          chatHistoryId: preGenerateResult?.chatHistory?._id?.toString(),
          preGenerateResult,
          description,
          translateDescription,
          checkSubscription,
        };
        
        if (imageData.chatHistoryId) {
          await adapter.sendConversationId(imageData.chatHistoryId);
          await adapter.endStream();
        }

        const imageResult = await this.generateImageService.chatHandleGenerateImage(
          {
            conversationId: imageData.chatHistoryId || createChatDto.conversationId,
            userPrompt: createChatDto.chat.content,
            prompt: imageData.description,
            translatedPrompt: imageData.translateDescription,
            user,
            regenerateMessageId,
            isRegenerate,
            checkSubscription: imageData.checkSubscription,
          },
          language_modification,
          imageData.preGenerateResult
        );

        return {
          type: 'image',
          imageResult,
        } as any;

      default:
        throw new BadRequestException(`Unknown function call: ${functionCall.name}`);
    }
  }
}
