112211

/* eslint-disable */
import { Inject, Injectable, Headers, InternalServerErrorException, BadRequestException } from '@nestjs/common';
import { AxiosUtil, LOGGER, LoggerUtil } from '@cvsdigital_sdk/nest-graphql-common';
import { ConfigService } from '@nestjs/config';
import CacheUtil from './utils/cache.util';

import MasterIntentClassifierResponse from './model/masterintent.model';
import IntentClassEnum from './model/intentClass.enum';
import { IntentRule, IntentRules } from './model/intent-rules.interface';
import { MatchedIntentResponse } from './model/matched-intent-response.model';
import DigitalIVRSessionsEntity from './entity/DigitalIVRSessions.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import PrescriberAddress from './masterintent.repository';

import IntentExperienceService from './intent.experience.service';
import { performance } from 'perf_hooks';

@Injectable()
export default class MasterIntentService {
    private configPrefix: string;
    constructor(
        private axiosUtil: AxiosUtil,
        private readonly configService: ConfigService,
        private readonly cacheUtil: CacheUtil,
        private readonly experienceService: IntentExperienceService,
        @InjectRepository(DigitalIVRSessionsEntity)
        private digitalIVRSessionsEntity: Repository<DigitalIVRSessionsEntity>,
        @Inject(LOGGER) private readonly logger: LoggerUtil,
    ) {}

    public setConfigPrefix(channel: string | string[]): void {
        let prefix: string;

        if (Array.isArray(channel)) {
            prefix = channel[0];
        } else {
            prefix = channel;
        }

        if (prefix !== 'X42_IVR' && prefix !== 'X42_CHAT') {
            prefix = 'X42_IVR';
        }
        this.configPrefix = prefix;
    }

