import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
/**
 * McpScreen — MCP server install/remove flow (v2).
 *
 * Uses an McpInstaller service (passed via props) instead of
 * importing business logic directly. Testable, no dynamic imports.
 *
 * Supports two modes via the `mode` prop:
 *   - 'install': detect clients -> confirm -> install
 *   - 'remove': detect installed clients -> confirm -> remove
 *
 * When done, calls store.setMcpComplete(). The router resolves to outro.
 */
import { Box, Text } from 'ink';
import { useState, useEffect, useRef } from 'react';
import { McpOutcome, RunPhase } from '../store.js';
import { useWizardStore } from '../hooks/useWizardStore.js';
import { useEscapeBack } from '../hooks/useEscapeBack.js';
import { ConfirmationInput, PickerMenu } from '../primitives/index.js';
import { Colors, Icons } from '../styles.js';
import { BrailleSpinner } from '../components/BrailleSpinner.js';
import { analytics, captureWizardError } from '../../../utils/analytics.js';
import { wizardSuccessExit } from '../../../utils/wizard-abort.js';
import { resolveZone } from '../../../lib/zone-resolution.js';
import { DEFAULT_AMPLITUDE_ZONE } from '../../../lib/constants.js';
var Phase;
(function (Phase) {
    Phase["Detecting"] = "detecting";
    Phase["Ask"] = "ask";
    Phase["Pick"] = "pick";
    Phase["Working"] = "working";
    Phase["Done"] = "done";
    Phase["None"] = "none";
})(Phase || (Phase = {}));
const markDone = (store, outcome, clients = [], standalone = false, onComplete) => {
    if (onComplete) {
        onComplete();
    }
    else {
        store.setMcpComplete(outcome, clients);
        if (standalone) {
            // Standalone /mcp slash-command run — route through
            // wizardSuccessExit so the 'MCP Install Complete' /
            // 'MCP No Clients Detected' analytics events fired moments
            // earlier flush before the process tears down. A bare
            // process.exit(0) here drops the trailing telemetry.
            void wizardSuccessExit(0);
        }
    }
};
export const McpScreen = ({ store, installer, mode = 'install', standalone = false, onComplete, }) => {
    useWizardStore(store);
    const isRemove = mode === 'remove';
    const timerRef = useRef(null);
    const unmountedRef = useRef(false);
    // Clear any pending timer on unmount and flag as unmounted so late-resolving
    // async work (e.g. detectClients) won't schedule new timers or call markDone.
    useEffect(() => {
        return () => {
            unmountedRef.current = true;
            if (timerRef.current !== null)
                clearTimeout(timerRef.current);
        };
    }, []);
    const { runPhase, amplitudePreDetected, amplitudePreDetectedChoicePending } = store.session;
    const dataSetupComplete = runPhase === RunPhase.Completed;
    // When shown as an /mcp slash-command overlay, onComplete is provided and
    // the user explicitly asked for MCP setup. Don't hijack their request with
    // the pre-detected picker (that's meant for the main wizard flow only).
    const isOverlay = onComplete !== undefined;
    const showPreDetectedChoice = amplitudePreDetectedChoicePending && !isOverlay;
    const [phase, setPhase] = useState(Phase.Detecting);
    const [clients, setClients] = useState([]);
    const [resultClients, setResultClients] = useState([]);
    useEffect(() => {
        if (showPreDetectedChoice) {
            return;
        }
        void (async () => {
            try {
                const detected = await installer.detectClients();
                if (unmountedRef.current)
                    return;
                if (detected.length === 0) {
                    analytics.wizardCapture('MCP No Clients Detected', { mode });
                    setPhase(Phase.None);
                    timerRef.current = setTimeout(() => markDone(store, McpOutcome.NoClients, [], standalone, onComplete), 1500);
                }
                else {
                    analytics.wizardCapture('MCP Clients Detected', {
                        mode,
                        clients: detected.map((c) => c.name),
                        count: detected.length,
                    });
                    setClients(detected);
                    setPhase(Phase.Ask);
                }
            }
            catch {
                if (unmountedRef.current)
                    return;
                captureWizardError('MCP Client Detection', 'Editor client detection failed', 'McpScreen', { mode });
                setPhase(Phase.None);
                timerRef.current = setTimeout(() => markDone(store, McpOutcome.Failed, [], standalone, onComplete), 1500);
            }
        })();
    }, [installer, showPreDetectedChoice]);
    const handleConfirm = () => {
        if (isRemove) {
            analytics.wizardCapture('MCP Remove Confirmed');
            void doRemove();
        }
        else if (clients.length === 1) {
            const names = clients.map((c) => c.name);
            analytics.wizardCapture('MCP Install Confirmed', { clients: names });
            void doInstall(names);
        }
        else {
            analytics.wizardCapture('MCP Client Picker Shown', {
                available_clients: clients.map((c) => c.name),
            });
            setPhase(Phase.Pick);
        }
    };
    const handleSkip = () => {
        analytics.wizardCapture('MCP Skipped', { mode });
        markDone(store, McpOutcome.Skipped, [], standalone, onComplete);
    };
    /** Esc on MCP confirm: router back when possible, else skip MCP. */
    const escCancelOrRouterBack = () => {
        if (store.canGoBack()) {
            store.goBack();
        }
        else {
            handleSkip();
        }
    };
    // Esc → goBack on spinner / client picker / pre-detected choice. Disabled on
    // Ask because ConfirmationInput owns Esc there (`onEscape` →
    // escCancelOrRouterBack so we don't double-fire with this hook).
    const escapeBackEnabled = !standalone &&
        !isOverlay &&
        phase !== Phase.Ask &&
        phase !== Phase.Working &&
        phase !== Phase.Done;
    useEscapeBack(store, { enabled: escapeBackEnabled });
    const doInstall = async (names) => {
        setPhase(Phase.Working);
        let result = [];
        try {
            // readDisk: false — McpScreen runs after RegionSelect + Auth, so the
            // session region is the authoritative tier-1 source. The zone gets
            // baked into the URL written to each editor's MCP config and persists
            // past the wizard run; an EU user installing here without this would
            // be stuck talking to mcp.amplitude.com (US) forever.
            const zone = resolveZone(store.session, DEFAULT_AMPLITUDE_ZONE, {
                readDisk: false,
            });
            result = await installer.install(names, zone);
            setResultClients(result);
        }
        catch {
            setResultClients([]);
        }
        const failed = names.filter((n) => !result.includes(n));
        analytics.wizardCapture('MCP Install Complete', {
            installed: result,
            failed,
            attempted: names,
        });
        setPhase(Phase.Done);
        const outcome = result.length > 0 ? McpOutcome.Installed : McpOutcome.Failed;
        timerRef.current = setTimeout(() => markDone(store, outcome, result, standalone, onComplete), 2000);
    };
    const doRemove = async () => {
        setPhase(Phase.Working);
        let result = [];
        try {
            result = await installer.remove();
            setResultClients(result);
        }
        catch {
            setResultClients([]);
        }
        analytics.wizardCapture('MCP Remove Complete', { removed: result });
        setPhase(Phase.Done);
        const outcome = result.length > 0 ? McpOutcome.Installed : McpOutcome.Failed;
        timerRef.current = setTimeout(() => markDone(store, outcome, result, standalone, onComplete), 2000);
    };
    return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [dataSetupComplete && (_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: Colors.success, bold: true, children: [Icons.checkmark, ' ', amplitudePreDetected
                            ? 'Amplitude is already configured in this project!'
                            : 'Data setup complete!'] }) })), showPreDetectedChoice && !isRemove && (_jsxs(Box, { marginBottom: 1, flexDirection: "column", children: [_jsx(Text, { color: Colors.secondary, children: "The installer skipped the automated setup step because Amplitude is already present. You can continue to editor MCP setup, or run the full setup wizard if you want to review or change the integration." }), _jsx(Box, { marginTop: 1, children: _jsx(PickerMenu, { message: "How would you like to proceed?", options: [
                                { label: 'Continue to MCP setup', value: 'continue' },
                                {
                                    label: 'Run setup wizard anyway',
                                    value: 'wizard',
                                },
                            ], onSelect: (value) => {
                                const runWizard = value === 'wizard';
                                analytics.wizardCapture('Amplitude Pre-Detected Choice', {
                                    run_wizard_anyway: runWizard,
                                });
                                store.resolvePreDetectedChoice(runWizard);
                            } }) })] })), !showPreDetectedChoice && (_jsxs(_Fragment, { children: [_jsx(Text, { bold: true, color: Colors.accent, children: isRemove
                            ? 'Remove Amplitude from your AI tools'
                            : '💬 Chat with your Amplitude data' }), !isRemove && (_jsx(Text, { color: Colors.muted, children: "We\u2019ll wire the Amplitude MCP into Claude Code, Cursor, Claude Desktop, and other AI tools you have installed. You can then ask questions, build charts, and check metrics from chat (e.g. \u201Cshow me yesterday\u2019s signups\u201D)." })), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [phase === Phase.Detecting && (_jsxs(Box, { children: [_jsx(BrailleSpinner, { color: Colors.muted }), _jsxs(Text, { color: Colors.muted, children: [' ', "Looking for supported AI tools", Icons.ellipsis] })] })), phase === Phase.None && (_jsxs(Text, { color: Colors.muted, children: [isRemove
                                        ? 'Amplitude isn’t installed in any detected AI tool. Skipping'
                                        : 'No supported AI tools found on this machine. Skipping', Icons.ellipsis] })), phase === Phase.Ask && (_jsxs(_Fragment, { children: [_jsxs(Text, { color: Colors.secondary, children: ["Detected: ", clients.map((c) => c.name).join(', ')] }), _jsx(Box, { marginTop: 1, children: _jsx(ConfirmationInput, { message: isRemove
                                                ? 'Remove the Amplitude MCP server from your editor?'
                                                : 'Install the Amplitude MCP server to your editor?', confirmLabel: isRemove ? 'Remove MCP' : 'Install MCP', cancelLabel: "No thanks", onConfirm: handleConfirm, onCancel: handleSkip, onEscape: escCancelOrRouterBack }) })] })), phase === Phase.Pick && (_jsxs(_Fragment, { children: [_jsx(Text, { color: Colors.secondary, children: "Everything is pre-selected. Space to uncheck anything you don\u2019t want, then Enter to continue." }), _jsx(PickerMenu, { message: "Select AI tool to install MCP server", options: clients.map((c) => ({
                                            label: c.name,
                                            value: c.name,
                                        })), mode: "multi", defaultSelected: clients.map((c) => c.name), onSelect: (selected) => {
                                            const names = Array.isArray(selected)
                                                ? selected
                                                : [selected];
                                            if (names.length === 0) {
                                                handleSkip();
                                                return;
                                            }
                                            analytics.wizardCapture('MCP Clients Selected', {
                                                selected_clients: names,
                                                available_clients: clients.map((c) => c.name),
                                            });
                                            void doInstall(names);
                                        } })] })), phase === Phase.Working && (_jsxs(Text, { color: Colors.active, children: [isRemove ? 'Removing' : 'Installing', " MCP server", Icons.ellipsis] })), phase === Phase.Done && (_jsx(Box, { flexDirection: "column", children: resultClients.length > 0 ? (_jsxs(_Fragment, { children: [_jsxs(Text, { color: Colors.success, bold: true, children: [Icons.checkmark, " MCP server", ' ', isRemove ? 'removed from' : 'installed for', ":"] }), resultClients.map((name, i) => (_jsxs(Text, { color: Colors.body, children: [' ', Icons.bullet, " ", name] }, i))), !isRemove && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsxs(Text, { color: Colors.muted, children: ["Next: open", ' ', resultClients.length === 1
                                                        ? resultClients[0]
                                                        : 'any of the above', ", sign in when prompted, then ask \u201Cshow me yesterday\u2019s signups\u201D."] }) }))] })) : (_jsxs(Text, { color: Colors.muted, children: [isRemove ? 'Removal' : 'Installation', " skipped."] })) }))] })] }))] }));
};
