import { detectOperatorFromValue, getOperatorOption, } from "../Dictionary/DictionaryFilterOperator";
import Icon, { SizeProp } from "../Icon/Icon";
import Includes from "../../../Types/BaseDatabase/Includes";
import IncludesAll from "../../../Types/BaseDatabase/IncludesAll";
import IncludesNone from "../../../Types/BaseDatabase/IncludesNone";
import StartsWith from "../../../Types/BaseDatabase/StartsWith";
import EndsWith from "../../../Types/BaseDatabase/EndsWith";
import NotContains from "../../../Types/BaseDatabase/NotContains";
import EqualTo from "../../../Types/BaseDatabase/EqualTo";
import NotEqual from "../../../Types/BaseDatabase/NotEqual";
import GreaterThan from "../../../Types/BaseDatabase/GreaterThan";
import LessThan from "../../../Types/BaseDatabase/LessThan";
import GreaterThanOrEqual from "../../../Types/BaseDatabase/GreaterThanOrEqual";
import LessThanOrEqual from "../../../Types/BaseDatabase/LessThanOrEqual";
import IsNull from "../../../Types/BaseDatabase/IsNull";
import NotNull from "../../../Types/BaseDatabase/NotNull";
import Button, { ButtonStyleType } from "../Button/Button";
import ErrorMessage from "../ErrorMessage/ErrorMessage";
import Modal, { ModalWidth } from "../Modal/Modal";
import FieldType from "../Types/FieldType";
import FilterViewerItem from "./FilterViewerItem";
import FiltersForm from "./FiltersForm";
import InBetween from "../../../Types/BaseDatabase/InBetween";
import Search from "../../../Types/BaseDatabase/Search";
import OneUptimeDate from "../../../Types/Date";
import IconProp from "../../../Types/Icon/IconProp";
import useTranslateValue from "../../Utils/Translation";
import React, { useEffect, useState } from "react";
const FilterComponent = (props) => {
    const { translateString } = useTranslateValue();
    const tx = (value) => {
        var _a, _b;
        return (_b = (_a = translateString(value)) !== null && _a !== void 0 ? _a : value) !== null && _b !== void 0 ? _b : "";
    };
    const [tempFilterDataForModal, setTempFilterDataForModal] = useState({});
    const changeFilterData = (filterData) => {
        var _a;
        setTempFilterDataForModal(filterData);
        (_a = props.onFilterChanged) === null || _a === void 0 ? void 0 : _a.call(props, filterData);
    };
    useEffect(() => {
        if (props.showFilterModal) {
            setTempFilterDataForModal(Object.assign({}, props.filterData));
        }
    }, [props.showFilterModal]);
    const formatJson = (json) => {
        /*
         * Ignore entries with empty key or empty value, and translate
         * operator wrappers into their display symbol so chips like
         * `host.name != prod-1` or `path contains api` render correctly.
         */
        const isMeaningfulEntry = (key, value) => {
            if (key.trim() === "" || value === undefined || value === null) {
                return false;
            }
            const detected = detectOperatorFromValue(value);
            const option = getOperatorOption(detected.operator);
            if (option.hidesValueInput) {
                return true;
            }
            return detected.rawValue.trim() !== "";
        };
        const visibleKeys = Object.keys(json).filter((key) => {
            return isMeaningfulEntry(key, json[key]);
        });
        return (React.createElement("div", { className: "flex space-x-2 -mt-1" }, visibleKeys.map((key, i) => {
            const rawValue = json[key];
            const detected = detectOperatorFromValue(rawValue);
            const option = getOperatorOption(detected.operator);
            let jsonText = detected.rawValue;
            if (typeof rawValue === "boolean") {
                jsonText = rawValue ? "True" : "False";
            }
            return (React.createElement("div", { key: i, className: "rounded-full h-7 bg-gray-100 text-gray-500 border-2 border-gray-200 p-1 pr-2 pl-2 text-xs" },
                React.createElement("span", { className: "font-medium" }, key),
                " ",
                React.createElement("span", null, option.symbol),
                !option.hidesValueInput && (React.createElement(React.Fragment, null,
                    " ",
                    React.createElement("span", { className: "font-medium" }, jsonText)))));
        })));
    };
    const translateFilterToText = (data) => {
        const filterTexts = [];
        for (const filter of data.filters) {
            filterTexts.push(translateFilterItemToText({
                filter: filter,
                filterData: data.filterData,
            }));
        }
        return filterTexts.filter((filterText) => {
            return filterText !== null;
        });
    };
    const translateFilterItemToText = (data) => {
        let filterText = React.createElement(React.Fragment, null);
        if (!data.filter.key) {
            return null;
        }
        if (data.filterData[data.filter.key] === undefined ||
            data.filterData[data.filter.key] === null) {
            return null;
        }
        if (data.filter.type === FieldType.Boolean) {
            filterText = (React.createElement("span", null,
                React.createElement("span", { className: "font-medium" }, tx(data.filter.title)),
                " ",
                tx("is"),
                " ",
                React.createElement("span", { className: "font-medium" }, data.filterData[data.filter.key] ? tx("Yes") : tx("No"))));
            return filterText;
        }
        if (data.filter.type === FieldType.Text ||
            data.filter.type === FieldType.Number ||
            data.filter.type === FieldType.Email ||
            data.filter.type === FieldType.Phone ||
            data.filter.type === FieldType.URL ||
            data.filter.type === FieldType.Hostname ||
            data.filter.type === FieldType.LongText ||
            data.filter.type === FieldType.Name ||
            data.filter.type === FieldType.Port ||
            data.filter.type === FieldType.ObjectID) {
            const key = data.filter.key;
            const value = data.filterData[key];
            const render = (verb, display) => {
                return (React.createElement("span", null,
                    React.createElement("span", { className: "font-medium" }, tx(data.filter.title)),
                    " ",
                    tx(verb),
                    " ",
                    React.createElement("span", { className: "font-medium" }, display)));
            };
            if (value instanceof IsNull) {
                return (React.createElement("span", null,
                    React.createElement("span", { className: "font-medium" }, tx(data.filter.title)),
                    " ",
                    tx("is empty")));
            }
            if (value instanceof NotNull) {
                return (React.createElement("span", null,
                    React.createElement("span", { className: "font-medium" }, tx(data.filter.title)),
                    " ",
                    tx("is not empty")));
            }
            if (value instanceof Search) {
                return render("contains", value.toString());
            }
            if (value instanceof NotContains) {
                return render("does not contain", value.toString());
            }
            if (value instanceof StartsWith) {
                return render("starts with", value.toString());
            }
            if (value instanceof EndsWith) {
                return render("ends with", value.toString());
            }
            if (value instanceof InBetween) {
                return render("is between", `${value.startValue} and ${value.endValue}`);
            }
            if (value instanceof GreaterThanOrEqual) {
                return render("is ≥", value.toString());
            }
            if (value instanceof LessThanOrEqual) {
                return render("is ≤", value.toString());
            }
            if (value instanceof GreaterThan) {
                return render("is greater than", value.toString());
            }
            if (value instanceof LessThan) {
                return render("is less than", value.toString());
            }
            if (value instanceof NotEqual) {
                return render("does not equal", value.toString());
            }
            if (value instanceof EqualTo) {
                return render("equals", value.toString());
            }
            if (value !== undefined && value !== null && value !== "") {
                return render("is", value.toString());
            }
            return null;
        }
        if (data.filter.type === FieldType.Date ||
            data.filter.type === FieldType.DateTime) {
            const key = data.filter.key;
            const value = data.filterData[key];
            const shouldOnlyShowDate = data.filter.type === FieldType.Date;
            const shouldShowSeconds = data.filter.type === FieldType.DateTime;
            const format = (d) => {
                return OneUptimeDate.getDateAsUserFriendlyLocalFormattedString(d, shouldOnlyShowDate, shouldShowSeconds);
            };
            const render = (verb, display) => {
                return (React.createElement("span", null,
                    React.createElement("span", { className: "font-medium" }, tx(data.filter.title)),
                    " ",
                    tx(verb),
                    " ",
                    React.createElement("span", { className: "font-medium" }, display)));
            };
            if (value instanceof IsNull) {
                return (React.createElement("span", null,
                    React.createElement("span", { className: "font-medium" }, tx(data.filter.title)),
                    " ",
                    tx("is empty")));
            }
            if (value instanceof NotNull) {
                return (React.createElement("span", null,
                    React.createElement("span", { className: "font-medium" }, tx(data.filter.title)),
                    " ",
                    tx("is not empty")));
            }
            if (value instanceof InBetween) {
                const start = value.startValue;
                const end = value.endValue;
                if (format(start) === format(end)) {
                    return render("is", format(start));
                }
                return render("is between", `${format(start)} and ${format(end)}`);
            }
            if (value instanceof GreaterThan) {
                return render("is after", format(value.value));
            }
            if (value instanceof LessThan) {
                return render("is before", format(value.value));
            }
            if (value instanceof EqualTo) {
                return render("is", format(value.value));
            }
            return null;
        }
        if (data.filter.type === FieldType.JSON) {
            const key = data.filter.key;
            const json = data.filterData[key];
            /*
             * Count only meaningful entries — empty key/value pairs aren't
             * real filters, and value-less operators (IsEmpty/IsNotEmpty) are
             * valid even with no value.
             */
            const nonEmptyEntryCount = Object.keys(json).filter((entryKey) => {
                const value = json[entryKey];
                if (entryKey.trim() === "" || value === undefined || value === null) {
                    return false;
                }
                const detected = detectOperatorFromValue(value);
                const option = getOperatorOption(detected.operator);
                if (option.hidesValueInput) {
                    return true;
                }
                return detected.rawValue.trim() !== "";
            }).length;
            if (nonEmptyEntryCount === 0) {
                return null;
            }
            const isPlural = nonEmptyEntryCount > 1;
            return (React.createElement("span", { className: "inline-flex items-center space-x-1" },
                React.createElement("span", { className: "font-medium" }, tx(data.filter.title)),
                React.createElement("span", null, isPlural ? tx("are") : tx("is")),
                React.createElement("span", { className: "font-medium" }, formatJson(json))));
        }
        if (data.filter.type === FieldType.Dropdown ||
            data.filter.type === FieldType.MultiSelectDropdown ||
            data.filter.type === FieldType.Entity ||
            data.filter.type === FieldType.EntityArray) {
            const key = data.filter.key;
            const rawValue = data.filterData[key];
            if (rawValue instanceof IsNull) {
                return (React.createElement("span", null,
                    React.createElement("span", { className: "font-medium" }, tx(data.filter.title)),
                    " ",
                    tx("is empty")));
            }
            if (rawValue instanceof NotNull) {
                return (React.createElement("span", null,
                    React.createElement("span", { className: "font-medium" }, tx(data.filter.title)),
                    " ",
                    tx("is not empty")));
            }
            let items = [];
            let matchMode = "any";
            if (rawValue instanceof IncludesAll) {
                items = rawValue.values;
                matchMode = "all";
            }
            else if (rawValue instanceof IncludesNone) {
                items = rawValue.values;
                matchMode = "none";
            }
            else if (rawValue instanceof Includes) {
                items = rawValue.values;
            }
            else if (Array.isArray(rawValue)) {
                items = rawValue;
            }
            else if (typeof rawValue === "string") {
                items = [rawValue];
            }
            const entityNames = items
                .map((item) => {
                var _a;
                const entity = (_a = data.filter.filterDropdownOptions) === null || _a === void 0 ? void 0 : _a.find((e) => {
                    return (e === null || e === void 0 ? void 0 : e.value.toString()) === item.toString();
                });
                if (entity) {
                    return entity.label.toString();
                }
                return null;
            })
                .filter((name) => {
                return name !== null;
            })
                .join(", ");
            if (!entityNames) {
                return null;
            }
            const isMoreItems = items.length > 1;
            let joiner;
            if (matchMode === "all") {
                joiner = tx("has all of:");
            }
            else if (matchMode === "none") {
                joiner = tx("has none of:");
            }
            else if (isMoreItems) {
                joiner = tx("is any of:");
            }
            else {
                joiner = tx("is");
            }
            return (React.createElement("span", null,
                React.createElement("span", { className: "font-medium" }, tx(data.filter.title)),
                " ",
                joiner,
                " ",
                React.createElement("span", { className: "font-medium" }, entityNames)));
        }
        return filterText;
    };
    const filterTexts = translateFilterToText({
        filters: props.filters,
        filterData: props.filterData || {},
    });
    if (props.filterError) {
        return React.createElement(ErrorMessage, { message: props.filterError });
    }
    const showViewer = filterTexts.length > 0;
    return (React.createElement("div", null,
        showViewer && (React.createElement("div", null,
            React.createElement("div", { className: "mt-4 mb-4 bg-gray-50 rounded-xl p-4 border border-gray-200" },
                React.createElement("div", { className: "flex items-center justify-between mb-3" },
                    React.createElement("div", { className: "flex items-center gap-2 text-sm text-gray-700" },
                        React.createElement(Icon, { icon: IconProp.Filter, size: SizeProp.Smaller }),
                        React.createElement("span", { className: "font-semibold" },
                            tx("Showing"),
                            " ",
                            props.pluralLabel || tx("results"),
                            " ",
                            tx("that match")))),
                React.createElement("div", { className: "flex flex-wrap gap-2" }, filterTexts.map((filterText, index) => {
                    return (React.createElement("div", { key: index, className: "inline-flex items-center rounded-full bg-white border border-gray-200 px-3 py-1 text-sm text-gray-700 shadow-sm whitespace-nowrap" },
                        React.createElement(FilterViewerItem, { key: index, text: filterText })));
                })),
                React.createElement("div", { className: "flex -ml-3 mt-3 -mb-1" },
                    React.createElement(Button, { className: "font-medium text-gray-900", icon: IconProp.Filter, onClick: props.onFilterModalOpen, title: tx("Edit Filters"), iconSize: SizeProp.Smaller, buttonStyle: ButtonStyleType.SECONDARY_LINK }),
                    React.createElement(Button, { onClick: () => {
                            var _a;
                            changeFilterData({});
                            (_a = props.onFilterModalClose) === null || _a === void 0 ? void 0 : _a.call(props);
                        }, className: "font-medium text-gray-900", icon: IconProp.Close, title: tx("Clear Filters"), buttonStyle: ButtonStyleType.SECONDARY_LINK }))))),
        props.showFilterModal && (React.createElement(Modal, { modalWidth: ModalWidth.Large, isLoading: props.isModalLoading, title: `${tx("Filter")} ${props.pluralLabel || props.singularLabel || tx("results")}`, description: `${tx("Narrow down")} ${props.pluralLabel || tx("results")} ${tx("by one or more criteria below.")}`, submitButtonText: tx("Apply Filters"), onClose: () => {
                var _a;
                (_a = props.onFilterModalClose) === null || _a === void 0 ? void 0 : _a.call(props);
            }, onSubmit: () => {
                var _a;
                setTempFilterDataForModal({});
                if (props.onFilterChanged) {
                    props.onFilterChanged(Object.assign({}, tempFilterDataForModal));
                }
                (_a = props.onFilterModalClose) === null || _a === void 0 ? void 0 : _a.call(props);
            } },
            React.createElement(FiltersForm, { onFilterRefreshClick: props.onFilterRefreshClick, filterData: tempFilterDataForModal, filters: props.filters, id: props.id + "-form", showFilter: true, onFilterChanged: (filterData) => {
                    setTempFilterDataForModal(filterData);
                }, onAdvancedFiltersToggle: props.onAdvancedFiltersToggle })))));
};
export default FilterComponent;
//# sourceMappingURL=FilterViewer.js.map