import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
/**
 * SlackScreen — Amplitude Slack integration setup (v2).
 *
 * Guides the user to connect their Slack workspace to Amplitude.
 * Since the OAuth handshake happens in the browser (Amplitude Settings),
 * this screen opens the right settings URL and lets the user confirm
 * once connected or skip.
 *
 * Region-aware: EU users need the "Amplitude - EU" Slack app.
 */
import { Box, Text } from 'ink';
import { useState, useEffect, useRef } from 'react';
import { SlackOutcome } from '../store.js';
import { useWizardStore } from '../hooks/useWizardStore.js';
import { useEscapeBack } from '../hooks/useEscapeBack.js';
import { ConfirmationInput, TerminalLink } from '../primitives/index.js';
import { Colors, Icons } from '../styles.js';
import { fetchSlackInstallUrl, fetchSlackConnectionStatus, } from '../../../lib/api.js';
import { OUTBOUND_URLS } from '../../../lib/constants.js';
import { useResolvedZone } from '../hooks/useResolvedZone.js';
import { logToFile } from '../../../utils/debug.js';
import { wizardSuccessExit } from '../../../utils/wizard-abort.js';
import opn from 'opn';
var Phase;
(function (Phase) {
    Phase["Prompt"] = "prompt";
    Phase["Opening"] = "opening";
    Phase["Waiting"] = "waiting";
    Phase["Verifying"] = "verifying";
    Phase["NotConnected"] = "notConnected";
    Phase["Done"] = "done";
})(Phase || (Phase = {}));
const markDone = (store, outcome, standalone, onComplete) => {
    if (onComplete) {
        onComplete();
    }
    else {
        store.setSlackComplete(outcome);
        if (standalone) {
            // Standalone /slack slash-command run — flush analytics
            // (the just-fired 'Slack Setup Complete' event) before the
            // process exits.
            void wizardSuccessExit(0);
        }
    }
};
export const SlackScreen = ({ store, standalone = false, onComplete, }) => {
    useWizardStore(store);
    const [phase, setPhase] = useState(Phase.Prompt);
    const timerRef = useRef(null);
    const unmountedRef = useRef(false);
    // ConfirmationInput: Esc → router back when possible (onEscape); focused
    // cancel row + Enter skips Slack (onCancel). Elsewhere (Opening / Verifying,
    // Done) Esc → goBack when the router allows it.
    const confirmationInputPhase = phase === Phase.Prompt ||
        phase === Phase.Waiting ||
        phase === Phase.NotConnected;
    useEscapeBack(store, {
        enabled: !standalone &&
            onComplete === undefined &&
            !confirmationInputPhase,
    });
    // Clear any pending timer on unmount and flag as unmounted so late-resolving
    // async work won't schedule new timers or call markDone.
    useEffect(() => {
        return () => {
            unmountedRef.current = true;
            if (timerRef.current !== null)
                clearTimeout(timerRef.current);
        };
    }, []);
    const region = useResolvedZone(store.session);
    const isEu = region === 'eu';
    const appName = isEu ? 'Amplitude - EU' : 'Amplitude';
    // Check if Slack is already connected on mount — auto-complete if so.
    useEffect(() => {
        let cancelled = false;
        const credentials = store.session.credentials;
        const orgId = store.session.selectedOrgId;
        logToFile(`[SlackScreen] selectedOrgName=${store.session.selectedOrgName ?? ''} credentials=${credentials ? 'present' : 'null'} region=${region}`);
        // The App API uses access_token, not id_token.
        const accessToken = credentials?.accessToken;
        if (accessToken && orgId) {
            void fetchSlackConnectionStatus(accessToken, region, orgId).then((isConnected) => {
                if (cancelled || unmountedRef.current)
                    return;
                logToFile(`[SlackScreen] slackConnectionStatus=${isConnected}`);
                if (isConnected) {
                    setPhase(Phase.Done);
                    timerRef.current = setTimeout(() => {
                        if (!cancelled && !unmountedRef.current) {
                            markDone(store, SlackOutcome.Configured, standalone, onComplete);
                        }
                    }, 1500);
                }
            });
        }
        return () => {
            cancelled = true;
        };
    }, []);
    const settingsUrl = OUTBOUND_URLS.slackSettings(region, store.session.selectedOrgId);
    const [openedUrl, setOpenedUrl] = useState(settingsUrl);
    const handleConnect = () => {
        setPhase(Phase.Opening);
        const credentials = store.session.credentials;
        const orgId = store.session.selectedOrgId;
        // The App API uses access_token, not id_token.
        const accessToken = credentials?.accessToken;
        // Try the direct Slack OAuth URL first; fall back to settings page.
        const open = (url) => {
            if (unmountedRef.current)
                return;
            setOpenedUrl(url);
            logToFile(`[SlackScreen] opening ${url === settingsUrl ? 'settings fallback' : 'direct Slack OAuth URL'}`);
            opn(url, { wait: false }).catch(() => { });
            timerRef.current = setTimeout(() => setPhase(Phase.Waiting), 800);
        };
        if (accessToken && orgId) {
            void fetchSlackInstallUrl(accessToken, region, orgId, settingsUrl).then((directUrl) => open(directUrl ?? settingsUrl));
        }
        else {
            open(settingsUrl);
        }
    };
    const handleSkip = () => {
        markDone(store, SlackOutcome.Skipped, standalone, onComplete);
    };
    /** Esc on confirm prompts: step back when possible; otherwise skip Slack. */
    const escCancelOrRouterBack = () => {
        if (store.canGoBack()) {
            store.goBack();
        }
        else {
            handleSkip();
        }
    };
    const handleDone = () => {
        // Don't trust the user's "yes" — re-verify against the App API. The
        // OAuth handshake can silently fail (closed tab, denied consent, popup
        // blocker) and we'd otherwise celebrate a connection that doesn't
        // exist.
        const credentials = store.session.credentials;
        const orgId = store.session.selectedOrgId;
        const accessToken = credentials?.accessToken;
        if (!accessToken || !orgId) {
            // No way to verify — fall back to trusting the user. This matches
            // the pre-existing behavior for unauthenticated/standalone runs.
            setPhase(Phase.Done);
            timerRef.current = setTimeout(() => markDone(store, SlackOutcome.Configured, standalone, onComplete), 1500);
            return;
        }
        setPhase(Phase.Verifying);
        void fetchSlackConnectionStatus(accessToken, region, orgId).then((isConnected) => {
            if (unmountedRef.current)
                return;
            logToFile(`[SlackScreen] post-confirm slackConnectionStatus=${isConnected}`);
            if (isConnected) {
                setPhase(Phase.Done);
                timerRef.current = setTimeout(() => markDone(store, SlackOutcome.Configured, standalone, onComplete), 1500);
            }
            else {
                setPhase(Phase.NotConnected);
            }
        });
    };
    const handleRetry = () => {
        // User wants another shot — re-open the auth URL and go back to
        // Waiting so they can confirm again.
        handleConnect();
    };
    return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [_jsx(Text, { bold: true, color: Colors.accent, children: "Slack Integration" }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: Colors.secondary, children: "Connect Amplitude to Slack for chart previews, dashboard sharing," }), _jsx(Text, { color: Colors.secondary, children: "and real-time tracking plan notifications." }), isEu && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: Colors.warning, children: "EU region: install the \"Amplitude - EU\" app from the Slack App Directory." }) })), phase === Phase.Prompt && (_jsx(Box, { marginTop: 1, children: _jsx(ConfirmationInput, { message: `Connect the "${appName}" Slack app to your workspace?`, confirmLabel: "Connect", cancelLabel: "Skip for now", onConfirm: handleConnect, onCancel: handleSkip, onEscape: escCancelOrRouterBack }) })), phase === Phase.Opening && (_jsxs(Text, { color: Colors.active, children: ["Opening browser", Icons.ellipsis] })), phase === Phase.Waiting && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [openedUrl === settingsUrl ? (_jsxs(_Fragment, { children: [_jsxs(Text, { color: Colors.body, children: ["Browser opened to", ' ', _jsx(TerminalLink, { url: settingsUrl, children: settingsUrl })] }), _jsxs(Text, { color: Colors.secondary, children: ["Go to Settings ", Icons.chevronRight, " Personal Settings", ' ', Icons.chevronRight, " Profile and click \"Connect to Slack\"."] }), _jsxs(Text, { color: Colors.muted, children: ["Docs:", ' ', _jsx(TerminalLink, { url: "https://amplitude.com/docs/analytics/integrate-slack" })] })] })) : (_jsxs(_Fragment, { children: [_jsxs(Text, { color: Colors.body, children: ["Browser opened to ", _jsx(Text, { color: Colors.accent, children: "Slack" }), " for authorization."] }), _jsxs(Text, { color: Colors.secondary, children: ["Authorize the ", appName, " app in Slack to complete the connection."] }), _jsxs(Text, { color: Colors.muted, children: ["Docs:", ' ', _jsx(TerminalLink, { url: "https://amplitude.com/docs/analytics/integrate-slack" })] })] })), _jsx(Box, { marginTop: 1, children: _jsx(ConfirmationInput, { message: "Connected to Slack?", confirmLabel: "Yes, connected", cancelLabel: "Skip for now", onConfirm: handleDone, onCancel: handleSkip, onEscape: escCancelOrRouterBack }) })] })), phase === Phase.Verifying && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: Colors.active, children: ["Checking your Slack connection", Icons.ellipsis] }) })), phase === Phase.NotConnected && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { color: Colors.warning, children: ["We don't see the Slack connection yet. Make sure you finished authorizing the ", appName, " app in your browser."] }), _jsx(Box, { marginTop: 1, children: _jsx(ConfirmationInput, { message: "Try again?", confirmLabel: "Retry", cancelLabel: "Skip anyway", onConfirm: handleRetry, onCancel: handleSkip, onEscape: escCancelOrRouterBack }) })] })), phase === Phase.Done && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsxs(Text, { color: Colors.success, bold: true, children: [Icons.checkmark, " Slack connected! You'll get chart previews and notifications in Slack."] }) }))] })] }));
};
