"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StackTypeControlGroup = void 0;
const tslib_1 = require("tslib");
const react_1 = tslib_1.__importDefault(require("react"));
const react_core_1 = require("@patternfly/react-core");
const formik_1 = require("formik");
const ip_address_1 = require("ip-address");
const types_1 = require("../../../types");
const ui_1 = require("../../ui");
const config_1 = require("../../../config");
const formik_2 = require("../../ui/formik");
const ui_2 = require("../../ui");
const use_translation_wrapper_1 = require("../../../hooks/use-translation-wrapper");
const reorderNetworks_1 = require("./reorderNetworks");
const hasDualStackConfigurationChanged = (clusterNetworks, serviceNetworks, cidrIPv6, values) => {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
    return clusterNetworks &&
        serviceNetworks &&
        ((((_a = values.machineNetworks) === null || _a === void 0 ? void 0 : _a[1]) && values.machineNetworks[1].cidr !== cidrIPv6) ||
            (((_b = values.clusterNetworks) === null || _b === void 0 ? void 0 : _b[1]) && values.clusterNetworks[1].cidr !== ((_c = clusterNetworks[1]) === null || _c === void 0 ? void 0 : _c.cidr)) ||
            (((_d = values.clusterNetworks) === null || _d === void 0 ? void 0 : _d[1]) &&
                values.clusterNetworks[1].hostPrefix !== ((_e = clusterNetworks[1]) === null || _e === void 0 ? void 0 : _e.hostPrefix)) ||
            (((_f = values.serviceNetworks) === null || _f === void 0 ? void 0 : _f[1]) && values.serviceNetworks[1].cidr !== ((_g = serviceNetworks[1]) === null || _g === void 0 ? void 0 : _g.cidr)) ||
            ((_j = (_h = values.apiVips) === null || _h === void 0 ? void 0 : _h[1]) === null || _j === void 0 ? void 0 : _j.ip) ||
            ((_l = (_k = values.ingressVips) === null || _k === void 0 ? void 0 : _k[1]) === null || _l === void 0 ? void 0 : _l.ip));
};
const StackTypeControlGroup = ({ clusterId, isDualStackSelectable, hostSubnets, defaultNetworkValues, isViewerMode = false, allowSingleStackIPv6 = false, }) => {
    var _a, _b;
    const { t } = (0, use_translation_wrapper_1.useTranslation)();
    const { setFieldValue, values, validateForm } = (0, formik_1.useFormikContext)();
    const [openConfirmModal, setConfirmModal] = react_1.default.useState(false);
    const singleStackLabel = allowSingleStackIPv6 ? t('ai:Single stack') : t('ai:IPv4');
    const IPv6Subnets = hostSubnets.filter((subnet) => ip_address_1.Address6.isValid(subnet.subnet));
    const cidrIPv6 = IPv6Subnets.length >= 1 ? IPv6Subnets[0].subnet : config_1.NO_SUBNET_SET;
    const shouldSetSingleStack = !isViewerMode && !isDualStackSelectable && values.stackType === config_1.DUAL_STACK;
    const setSingleStack = react_1.default.useCallback(() => {
        var _a, _b;
        setFieldValue('stackType', config_1.SINGLE_STACK);
        // Determine whether the first machine network is IPv4
        const firstNetwork = (_a = values.machineNetworks) === null || _a === void 0 ? void 0 : _a[0];
        const isFirstIPv4 = Boolean((firstNetwork === null || firstNetwork === void 0 ? void 0 : firstNetwork.cidr) && ip_address_1.Address4.isValid(firstNetwork.cidr));
        if (values.machineNetworks && ((_b = values.machineNetworks) === null || _b === void 0 ? void 0 : _b.length) >= 2) {
            // For single-stack IPv4, prefer IPv4 machine network
            if (isFirstIPv4) {
                // Keep the first network if it's IPv4
                setFieldValue('machineNetworks', [firstNetwork]);
            }
            else {
                // If first is IPv6, look for IPv4 network or set empty for auto-selection
                const ipv4Network = values.machineNetworks.find((network) => network.cidr && ip_address_1.Address4.isValid(network.cidr));
                if (ipv4Network) {
                    setFieldValue('machineNetworks', [ipv4Network]);
                }
                else {
                    // No IPv4 network found, set empty for auto-selection
                    setFieldValue('machineNetworks', []);
                }
            }
        }
        // Set cluster/service to IPv4 defaults when switching to single-stack
        if (values.clusterNetworks && values.clusterNetworks.length >= 1) {
            const defaultCluster = defaultNetworkValues.clusterNetworksIpv4 && defaultNetworkValues.clusterNetworksIpv4[0];
            const firstCluster = values.clusterNetworks[0];
            const ipv4Cluster = defaultCluster
                ? {
                    cidr: defaultCluster.cidr,
                    hostPrefix: defaultCluster.hostPrefix,
                    clusterId: firstCluster.clusterId, // ← Preserve clusterId from original network
                }
                : {
                    cidr: '',
                    hostPrefix: '',
                    clusterId: clusterId, // ← Use current clusterId
                };
            setFieldValue('clusterNetworks', [ipv4Cluster]);
        }
        if (values.serviceNetworks && values.serviceNetworks.length >= 1) {
            const defaultService = defaultNetworkValues.serviceNetworksIpv4 && defaultNetworkValues.serviceNetworksIpv4[0];
            const firstService = values.serviceNetworks[0];
            const ipv4Service = defaultService
                ? {
                    cidr: defaultService.cidr,
                    clusterId: firstService.clusterId, // ← Preserve clusterId from original network
                }
                : {
                    cidr: '',
                    clusterId: clusterId, // ← Use current clusterId
                };
            setFieldValue('serviceNetworks', [ipv4Service]);
        }
        // Keep only IPv4 VIPs when switching to single-stack (unless DHCP allocation is used)
        if (!values.vipDhcpAllocation) {
            const pruneVips = (vips) => {
                if (!vips || vips.length === 0)
                    return [];
                // Choose which index to keep based on whether the first network is IPv4
                const keepIndex = isFirstIPv4 ? 0 : 1;
                const chosen = vips[keepIndex];
                return chosen && chosen.ip
                    ? [{ ip: chosen.ip, clusterId: chosen.clusterId || clusterId }]
                    : [];
            };
            setFieldValue('apiVips', pruneVips(values.apiVips));
            setFieldValue('ingressVips', pruneVips(values.ingressVips));
        }
        void validateForm();
    }, [
        setFieldValue,
        validateForm,
        clusterId,
        defaultNetworkValues.clusterNetworksIpv4,
        defaultNetworkValues.serviceNetworksIpv4,
        values.clusterNetworks,
        values.machineNetworks,
        values.serviceNetworks,
        values.apiVips,
        values.ingressVips,
        values.vipDhcpAllocation,
    ]);
    const setDualStack = () => {
        var _a, _b, _c, _d, _e, _f, _g;
        setFieldValue('stackType', config_1.DUAL_STACK);
        setFieldValue('vipDhcpAllocation', false);
        if (values.networkType === types_1.NETWORK_TYPE_SDN) {
            setFieldValue('networkType', types_1.NETWORK_TYPE_OVN);
        }
        if (values.machineNetworks && ((_a = values.machineNetworks) === null || _a === void 0 ? void 0 : _a.length) < 2) {
            // Ensure IPv4 is primary when switching to dual-stack
            const firstNetwork = values.machineNetworks[0];
            const isFirstIPv6 = (firstNetwork === null || firstNetwork === void 0 ? void 0 : firstNetwork.cidr) && ip_address_1.Address6.isValid(firstNetwork.cidr);
            if (isFirstIPv6) {
                // If first network is IPv6, make IPv4 primary and IPv6 secondary
                const IPv4Subnets = hostSubnets.filter((subnet) => ip_address_1.Address4.isValid(subnet.subnet));
                const cidrIPv4 = IPv4Subnets.length >= 1 ? IPv4Subnets[0].subnet : config_1.NO_SUBNET_SET;
                setFieldValue('machineNetworks', [
                    { cidr: cidrIPv4, clusterId: clusterId },
                    { cidr: firstNetwork.cidr, clusterId: clusterId },
                ], false);
            }
            else {
                // If first network is IPv4, add IPv6 as secondary
                setFieldValue('machineNetworks', [...values.machineNetworks, { cidr: cidrIPv6, clusterId: clusterId }], false);
            }
        }
        if (values.clusterNetworks && ((_b = values.clusterNetworks) === null || _b === void 0 ? void 0 : _b.length) < 2) {
            const firstClusterCidr = (_c = values.clusterNetworks[0]) === null || _c === void 0 ? void 0 : _c.cidr;
            const isPrimaryIPv6 = firstClusterCidr && ip_address_1.Address6.isValid(firstClusterCidr);
            const missingFamilyNetworkDefault = (_d = defaultNetworkValues.clusterNetworksDualstack) === null || _d === void 0 ? void 0 : _d[isPrimaryIPv6 ? 0 : 1];
            const secondClusterNetwork = missingFamilyNetworkDefault !== null && missingFamilyNetworkDefault !== void 0 ? missingFamilyNetworkDefault : {
                cidr: '',
                hostPrefix: '',
                clusterId: clusterId,
            };
            setFieldValue('clusterNetworks', [...values.clusterNetworks, secondClusterNetwork], false);
        }
        if (values.serviceNetworks && ((_e = values.serviceNetworks) === null || _e === void 0 ? void 0 : _e.length) < 2) {
            const firstServiceCidr = (_f = values.serviceNetworks[0]) === null || _f === void 0 ? void 0 : _f.cidr;
            const isPrimaryIPv6 = firstServiceCidr && ip_address_1.Address6.isValid(firstServiceCidr);
            const missingFamilyNetworkDefault = (_g = defaultNetworkValues.serviceNetworksDualstack) === null || _g === void 0 ? void 0 : _g[isPrimaryIPv6 ? 0 : 1];
            const secondServiceNetwork = missingFamilyNetworkDefault !== null && missingFamilyNetworkDefault !== void 0 ? missingFamilyNetworkDefault : {
                cidr: '',
                clusterId: clusterId,
            };
            setFieldValue('serviceNetworks', [...values.serviceNetworks, secondServiceNetwork], false);
        }
        // Initialize VIPs for dual-stack
        if (values.apiVips && values.apiVips.length < 2) {
            setFieldValue('apiVips', [values.apiVips[0] || { ip: '', clusterId: clusterId }, { ip: '', clusterId: clusterId }], false);
        }
        if (values.ingressVips && values.ingressVips.length < 2) {
            setFieldValue('ingressVips', [
                values.ingressVips[0] || { ip: '', clusterId: clusterId },
                { ip: '', clusterId: clusterId },
            ], false);
        }
    };
    // Ensure cluster/service networks ordering matches the new primary family
    const primaryCidr = (_b = (_a = values.machineNetworks) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.cidr;
    react_1.default.useEffect(() => {
        if (isViewerMode) {
            return;
        }
        (0, reorderNetworks_1.reorderNetworksByCurrentPrimary)(values, setFieldValue);
    }, [
        isViewerMode,
        setFieldValue,
        values,
        values.stackType,
        primaryCidr,
        values.clusterNetworks,
        values.serviceNetworks,
    ]);
    const setStackType = (e) => {
        if (e.target.value === config_1.DUAL_STACK) {
            setDualStack();
        }
        else if (hasDualStackConfigurationChanged(defaultNetworkValues.clusterNetworksDualstack || [], defaultNetworkValues.serviceNetworksDualstack || [], cidrIPv6, values)) {
            setConfirmModal(true);
        }
        else {
            setSingleStack();
        }
    };
    react_1.default.useEffect(() => {
        if (shouldSetSingleStack) {
            setSingleStack();
        }
    }, [shouldSetSingleStack, setSingleStack]);
    return (react_1.default.createElement(react_1.default.Fragment, null,
        react_1.default.createElement(react_core_1.FormGroup, { label: "Networking stack type", fieldId: (0, ui_1.getFieldId)('stackType', 'radio'), onChange: setStackType, isInline: true },
            react_1.default.createElement(react_core_1.Split, null,
                react_1.default.createElement(react_core_1.SplitItem, null,
                    react_1.default.createElement(formik_2.RadioField, { name: 'stackType', value: config_1.SINGLE_STACK, isDisabled: !isDualStackSelectable || isViewerMode, label: `${singleStackLabel}\u00A0` })),
                react_1.default.createElement(react_core_1.SplitItem, null,
                    react_1.default.createElement(ui_2.PopoverIcon, { bodyContent: allowSingleStackIPv6
                            ? t('ai:Select a single address family (IPv4 or IPv6) for your machine network.')
                            : t('ai:Select this when your hosts are using only IPv4.'), buttonStyle: { top: '-4px' } }))),
            react_1.default.createElement(react_core_1.Split, null,
                react_1.default.createElement(react_core_1.SplitItem, null,
                    react_1.default.createElement(react_core_1.Tooltip, { content: 'Dual-stack is only available when your hosts are using IPV4 together with IPV6.', hidden: isDualStackSelectable },
                        react_1.default.createElement(formik_2.RadioField, { name: 'stackType', value: config_1.DUAL_STACK, isDisabled: !isDualStackSelectable || isViewerMode, label: "Dual-stack\u00A0" }))),
                react_1.default.createElement(react_core_1.SplitItem, null,
                    react_1.default.createElement(ui_2.PopoverIcon, { bodyContent: "Select dual-stack when your hosts are using IPV4 together with IPV6.", buttonStyle: { top: '-4px' } })))),
        openConfirmModal && (react_1.default.createElement(ui_2.ConfirmationModal, { title: 'Change stack type?', titleIconVariant: 'warning', confirmationButtonText: 'Change', confirmationButtonVariant: react_core_1.ButtonVariant.primary, content: react_1.default.createElement("p", null, "All data and configuration done for 'Dual-stack' will be lost."), onClose: () => {
                setConfirmModal(false);
                setDualStack();
            }, onConfirm: () => {
                setConfirmModal(false);
                setSingleStack();
            } }))));
};
exports.StackTypeControlGroup = StackTypeControlGroup;
//# sourceMappingURL=StackTypeControlGroup.js.map