    /**
     * Get Master Intent
     * @param userText
     * @param channel
     * @param id
     * @param idType
     */
    public async getMasterIntent(userText: string, id?: string, idType?: string, store?: string): Promise<any> {
        const startTime = performance.now();
        const masterIntentResponse: MasterIntentClassifierResponse = new MasterIntentClassifierResponse();
        masterIntentResponse.statusFlags = {
            expeditedPrescriptionEligibleCount: -1,
            prescriptionEligibleCount: -1,
            cancelPrescriptionEligibleCount: -1,
            refillablePrescriptionEligibleCount: -1,
            transferPrescriptionEligibleCount: -1,
            prescriptionStatus: [],
        };

        // Classify intent and skip words in parallel
        const mlResponsePromise = this.classifyIntent(userText);
        const skipWordsPromise = this.configService.get<string[]>(`skipWords`) || [];
        const cacheLogicPromise = id && idType ? this.handleCacheLogic(masterIntentResponse, id, idType) : Promise.resolve();
        const userQueryCache = this.getUserQueryCache(userText, masterIntentResponse);

        const [mlResponse, skipWords, cacheLogicResponse, userCacheResponse] = await Promise.all([
            mlResponsePromise,
            skipWordsPromise,
            cacheLogicPromise,
            userQueryCache,
        ]);

        // Process high-level intent and check if it should be skipped
        const highLevelIntent = mlResponse?.intents.length ? mlResponse.intents[0].toLowerCase().trim() : 'unknown';
        const isSkip = skipWords.some((word) => highLevelIntent.toLowerCase().includes(word.toLowerCase()));

        let intentResp: string[] | undefined;

        // Get Intent AI data if not skipping and cache is not available
        if (highLevelIntent !== 'unknown' && !isSkip && !userCacheResponse) {
            const intentAIDataPromise = this.getIntentAIData(userText, highLevelIntent);
            const response = await intentAIDataPromise;
            intentResp = response?.chat_response.split(',');
            masterIntentResponse.subIntent = intentResp.map((i: string) => i.toLowerCase().trim());
        } else {
            masterIntentResponse.subIntent = userCacheResponse ? [userCacheResponse] : [highLevelIntent];
        }

        masterIntentResponse.userText = userText;

        // Filter out 'help' from subIntents if necessary
        const valueToRemove = 'help';
        masterIntentResponse.subIntent =
            masterIntentResponse.subIntent.length > 1
                ? masterIntentResponse.subIntent.filter((item) => item !== valueToRemove)
                : masterIntentResponse.subIntent;

        await cacheLogicPromise;

        // Handle intent matching
        let matchedIntent: MatchedIntentResponse = await this.matchIntent(masterIntentResponse.subIntent);

        if (masterIntentResponse.subIntent.includes('unknown')) {
            masterIntentResponse.intent = String(IntentClassEnum.INTENT_UNKNOWN);
        } else if (matchedIntent.matchedAttributes.mainIntent === 'multiintent') {
            matchedIntent = await this.matchExceptionIntent(masterIntentResponse.subIntent);
        }

        masterIntentResponse.intent = matchedIntent.matchedAttributes.mainIntent;
        masterIntentResponse.fillerText = matchedIntent.partialFiller;
        masterIntentResponse.promptId = matchedIntent.matchedAttributes.promptID?.trim() || '-1';
        masterIntentResponse.templateId = matchedIntent.matchedAttributes.dataTemplate?.trim() || '-1';
        masterIntentResponse.ruleNo = matchedIntent.matchedAttributes.ruleNo?.trim() || '-1';
        masterIntentResponse.seqNo = matchedIntent.matchedAttributes.seqNo;

        // Additional check for patient interaction
        let patientInteractedRecently = false;
        masterIntentResponse.statusFlags.patientInteractedRecently = patientInteractedRecently;
        if (masterIntentResponse.intent === 'live_pharmacist' && id) {
            patientInteractedRecently = await this.hasRecentEntry(id);
            masterIntentResponse.statusFlags.patientInteractedRecently = patientInteractedRecently;
            this.logger.addFunctionalTags(
                'masterIntentResponse.patientInteractedRecently',
                `${patientInteractedRecently}`,
            );
        }

        // Call classifyIntentForPartialFiller and set fillerText
        const partialFillerResponse = await this.classifyIntentForPartialFiller(userText, highLevelIntent);
        masterIntentResponse.fillerText = partialFillerResponse?.text || '';

        // Log response and performance
        this.logger.addFunctionalTags('masterIntentResponse.intent', `${masterIntentResponse.intent}`);
        this.logger.addFunctionalTags('masterIntentResponse.subIntent', `${masterIntentResponse.subIntent}`);
        this.logger.addFunctionalTags('masterIntentResponse.fillerText', `${masterIntentResponse.fillerText}`);
        this.logger.addFunctionalTags('masterIntentResponse.promptId', `${masterIntentResponse.promptId}`);
        this.logger.addFunctionalTags('masterIntentResponse.templateId', `${masterIntentResponse.templateId}`);
        this.logger.addFunctionalTags('masterIntentResponse.ruleId', `${matchedIntent.matchedAttributes.ruleNo}`);
        this.logger.addFunctionalTags('masterIntentResponse.seqNo', `${matchedIntent.matchedAttributes.seqNo}`);
        this.logger.addFunctionalTags('masterIntentResponse', `${JSON.stringify(masterIntentResponse)}`);
        const endTime = performance.now();
        const duration = endTime - startTime;
        this.logger.addFunctionalTags('MasterIntentServiceTimeTaken', `${duration}ms`);

        return masterIntentResponse;
    }

    /**
     * Classify Intent for Partial Filler
     * @param userText
     * @param highLevelIntent
     * @returns Partial filler text response
     */
    private async classifyIntentForPartialFiller(userText: string, highLevelIntent: string): Promise<any> {
        const classifyIntentReq: any = {
            query: userText,
            intent: highLevelIntent,
        };
        this.logger.addFunctionalTags('classifyIntentForPartialFillerRequest', classifyIntentReq);

        // Extract the client name directly without including the configPrefix
        const clientName = `${this.configPrefix}.ClassifyIntentForPartialFiller`;

        // Use the configPrefix to correctly fetch the URI
        const uri = this.configService.get<string>(`client.${clientName}.uri`);
        this.logger.addFunctionalTags('configUriForPartialFiller', uri);

        const startTime = performance.now();

        const classifyIntentForPartialFillerResponse: any = await this.axiosUtil.getInstance(clientName).post(uri, classifyIntentReq);
        const endTime = performance.now();
        const duration = endTime - startTime;
        this.logger.addFunctionalTags('classifyIntentForPartialFillerTimeTaken', `${duration}ms`);

        this.logger.addFunctionalTags('classifyIntentForPartialFillerResponse', classifyIntentForPartialFillerResponse);
        return classifyIntentForPartialFillerResponse;
    }

    // Other existing methods ...
}