import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { Box, Check, ChevronDown, Eye, Flag, FolderTree, Network, X, } from "lucide-react";
import { useCallback, useEffect, useMemo, useState, } from "react";
import { Button } from "../../components/ui/button";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "../../components/ui/dropdown-menu";
import { Switch } from "../../components/ui/switch";
import { Tooltip, TooltipContent, TooltipTrigger, } from "../../components/ui/tooltip";
import { cn } from "../../lib/utils";
import { useEditContext } from "../client/editContext";
import { getDefaultNotificationEventTypes } from "../services/notificationService";
import { subscribeToNotificationTarget, unmuteNotificationTarget, unsubscribeFromNotificationTarget, useNotificationSubscriptions, } from "./useNotificationSubscriptions";
import { getWatchEventOptions, } from "./watchEventOptions";
function orderEventTypes(eventTypes, targetType) {
    const eventOrder = getWatchEventOptions(targetType).map((option) => option.eventType);
    return [...eventTypes].sort((left, right) => {
        const leftIndex = eventOrder.indexOf(left);
        const rightIndex = eventOrder.indexOf(right);
        const normalizedLeft = leftIndex === -1 ? Number.MAX_SAFE_INTEGER : leftIndex;
        const normalizedRight = rightIndex === -1 ? Number.MAX_SAFE_INTEGER : rightIndex;
        return normalizedLeft - normalizedRight || left.localeCompare(right);
    });
}
function useWatchControls({ targetType, targetId, }) {
    const editContext = useEditContext();
    const [loading, setLoading] = useState(false);
    const [currentLanguageOnly, setCurrentLanguageOnly] = useState(false);
    const defaultEventTypes = useMemo(() => getDefaultNotificationEventTypes(targetType), [targetType]);
    const [selectedEventTypes, setSelectedEventTypes] = useState(() => getDefaultNotificationEventTypes(targetType));
    const { subscriptions } = useNotificationSubscriptions();
    const current = useMemo(() => {
        return subscriptions.find((subscription) => subscription.targetType.toLowerCase() === targetType &&
            subscription.targetId === targetId);
    }, [subscriptions, targetType, targetId]);
    const isWatching = Boolean(current && !current.isMuted);
    const isSubtree = Boolean(current?.includeDescendants);
    const disabled = loading || !targetId;
    const currentEventTypes = current?.eventTypes?.length && Array.isArray(current.eventTypes)
        ? current.eventTypes
        : defaultEventTypes;
    const currentLanguage = targetType === "item"
        ? editContext?.currentItemDescriptor?.language
        : undefined;
    const languageOnlyLabel = current?.language && current?.language !== currentLanguage
        ? `Current language only (${current.language})`
        : "Current language only";
    const watchEventOptions = useMemo(() => getWatchEventOptions(targetType), [targetType]);
    useEffect(() => {
        setCurrentLanguageOnly(Boolean(current?.language));
    }, [current?.language]);
    useEffect(() => {
        setSelectedEventTypes(orderEventTypes(currentEventTypes, targetType));
    }, [current?.eventTypes, currentEventTypes, targetType]);
    const doSubscribe = useCallback(async (descendants, options) => {
        if (disabled)
            return;
        setLoading(true);
        try {
            const eventTypes = orderEventTypes(options?.eventTypes ?? selectedEventTypes, targetType);
            const applyCurrentLanguageOnly = options?.currentLanguageOnly ?? currentLanguageOnly;
            await subscribeToNotificationTarget({
                targetType,
                targetId,
                includeDescendants: targetType === "item" ? descendants : false,
                language: targetType === "item" && applyCurrentLanguageOnly
                    ? currentLanguage
                    : undefined,
                eventTypes,
            });
        }
        finally {
            setLoading(false);
        }
    }, [
        currentLanguage,
        currentLanguageOnly,
        disabled,
        selectedEventTypes,
        targetId,
        targetType,
    ]);
    const doUnsubscribe = useCallback(async () => {
        if (disabled)
            return;
        setLoading(true);
        try {
            await unsubscribeFromNotificationTarget({ targetType, targetId });
        }
        finally {
            setLoading(false);
        }
    }, [disabled, targetId, targetType]);
    const doUnmute = useCallback(async () => {
        if (disabled)
            return;
        setLoading(true);
        try {
            await unmuteNotificationTarget({ targetType, targetId });
        }
        finally {
            setLoading(false);
        }
    }, [disabled, targetId, targetType]);
    // Three-state toggle: subscribe when not subscribed, unmute when subscribed
    // but muted, otherwise unsubscribe. The middle branch matters most for
    // `review` / `agent-run` targets, which use the single-button path.
    const toggleSimple = useCallback(async () => {
        if (disabled)
            return;
        if (!current) {
            await doSubscribe(false);
        }
        else if (current.isMuted) {
            await doUnmute();
        }
        else {
            await doUnsubscribe();
        }
    }, [current, disabled, doSubscribe, doUnmute, doUnsubscribe]);
    const toggleEventType = useCallback((eventType) => {
        const nextEventTypes = (() => {
            if (selectedEventTypes.includes(eventType)) {
                if (selectedEventTypes.length === 1)
                    return selectedEventTypes;
                return selectedEventTypes.filter((value) => value !== eventType);
            }
            return orderEventTypes([...selectedEventTypes, eventType], targetType);
        })();
        setSelectedEventTypes(nextEventTypes);
        if (isWatching) {
            void doSubscribe(isSubtree, { eventTypes: nextEventTypes });
        }
    }, [doSubscribe, isSubtree, isWatching, selectedEventTypes, targetType]);
    const toggleCurrentLanguageOnly = useCallback(() => {
        const nextCurrentLanguageOnly = !currentLanguageOnly;
        setCurrentLanguageOnly(nextCurrentLanguageOnly);
        if (isWatching) {
            void doSubscribe(isSubtree, {
                currentLanguageOnly: nextCurrentLanguageOnly,
            });
        }
    }, [currentLanguageOnly, doSubscribe, isSubtree, isWatching]);
    const iconCls = "size-3.5";
    const stateIcon = isSubtree ? (_jsx(FolderTree, { strokeWidth: 1, className: iconCls })) : (_jsx(Eye, { className: iconCls, strokeWidth: 1 }));
    const toggleTooltip = isWatching
        ? isSubtree
            ? "Watching subtree (click to unwatch)"
            : "Watching (click to unwatch)"
        : "Watch";
    const activeButtonClass = isWatching
        ? "bg-neutral-grey-5 text-neutral-grey-100 hover:bg-neutral-grey-5"
        : undefined;
    return {
        activeButtonClass,
        current,
        currentLanguage,
        currentLanguageOnly,
        disabled,
        doSubscribe,
        doUnsubscribe,
        isSubtree,
        isWatching,
        languageOnlyLabel,
        selectedEventTypes,
        stateIcon,
        toggleCurrentLanguageOnly,
        toggleEventType,
        toggleSimple,
        toggleTooltip,
        watchEventOptions,
    };
}
function WatchToggleRow({ icon: Icon, checked, children, ...switchProps }) {
    return (_jsxs("label", { className: "flex h-9 cursor-pointer items-center gap-2.5 select-none", children: [_jsx("span", { className: cn("flex size-7 shrink-0 items-center justify-center rounded-md", checked && "bg-neutral-grey-5"), children: _jsx(Icon, { className: "text-neutral-grey-100 size-4" }) }), _jsx("span", { className: "text-neutral-grey-100 min-w-0 flex-1 truncate text-sm", children: children }), _jsx(Switch, { checked: checked, className: "data-[state=checked]:bg-neutral-grey-100 data-[state=unchecked]:bg-neutral-grey-15 h-[20px] w-[38px] shrink-0 p-[2px] shadow-none [&_[data-slot=switch-thumb]]:size-[16px] [&_[data-slot=switch-thumb]]:data-[state=checked]:translate-x-[18px]", ...switchProps })] }));
}
export function WatchMenuSection(props) {
    const { targetType, targetId, className } = props;
    const { currentLanguage, currentLanguageOnly, disabled, doSubscribe, doUnsubscribe, isSubtree, isWatching, languageOnlyLabel, selectedEventTypes, toggleCurrentLanguageOnly, toggleEventType, toggleSimple, watchEventOptions, } = useWatchControls(props);
    const sectionTestId = targetType === "item" || targetType === "project"
        ? `watch-button-${targetType}-${targetId}`
        : undefined;
    return (_jsxs("div", { id: "watch-button-controls", className: cn("border-border-default border-t", className), "data-testid": sectionTestId, children: [_jsxs("div", { className: "px-4 py-3", children: [_jsx("div", { className: "text-neutral-grey-50 mb-1 text-xs", children: "Watch" }), targetType === "item" ? (_jsxs(_Fragment, { children: [_jsx(WatchToggleRow, { icon: Box, checked: isWatching, disabled: disabled, onCheckedChange: (checked) => void (checked ? doSubscribe(false) : doUnsubscribe()), "data-testid": `watch-button-${targetType}-${targetId}-watch-item`, children: "Item" }), _jsx(WatchToggleRow, { icon: Network, checked: isWatching && isSubtree, disabled: disabled, onCheckedChange: (checked) => void doSubscribe(checked), "data-testid": `watch-button-${targetType}-${targetId}-watch-subtree`, children: "Subtree" }), _jsx(WatchToggleRow, { icon: Flag, checked: currentLanguageOnly, disabled: !currentLanguage || disabled, onCheckedChange: () => toggleCurrentLanguageOnly(), "data-testid": `watch-button-${targetType}-${targetId}-current-language-only`, children: languageOnlyLabel })] })) : targetType === "project" ? (_jsx(WatchToggleRow, { icon: Eye, checked: isWatching, disabled: disabled, onCheckedChange: (checked) => void (checked ? doSubscribe(false) : doUnsubscribe()), "data-testid": `watch-button-${targetType}-${targetId}-watch-project`, children: "Project" })) : (_jsx(WatchToggleRow, { icon: Eye, checked: isWatching, disabled: disabled, onCheckedChange: () => void toggleSimple(), "data-testid": `watch-button-${targetType}-${targetId}`, children: targetType === "review" ? "Review" : "Agent run" }))] }), watchEventOptions.length > 0 ? (_jsxs("div", { className: "border-border-default border-t px-4 py-3", children: [_jsx("div", { className: "text-neutral-grey-50 mb-1 text-xs", children: "Alert me about" }), watchEventOptions.map((option) => (_jsx(WatchToggleRow, { icon: option.icon, checked: selectedEventTypes.includes(option.eventType), disabled: disabled, onCheckedChange: () => toggleEventType(option.eventType), "data-testid": `watch-button-${targetType}-${targetId}-event-${option.eventType}`, children: option.label }, option.eventType)))] })) : null] }));
}
export function WatchButton(props) {
    const { targetType, targetId, className } = props;
    const { activeButtonClass, currentLanguage, currentLanguageOnly, disabled, doSubscribe, doUnsubscribe, isSubtree, isWatching, languageOnlyLabel, selectedEventTypes, stateIcon, toggleCurrentLanguageOnly, toggleEventType, toggleSimple, toggleTooltip, watchEventOptions, } = useWatchControls(props);
    const menuTooltip = "Watch options";
    if (targetType === "item" || targetType === "project") {
        const watchActionLabel = targetType === "item" ? "Watch item" : "Watch project";
        const watchActionTestId = targetType === "item"
            ? `watch-button-${targetType}-${targetId}-watch-item`
            : `watch-button-${targetType}-${targetId}-watch-project`;
        return (_jsxs("div", { id: "watch-button-controls", className: cn("inline-flex items-center", className), "data-testid": targetType === "item"
                ? `watch-button-${targetType}-${targetId}`
                : undefined, children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "iconSm", className: cn("rounded-r-none border-r-0", activeButtonClass), disabled: disabled, onClick: () => void toggleSimple(), id: "watch-button-toggle", "data-testid": targetType === "item"
                                    ? `watch-button-${targetType}-${targetId}-toggle`
                                    : `watch-button-${targetType}-${targetId}`, "aria-label": toggleTooltip, children: stateIcon }) }), _jsx(TooltipContent, { children: toggleTooltip })] }), _jsxs(DropdownMenu, { children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "iconSm", className: cn("w-5 min-w-0 rounded-l-none px-0", activeButtonClass), disabled: disabled, id: "watch-button-menu-trigger", "data-testid": `watch-button-${targetType}-${targetId}-menu-trigger`, "aria-label": menuTooltip, children: _jsx(ChevronDown, { strokeWidth: 1, className: "size-3" }) }) }) }), _jsx(TooltipContent, { children: menuTooltip })] }), _jsxs(DropdownMenuContent, { align: "end", className: "min-w-[160px]", children: [_jsxs(DropdownMenuItem, { onClick: () => void doSubscribe(false), "data-testid": watchActionTestId, className: cn("gap-2", isWatching &&
                                        !isSubtree &&
                                        "bg-highlight-10 text-accent-foreground hover:bg-highlight-10/90"), children: [_jsx(Eye, { strokeWidth: 1, className: "size-3.5" }), watchActionLabel, isWatching && !isSubtree && (_jsx(Check, { strokeWidth: 1, className: "text-feedback-green ml-auto size-3.5" }))] }), targetType === "item" && (_jsxs(_Fragment, { children: [_jsxs(DropdownMenuItem, { onClick: () => void doSubscribe(true), "data-testid": `watch-button-${targetType}-${targetId}-watch-subtree`, className: cn("gap-2", isWatching &&
                                                isSubtree &&
                                                "bg-highlight-10 text-accent-foreground hover:bg-highlight-10/90"), children: [_jsx(FolderTree, { strokeWidth: 1, className: "size-3.5" }), "Watch subtree", isWatching && isSubtree && (_jsx(Check, { strokeWidth: 1, className: "text-feedback-green ml-auto size-3.5" }))] }), _jsxs(DropdownMenuItem, { disabled: !currentLanguage, onClick: () => toggleCurrentLanguageOnly(), onSelect: (event) => event.preventDefault(), "data-testid": `watch-button-${targetType}-${targetId}-current-language-only`, className: cn("gap-2 text-xs", currentLanguageOnly &&
                                                "bg-highlight-10 text-accent-foreground hover:bg-highlight-10/90"), children: [_jsx(Flag, { strokeWidth: 1, className: "size-3.5" }), languageOnlyLabel, currentLanguageOnly && (_jsx(Check, { strokeWidth: 1, className: "text-feedback-green ml-auto size-3.5" }))] })] })), _jsx(DropdownMenuSeparator, {}), watchEventOptions.map((option) => {
                                    const selected = selectedEventTypes.includes(option.eventType);
                                    const Icon = option.icon;
                                    return (_jsxs(DropdownMenuItem, { onClick: () => toggleEventType(option.eventType), onSelect: (event) => event.preventDefault(), "data-testid": `watch-button-${targetType}-${targetId}-event-${option.eventType}`, className: cn("gap-2 text-xs", selected &&
                                            "bg-highlight-10 text-accent-foreground hover:bg-highlight-10/90"), children: [_jsx(Icon, { className: "size-3.5" }), option.label, selected && (_jsx(Check, { strokeWidth: 1, className: "text-feedback-green ml-auto size-3.5" }))] }, option.eventType));
                                }), isWatching && (_jsxs(_Fragment, { children: [_jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuItem, { onClick: () => void doUnsubscribe(), className: "gap-2", variant: "destructive", "data-testid": `watch-button-${targetType}-${targetId}-unwatch`, children: [_jsx(X, { strokeWidth: 1, className: "size-3.5" }), "Unwatch"] })] }))] })] })] }));
    }
    return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "iconSm", className: cn(className, activeButtonClass), disabled: disabled, onClick: () => void toggleSimple(), "data-testid": `watch-button-${targetType}-${targetId}`, "aria-label": toggleTooltip, children: stateIcon }) }), _jsx(TooltipContent, { children: toggleTooltip })] }));
}
//# sourceMappingURL=WatchButton.js.map