"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useAgentsFilter = exports.filterHosts = exports.useAgentsTable = exports.canUnbindAgent = exports.canChangeHostname = exports.canEditAgent = exports.canEditBMH = void 0;
const tslib_1 = require("tslib");
const React = tslib_1.__importStar(require("react"));
const countBy_1 = tslib_1.__importDefault(require("lodash-es/countBy"));
const tableUtils_1 = require("../../../common/components/hosts/tableUtils");
const helpers_1 = require("../helpers");
const helpers_2 = require("../ClusterDeployment/helpers");
const common_1 = require("../common");
const status_1 = require("../helpers/status");
const utils_1 = require("../../../common/components/hosts/utils");
const agentStatus_1 = require("../helpers/agentStatus");
const noop_js_1 = tslib_1.__importDefault(require("lodash-es/noop.js"));
const use_translation_wrapper_1 = require("../../../common/hooks/use-translation-wrapper");
const canEditBMH = (bmh, t) => {
    const canEdit = ['deprovisioning', 'pending', 'registering'].includes((0, status_1.getBMHStatusKey)(bmh) || '');
    return [
        canEdit,
        canEdit
            ? undefined
            : t('ai:Bare metal host cannot be edited. Remove this host and add it again if a change is needed.'),
    ];
};
exports.canEditBMH = canEditBMH;
const canEditAgent = (agent, agentStatuses, t) => {
    const enabled = (0, status_1.getAgentStatus)(agent, agentStatuses).status.category !== 'Installation related';
    return [
        enabled,
        enabled
            ? undefined
            : t('ai:Hostname cannot be edited while host is either installed or being installed.'),
    ];
};
exports.canEditAgent = canEditAgent;
const canChangeHostname = (agents, agentStatuses, bareMetalHosts, t) => (h) => {
    const agent = agents.find((a) => { var _a; return ((_a = a.metadata) === null || _a === void 0 ? void 0 : _a.uid) === h.id; });
    if (agent) {
        return (0, exports.canEditAgent)(agent, agentStatuses, t);
    }
    const bmh = bareMetalHosts.find((bmh) => { var _a; return ((_a = bmh.metadata) === null || _a === void 0 ? void 0 : _a.uid) === h.id; });
    if (bmh) {
        return (0, exports.canEditBMH)(bmh, t);
    }
    return [true, undefined];
};
exports.canChangeHostname = canChangeHostname;
const canUnbindAgent = (agentClusterInstalls, agent, t) => {
    var _a, _b, _c, _d, _e, _f, _g;
    if (!((_a = agent === null || agent === void 0 ? void 0 : agent.spec.clusterDeploymentName) === null || _a === void 0 ? void 0 : _a.name)) {
        return [false, t('ai:The agent is not bound to a cluster.')];
    }
    const statusKey = (0, status_1.getAgentStatusKey)(agent);
    if (['installed', 'error', 'cancelled'].includes(statusKey) &&
        (((_b = agent.status) === null || _b === void 0 ? void 0 : _b.role) === 'master' || ((_c = agent.status) === null || _c === void 0 ? void 0 : _c.role) === 'bootstrap')) {
        return [
            false,
            t('ai:It is not possible to remove control plane node from an installed cluster.'),
        ];
    }
    if (agentClusterInstalls) {
        const agentClusterInstall = (0, helpers_1.getAgentClusterInstallOfAgent)(agentClusterInstalls, agent);
        if (agentClusterInstall) {
            if ((0, helpers_2.isInstallationInProgress)(agentClusterInstall)) {
                return [
                    false,
                    t('ai:It is not possible to remove a node from a cluster during installation.'),
                ];
            }
        }
    }
    if (!((_e = (_d = agent.metadata) === null || _d === void 0 ? void 0 : _d.labels) === null || _e === void 0 ? void 0 : _e.hasOwnProperty(common_1.AGENT_BMH_NAME_LABEL_KEY)) &&
        ((_g = (_f = agent.metadata) === null || _f === void 0 ? void 0 : _f.labels) === null || _g === void 0 ? void 0 : _g.hasOwnProperty(common_1.INFRAENV_GENERATED_AI_FLOW)) &&
        !!agent.spec.clusterDeploymentName) {
        return [false, t('ai:It is not possible to remove this node from the cluster.')];
    }
    return [true, undefined];
};
exports.canUnbindAgent = canUnbindAgent;
const canDeleteAgent = (agent, agentStatuses, t) => {
    const enabled = (0, status_1.getAgentStatus)(agent, agentStatuses).status.category !== 'Installation related';
    return [
        enabled,
        enabled
            ? undefined
            : t('ai:Host cannot be deleted while host is either installed or being installed.'),
    ];
};
const useAgentsTable = ({ agents, bmhs, infraEnv, agentClusterInstalls }, tableActions) => {
    const { onEditHost, onDeleteHost, onEditRole, onSelect, onEditBMH, onUnbindHost, onSetInstallationDiskId, } = tableActions || {};
    const { t } = (0, use_translation_wrapper_1.useTranslation)();
    const agentStatuses = (0, agentStatus_1.agentStatus)(t);
    const [hosts, actions] = React.useMemo(() => [
        (0, helpers_1.getAIHosts)(agents, bmhs, infraEnv),
        {
            onEditHost: onEditHost
                ? (host) => {
                    const agent = agents.find((a) => { var _a; return ((_a = a.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
                    if (agent) {
                        return onEditHost(agent);
                    }
                    const bmh = bmhs === null || bmhs === void 0 ? void 0 : bmhs.find((bmh) => { var _a; return ((_a = bmh.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
                    if (bmh && onEditBMH) {
                        return onEditBMH(bmh);
                    }
                    return noop_js_1.default;
                }
                : undefined,
            canEditHost: (host) => {
                const agent = agents.find((a) => { var _a; return ((_a = a.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
                if (!agent) {
                    return false;
                }
                return (0, exports.canEditAgent)(agent, agentStatuses, t);
            },
            onDeleteHost: onDeleteHost
                ? (host) => {
                    const agent = agents.find((a) => { var _a; return ((_a = a.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
                    const bmh = bmhs === null || bmhs === void 0 ? void 0 : bmhs.find((a) => { var _a; return ((_a = a.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
                    return onDeleteHost(agent, bmh);
                }
                : undefined,
            canDelete: (host) => {
                const agent = agents.find((a) => { var _a; return ((_a = a.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
                const bmh = bmhs === null || bmhs === void 0 ? void 0 : bmhs.find((a) => { var _a; return ((_a = a.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
                if (agent) {
                    return canDeleteAgent(agent, agentStatuses, t);
                }
                else if (bmh) {
                    return [true, undefined];
                }
                return [false, t('ai:Host not found')];
            },
            onEditRole: onEditRole
                ? (host, role) => {
                    const agent = agents.find((a) => { var _a; return ((_a = a.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
                    return agent ? onEditRole(agent, role) : Promise.resolve(agent);
                }
                : undefined,
            canEditRole: () => !!onEditRole,
            onDiskRole: onSetInstallationDiskId
                ? (hostId, diskId) => {
                    const agent = agents.find((a) => { var _a; return ((_a = a.metadata) === null || _a === void 0 ? void 0 : _a.uid) === hostId; });
                    if (agent && diskId) {
                        return onSetInstallationDiskId(agent, diskId);
                    }
                    return Promise.resolve(agent);
                }
                : undefined,
            canEditDisks: () => !!onSetInstallationDiskId,
            onSelect: onSelect
                ? (host, selected) => {
                    const agent = agents.find((a) => { var _a; return ((_a = a.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
                    return agent ? onSelect(agent, selected) : noop_js_1.default;
                }
                : undefined,
            onEditBMH: onEditBMH
                ? (host) => {
                    const bmh = bmhs === null || bmhs === void 0 ? void 0 : bmhs.find((h) => { var _a; return ((_a = h.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
                    return bmh ? onEditBMH(bmh) : noop_js_1.default;
                }
                : undefined,
            canEditBMH: (host) => {
                const bmh = bmhs === null || bmhs === void 0 ? void 0 : bmhs.find((h) => { var _a; return ((_a = h.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
                if (!bmh) {
                    return [false, t('ai:Bare metal host not found')];
                }
                return (0, exports.canEditBMH)(bmh, t);
            },
            onUnbindHost: onUnbindHost
                ? (host) => {
                    const agent = agents.find((a) => { var _a; return ((_a = a.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
                    return agent ? onUnbindHost(agent) : noop_js_1.default;
                }
                : undefined,
            canUnbindHost: (host) => {
                const agent = agents.find((a) => { var _a; return ((_a = a.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
                if (agent) {
                    return (0, exports.canUnbindAgent)(agentClusterInstalls, agent, t);
                }
                const bmh = bmhs === null || bmhs === void 0 ? void 0 : bmhs.find((bmh) => { var _a; return ((_a = bmh.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
                if (bmh) {
                    return [false, t('ai:Bare metal host cannot be removed from cluster.')];
                }
                return [false, t('ai:Host not found')];
            },
        },
    ], [
        agents,
        t,
        bmhs,
        infraEnv,
        onEditHost,
        onDeleteHost,
        onEditRole,
        onSetInstallationDiskId,
        onSelect,
        onEditBMH,
        onUnbindHost,
        agentStatuses,
        agentClusterInstalls,
    ]);
    const actionResolver = React.useMemo(() => (0, tableUtils_1.hostActionResolver)(Object.assign({ t }, actions)), [actions, t]);
    return [hosts, actions, actionResolver];
};
exports.useAgentsTable = useAgentsTable;
const filterByStatus = (hosts, agents, agentStatuses, bareMetalHosts, statusFilter) => {
    if (!(statusFilter === null || statusFilter === void 0 ? void 0 : statusFilter.length)) {
        return hosts;
    }
    const statusKeys = Object.keys(agentStatuses).filter((k) => statusFilter.includes(agentStatuses[k].title));
    return hosts.filter((h) => {
        const agent = agents.find((a) => { var _a; return ((_a = a.metadata) === null || _a === void 0 ? void 0 : _a.uid) === h.id; });
        if (!agent) {
            const bmh = bareMetalHosts.find((bmh) => { var _a; return ((_a = bmh.metadata) === null || _a === void 0 ? void 0 : _a.uid) === h.id; });
            if (!bmh) {
                return false;
            }
            return statusKeys.includes((0, status_1.getBMHStatusKey)(bmh) || '');
        }
        const { status } = (0, status_1.getAgentStatus)(agent, agentStatuses);
        return statusKeys.includes(status.key);
    });
};
const filterByLabels = (hosts, labelFilter) => {
    if (!labelFilter.length) {
        return hosts;
    }
    return hosts.filter((h) => {
        const labels = (0, utils_1.getHostLabels)(h);
        return labelFilter.some((l) => Object.entries(labels)
            .map(([key, value]) => `${key} = ${value}`)
            .includes(l));
    });
};
const filterHosts = (hosts, agents, agentStatuses, bareMetalHosts, hostnameFilter, statusFilter, labelFilter) => {
    const { hosts: byHostname, sorted } = (0, utils_1.filterByHostname)(hosts, hostnameFilter);
    const byStatus = filterByStatus(byHostname, agents, agentStatuses, bareMetalHosts, statusFilter);
    const byLabels = filterByLabels(byStatus, labelFilter);
    return { hosts: byLabels, sorted };
};
exports.filterHosts = filterHosts;
const getAllLabels = (hosts) => {
    const labelArray = hosts
        .map((host) => {
        const labels = (0, utils_1.getHostLabels)(host);
        return Object.entries(labels).map(([key, val]) => `${key} = ${val}`);
    })
        .flat()
        .sort();
    return (0, countBy_1.default)(labelArray);
};
const useAgentsFilter = ({ agents, agentStatuses, bmhs, bmhStatuses, hosts, }) => {
    const [hostnameFilter, setHostnameFilter] = React.useState();
    const [statusFilter, setStatusFilter] = React.useState([]);
    const [labelFilter, setLabelFilter] = React.useState([]);
    const statusCount = Object.keys(agentStatuses).reduce((acc, curr) => {
        acc[agentStatuses[curr].title] = 0;
        return acc;
    }, {});
    hosts.forEach((host) => {
        const agent = agents.find((a) => { var _a; return ((_a = a.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
        const bmh = bmhs.find((bmh) => { var _a; return ((_a = bmh.metadata) === null || _a === void 0 ? void 0 : _a.uid) === host.id; });
        if (agent) {
            const { status } = (0, status_1.getAgentStatus)(agent, agentStatuses);
            statusCount[status.title]++;
        }
        else if (bmh) {
            const { state } = (0, status_1.getBMHStatus)(bmh, bmhStatuses);
            statusCount[state.title]++;
        }
    });
    const hostLabels = getAllLabels(hosts);
    const { hosts: filteredHosts, sorted } = (0, exports.filterHosts)(hosts, agents, agentStatuses, bmhs, hostnameFilter, statusFilter, labelFilter);
    return {
        statusCount,
        hostnameFilter,
        setHostnameFilter,
        statusFilter,
        setStatusFilter,
        hostLabels,
        labelFilter,
        setLabelFilter,
        filteredHosts,
        sorted,
    };
};
exports.useAgentsFilter = useAgentsFilter;
//# sourceMappingURL=tableUtils.js.map