/**
 * @fileoverview MCP Tools Service
 *
 * Service for managing MCP tool operations including synchronization
 * with real-time progress streaming via GraphQL subscriptions.
 */
import { Injectable } from '@angular/core';
import { GraphQLDataProvider, gql } from '@memberjunction/graphql-dataprovider';
import { Subject, BehaviorSubject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import * as i0 from "@angular/core";
/**
 * GraphQL mutation for syncing MCP tools
 */
const SyncMCPToolsMutation = gql `
    mutation SyncMCPTools($input: SyncMCPToolsInput!) {
        SyncMCPTools(input: $input) {
            Success
            ErrorMessage
            Added
            Updated
            Deprecated
            Total
            ServerName
            ConnectionName
            RequiresOAuth
            AuthorizationUrl
            StateParameter
            RequiresReauthorization
            ReauthorizationReason
        }
    }
`;
/**
 * Service for MCP tool synchronization operations
 */
export class MCPToolsService {
    destroy$ = new Subject();
    /** Map of connection ID to sync state */
    syncStates = new Map();
    /** Provider instance for GraphQL operations */
    gqlProvider = GraphQLDataProvider.Instance;
    constructor() {
        this.setupProgressListener();
    }
    ngOnDestroy() {
        this.destroy$.next();
        this.destroy$.complete();
        this.syncStates.forEach(state => state.complete());
        this.syncStates.clear();
    }
    /**
     * Gets the sync state observable for a connection
     */
    getSyncState(connectionId) {
        return this.getOrCreateSyncState(connectionId).asObservable();
    }
    /**
     * Gets the current sync state value for a connection
     */
    getSyncStateValue(connectionId) {
        return this.getOrCreateSyncState(connectionId).getValue();
    }
    /**
     * Checks if a connection is currently syncing
     */
    isSyncing(connectionId) {
        const state = this.syncStates.get(connectionId);
        return state ? state.getValue().isSyncing : false;
    }
    /**
     * Syncs tools for a specific MCP connection
     *
     * @param connectionId - The ID of the MCP connection to sync
     * @param forceSync - Optional flag to force sync even if recently synced
     * @returns Promise resolving to the sync result
     */
    async syncTools(connectionId, forceSync = false) {
        const state$ = this.getOrCreateSyncState(connectionId);
        // Check if already syncing
        if (state$.getValue().isSyncing) {
            throw new Error('Sync already in progress for this connection');
        }
        // Update state to syncing
        state$.next({
            ...state$.getValue(),
            isSyncing: true,
            progress: {
                resolver: 'MCPResolver',
                type: 'MCPToolSyncProgress',
                status: 'ok',
                connectionId,
                phase: 'connecting',
                message: 'Starting sync...'
            },
            error: null
        });
        try {
            // Execute the mutation
            const result = await this.gqlProvider.ExecuteGQL(SyncMCPToolsMutation, {
                input: {
                    ConnectionID: connectionId,
                    ForceSync: forceSync
                }
            });
            const syncResult = result?.SyncMCPTools || {
                Success: false,
                ErrorMessage: 'No result returned from server',
                Added: 0,
                Updated: 0,
                Deprecated: 0,
                Total: 0
            };
            // Update state with result
            state$.next({
                isSyncing: false,
                progress: null,
                lastResult: syncResult,
                error: syncResult.Success ? null : (syncResult.ErrorMessage || 'Sync failed')
            });
            return syncResult;
        }
        catch (error) {
            const errorMsg = error instanceof Error ? error.message : String(error);
            // Update state with error
            state$.next({
                isSyncing: false,
                progress: null,
                lastResult: null,
                error: errorMsg
            });
            return {
                Success: false,
                ErrorMessage: errorMsg,
                Added: 0,
                Updated: 0,
                Deprecated: 0,
                Total: 0
            };
        }
    }
    /**
     * Clears the sync state for a connection
     */
    clearSyncState(connectionId) {
        const state$ = this.syncStates.get(connectionId);
        if (state$) {
            state$.next({
                isSyncing: false,
                progress: null,
                lastResult: null,
                error: null
            });
        }
    }
    /**
     * Gets or creates a sync state subject for a connection
     */
    getOrCreateSyncState(connectionId) {
        let state$ = this.syncStates.get(connectionId);
        if (!state$) {
            state$ = new BehaviorSubject({
                isSyncing: false,
                progress: null,
                lastResult: null,
                error: null
            });
            this.syncStates.set(connectionId, state$);
        }
        return state$;
    }
    /**
     * Sets up listener for progress updates via the GraphQL subscription
     * The statusUpdates subscription receives progress messages during sync
     */
    setupProgressListener() {
        // Listen for status updates from the GraphQL provider
        // These come through the existing PUSH_STATUS_UPDATES subscription
        // PushStatusUpdates returns Observable<string> with the message content
        this.gqlProvider.PushStatusUpdates()
            .pipe(takeUntil(this.destroy$), filter((message) => {
            try {
                const parsed = JSON.parse(message || '{}');
                return parsed.type === 'MCPToolSyncProgress';
            }
            catch {
                return false;
            }
        }))
            .subscribe((message) => {
            try {
                const progress = JSON.parse(message || '{}');
                this.handleProgressUpdate(progress);
            }
            catch (error) {
                console.error('Failed to parse MCP sync progress:', error);
            }
        });
    }
    /**
     * Handles a progress update from the server
     */
    handleProgressUpdate(progress) {
        const state$ = this.syncStates.get(progress.connectionId);
        if (state$ && state$.getValue().isSyncing) {
            state$.next({
                ...state$.getValue(),
                progress
            });
        }
    }
    static ɵfac = function MCPToolsService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MCPToolsService)(); };
    static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: MCPToolsService, factory: MCPToolsService.ɵfac, providedIn: 'root' });
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MCPToolsService, [{
        type: Injectable,
        args: [{
                providedIn: 'root'
            }]
    }], () => [], null); })();
//# sourceMappingURL=mcp-tools.service.js.map