"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AvailableSubnetsControl = void 0;
const tslib_1 = require("tslib");
const react_1 = tslib_1.__importStar(require("react"));
const react_core_1 = require("@patternfly/react-core");
const formik_1 = require("formik");
const ip_address_1 = require("ip-address");
const config_1 = require("../../../config");
const utils_1 = require("../../../utils");
const use_translation_wrapper_1 = require("../../../hooks/use-translation-wrapper");
const SubnetsDropdown_1 = require("./SubnetsDropdown");
const reorderNetworks_1 = require("./reorderNetworks");
const subnetSort = (subA, subB) => subA.humanized.localeCompare(subB.humanized);
const useAutoSelectDefaultMachineNetworks = (autoSelectNetwork, setFieldValue, cidrV4, cidrV6, clusterId, isDualStack) => {
    (0, react_1.useEffect)(() => {
        if (autoSelectNetwork) {
            setFieldValue('machineNetworks', isDualStack
                ? [
                    { cidr: cidrV4, clusterId },
                    { cidr: cidrV6, clusterId },
                ]
                : [{ cidr: cidrV4, clusterId }], false);
        }
    }, [autoSelectNetwork, cidrV4, cidrV6, clusterId, isDualStack, setFieldValue]);
};
const AvailableSubnetsControl = ({ clusterId, hostSubnets, isRequired = false, isDisabled, openshiftVersion, isViewerMode = false, hosts, isMultiNodeCluster = true, allowSingleStackIPv6 = false, }) => {
    var _a, _b, _c;
    const { t } = (0, use_translation_wrapper_1.useTranslation)();
    const { values, errors, setFieldValue } = (0, formik_1.useFormikContext)();
    const isDualStack = values.stackType === config_1.DUAL_STACK;
    // Check if OCP version supports IPv6 as primary network
    const supportsIPv6Primary = openshiftVersion && (0, utils_1.isMajorMinorVersionEqualOrGreater)(openshiftVersion, '4.12');
    const IPv4Subnets = hostSubnets
        .filter((subnet) => ip_address_1.Address4.isValid(subnet.subnet))
        .sort(subnetSort);
    const IPv6Subnets = hostSubnets
        .filter((subnet) => ip_address_1.Address6.isValid(subnet.subnet))
        .sort(subnetSort);
    // For OCP >= 4.12, both networks can use either IPv4 or IPv6
    const allSubnets = supportsIPv6Primary
        ? [...IPv4Subnets, ...IPv6Subnets].sort(subnetSort)
        : IPv4Subnets;
    // For auto-selection, prefer IPv4 as primary (even for dual-stack)
    const cidrV4 = IPv4Subnets.length >= 1 ? IPv4Subnets[0].subnet : config_1.NO_SUBNET_SET;
    const cidrV6 = IPv6Subnets.length >= 1 ? IPv6Subnets[0].subnet : config_1.NO_SUBNET_SET;
    const hasEmptySelection = ((_a = values.machineNetworks) !== null && _a !== void 0 ? _a : []).length === 0;
    const autoSelectNetwork = !isViewerMode && hasEmptySelection;
    useAutoSelectDefaultMachineNetworks(autoSelectNetwork, setFieldValue, cidrV4, cidrV6, clusterId, isDualStack);
    // Ensure primary and secondary machine networks are not in the same stack (IPv4/IPv6).
    // If the user switches primary to the same address family as secondary, adjust secondary to the opposite family
    // (or clear it if no subnet is available).
    react_1.default.useEffect(() => {
        var _a, _b, _c, _d, _e, _f, _g, _h;
        if (!isDualStack) {
            return;
        }
        if (!values.machineNetworks || values.machineNetworks.length < 2) {
            return;
        }
        const first = ((_b = (_a = values.machineNetworks) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.cidr) || '';
        const second = ((_d = (_c = values.machineNetworks) === null || _c === void 0 ? void 0 : _c[1]) === null || _d === void 0 ? void 0 : _d.cidr) || '';
        if (!first || !second) {
            return;
        }
        const firstIsV4 = ip_address_1.Address4.isValid(first);
        const firstIsV6 = ip_address_1.Address6.isValid(first);
        const secondIsV4 = ip_address_1.Address4.isValid(second);
        const secondIsV6 = ip_address_1.Address6.isValid(second);
        // If both are the same family, force the secondary to the opposite family.
        if ((firstIsV4 && secondIsV4) || (firstIsV6 && secondIsV6)) {
            const replacement = firstIsV4
                ? (_f = (_e = IPv6Subnets[0]) === null || _e === void 0 ? void 0 : _e.subnet) !== null && _f !== void 0 ? _f : config_1.NO_SUBNET_SET
                : (_h = (_g = IPv4Subnets[0]) === null || _g === void 0 ? void 0 : _g.subnet) !== null && _h !== void 0 ? _h : config_1.NO_SUBNET_SET;
            if (replacement !== second) {
                setFieldValue('machineNetworks.1.cidr', replacement, false);
            }
        }
    }, [isDualStack, values.machineNetworks, IPv4Subnets, IPv6Subnets, setFieldValue]);
    // Helper text showing excluded hosts
    const getExcludedHostsAlert = react_1.default.useCallback((subnetCidr) => {
        if (!hosts || !isMultiNodeCluster || !subnetCidr) {
            return null;
        }
        const matchingSubnet = hostSubnets.find((hn) => hn.subnet === subnetCidr);
        if (!matchingSubnet) {
            return null;
        }
        const excludedHosts = hosts.filter((host) => !['disabled', 'disconnected'].includes(host.status) &&
            !matchingSubnet.hostIDs.includes(host.requestedHostname || '')) || [];
        // Workaround for bug in CIM backend. hostIDs are empty
        if (excludedHosts.length === 0 || !matchingSubnet.hostIDs.length) {
            return null;
        }
        const actionLinks = (react_1.default.createElement(react_core_1.Popover, { position: "right", bodyContent: react_1.default.createElement("ul", null, excludedHosts
                .sort((hostA, hostB) => { var _a; return ((_a = hostA.requestedHostname) === null || _a === void 0 ? void 0 : _a.localeCompare(hostB.requestedHostname || '')) || 0; })
                .map((host) => (react_1.default.createElement("li", { key: host.id }, host.requestedHostname || host.id)))), minWidth: "30rem", maxWidth: "50rem" },
            react_1.default.createElement(react_core_1.AlertActionLink, { id: "form-input-hostSubnet-field-helper-view-excluded" }, t('ai:View {{count}} affected host', {
                count: excludedHosts.length,
            }))));
        return (react_1.default.createElement(react_core_1.Alert, { title: t('ai:This subnet range is not available on all hosts'), variant: react_core_1.AlertVariant.warning, actionLinks: actionLinks, isInline: true }, t('ai:Hosts outside of this range will not be included in the new cluster.')));
    }, [hosts, isMultiNodeCluster, hostSubnets, t]);
    const primaryNetworkCidr = (_c = (_b = values.machineNetworks) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.cidr;
    const excludedHostsAlert = getExcludedHostsAlert(primaryNetworkCidr);
    const showSecondaryMachineNetwork = isDualStack && values.machineNetworks && values.machineNetworks.length > 1;
    // Determine available subnets for primary dropdown
    let primaryMachineSubnets;
    if ((isDualStack && supportsIPv6Primary) || (!isDualStack && allowSingleStackIPv6)) {
        primaryMachineSubnets = allSubnets;
    }
    else {
        primaryMachineSubnets = IPv4Subnets;
    }
    // Determine available subnets for secondary dropdown
    const secondaryMachineSubnets = react_1.default.useMemo(() => {
        if (supportsIPv6Primary) {
            // For OCP >= 4.12, smart filtering based on the other network's selection
            if (primaryNetworkCidr && ip_address_1.Address6.isValid(primaryNetworkCidr)) {
                // If first is IPv6, second should be IPv4
                return IPv4Subnets;
            }
            else if (primaryNetworkCidr && ip_address_1.Address4.isValid(primaryNetworkCidr)) {
                // If first is IPv4, second should be IPv6
                return IPv6Subnets;
            }
            else {
                // If first is not selected yet, show all subnets
                return allSubnets;
            }
        }
        else {
            // For older versions, second network is IPv6
            return IPv6Subnets;
        }
    }, [supportsIPv6Primary, primaryNetworkCidr, IPv4Subnets, IPv6Subnets, allSubnets]);
    return (react_1.default.createElement(react_1.default.Fragment, null,
        react_1.default.createElement(react_core_1.FormGroup, { label: "Machine network", labelInfo: isDualStack && 'Primary', fieldId: "machine-networks", isRequired: isRequired },
            react_1.default.createElement(formik_1.FieldArray, { name: "machineNetworks" }, () => (react_1.default.createElement(react_core_1.Stack, null,
                react_1.default.createElement(react_core_1.StackItem, null,
                    react_1.default.createElement(SubnetsDropdown_1.SubnetsDropdown, { name: "machineNetworks.0.cidr", machineSubnets: primaryMachineSubnets, isDisabled: isDisabled, onAfterSelect: (newSelection) => (0, reorderNetworks_1.reorderNetworksForPrimary)(newSelection, values, setFieldValue), "data-testid": "subnets-dropdown-toggle-primary" })))))),
        showSecondaryMachineNetwork && (react_1.default.createElement(react_core_1.FormGroup, { label: "Machine network", labelInfo: "Secondary", fieldId: "machine-networks-secondary", isRequired: isRequired },
            react_1.default.createElement(SubnetsDropdown_1.SubnetsDropdown, { name: "machineNetworks.1.cidr", machineSubnets: secondaryMachineSubnets, isDisabled: isDisabled, "data-testid": "subnets-dropdown-toggle-secondary" }))),
        react_1.default.createElement(react_1.default.Fragment, null,
            typeof errors.machineNetworks === 'string' && (react_1.default.createElement(react_core_1.Alert, { variant: react_core_1.AlertVariant.warning, title: errors.machineNetworks, isInline: true })),
            excludedHostsAlert)));
};
exports.AvailableSubnetsControl = AvailableSubnetsControl;
//# sourceMappingURL=AvailableSubnetsControl.js.map