$(document).ready(function () {
    $("[data-timepicker-input]").each(function () {
        const $input = $(this);
        const $container = $input.closest(".inail-timepicker-input-container");
        const $options = $container.find("[data-timepicker-list]");
        const $message = $container
            .closest(".inail-timepicker-container")
            .find("[data-timepicker-message]");
        const $error = $message.find("[data-timepicker-error]");
        const $hint = $message.find("[data-timepicker-helper]");

        $error.hide();
        $hint.show();

        $input.attr({
        "role": "combobox",
        "aria-autocomplete": "list",
        "aria-expanded": "false",
        "aria-controls": $options.attr("id"),
        "aria-haspopup": "listbox"
      });

        function parseInterval(str) {
            if (/^\d+$/.test(str)) return parseInt(str, 10);
            if (/(\d+)\s*m/i.test(str)) return parseInt(RegExp.$1, 10);
            if (/(\d+)\s*h/i.test(str)) return parseInt(RegExp.$1, 10) * 60;
            return 30;
        }
        function generateTimeOptions() {
            $options.empty();
            const format = $input.data("timepicker-format") || "24h";
            const locale = $input.data("locale") || "it-It";
            const interval = parseInterval($input.data("time-interval") || "30m");
            const [minH, minM] = ($input.data("time-min") || "00:00")
                .split(":")
                .map(Number);
            const [maxH, maxM] = ($input.data("time-max") || "23:59")
                .split(":")
                .map(Number);

            let start = minH * 60 + minM;
            let end = maxH * 60 + maxM;

            for (let t = start; t <= end; t += interval) {
                let h = Math.floor(t / 60);
                let m = t % 60;
                const d = new Date();
                d.setHours(h);
                d.setMinutes(m);
                d.setSeconds(0);
                d.setMilliseconds(0);
                let label = new Intl.DateTimeFormat(locale, {
                    hour: "2-digit",
                    minute: "2-digit",
                    hour12: format === "12h",
                }).format(d);
                $options.append(
                    `<div class="inail-timepicker-options" tabindex="0" role="option" data-date="${d.toString()}">${label}</div>`
                );
            }
        }
        generateTimeOptions();

        function validateInput() {
            const val = $input.val().trim();
            if (val === "") {
                $error.hide();
                $hint.show();
                $input.removeClass("inail-input-error");
                return true;
            }
            const format = $input.data("timepicker-format") || "24h";
            let regex =
                format === "12h"
                    ? /^([0-9]{1,2}):([0-9]{2})\s?(AM|PM)$/i
                    : /^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/;

            const isValid = regex.test(val);

            if (!isValid) {
                $error.show();
                $hint.hide();
                $input.addClass("inail-input-error");
            } else {
                $error.hide();
                $hint.show();
                $input.removeClass("inail-input-error");
            }
            return isValid;
        }

        function setActiveOption($option) {
            $options
                .find(".inail-timepicker-options")
                .removeClass("active")
                .attr("aria-selected", "false");
            $option.addClass("active").attr("aria-selected", "true");
            $option[0].scrollIntoView({ block: "nearest", inline: "nearest" });
        }

        function selectOption($option) {
            $options.find(".inail-timepicker-options").removeClass("selected");
            $option.addClass("selected");
            const val = $option.text();
            const dateVal = $option.data("date");
            $input.val(val).trigger("change");
            $input.data("selected-date", dateVal);
            $options.hide();
            $input.attr("aria-expanded", "false");
            $error.hide();
            $hint.show();
            $input.removeClass("inail-input-error");
            $("[data-time-picker-value]").text(dateVal);
        }

        function showAllOptions() {
            $options.show();
            $input.attr("aria-expanded", "true");

            const isValid = validateInput();
            const val = $input.val().trim();

            $options
                .find(".inail-timepicker-options")
                .removeClass("active selected")
                .attr("aria-selected", "false");

            if (isValid) {
                const $match = $options
                    .find(".inail-timepicker-options")
                    .filter(function () {
                        return $(this).text() === val;
                    })
                    .first();
                if ($match.length) {
                    $match.addClass("selected");
                    setActiveOption($match);
                    return;
                }
            }

            const $first = $options.find(".inail-timepicker-options").first();
            if ($first.length) setActiveOption($first);
        }

        $input
            .on("keydown", function (e) {
                if (e.key === "Enter") {
                    e.preventDefault();

                    if ($options.is(":visible")) {
                        const val = $input.val().trim();
                        const $active = $options
                            .find(".inail-timepicker-options.active:visible")
                            .first();
                        if ($active.length) {
                            selectOption($active);
                            return;
                        }

                        const isValid = validateInput();

                        if (isValid) {
                            const $match = $options
                                .find(".inail-timepicker-options")
                                .filter(function () {
                                    return $(this).text() === val;
                                })
                                .first();

                            if ($match.length) {
                                selectOption($match);
                            } else {
                                const [h, m] = val.split(":").map(Number);
                                if (!isNaN(h) && !isNaN(m)) {
                                    const d = new Date();
                                    d.setHours(h);
                                    d.setMinutes(m);
                                    d.setSeconds(0);
                                    d.setMilliseconds(0);
                                    $input.data("selected-date", d.toString());
                                    $("[data-time-picker-value]").text(
                                        "Digitato: " + val + " (" + d.toString() + ")"
                                    );
                                    $error.hide();
                                    $hint.show();
                                    $input.removeClass("inail-input-error");
                                }
                            }
                        } else {
                            $("[data-time-picker-value]").text("Invalid date");
                        }
                    } else {
                        showAllOptions();
                    }
                } else if (e.key === "ArrowDown") {
                    e.preventDefault();
                    if ($options.is(":visible")) {
                        const $visible = $options.find(".inail-timepicker-options:visible");
                        const $active = $options
                            .find(".inail-timepicker-options.active:visible")
                            .first();
                        if ($active.length) {
                            const currentIndex = $visible.index($active);
                            if (currentIndex + 1 < $visible.length) {
                                setActiveOption($visible.eq(currentIndex + 1));
                            }
                        } else {
                            const $first = $visible.first();
                            if ($first.length) setActiveOption($first);
                        }
                    } else {
                        showAllOptions();
                    }
                } else if (e.key === "ArrowUp") {
                    e.preventDefault();
                    if ($options.is(":visible")) {
                        const $visible = $options.find(".inail-timepicker-options:visible");
                        const $active = $options
                            .find(".inail-timepicker-options.active:visible")
                            .first();
                        if ($active.length) {
                            const currentIndex = $visible.index($active);
                            if (currentIndex > 0) {
                                setActiveOption($visible.eq(currentIndex - 1));
                            }
                        }
                    }
                }
            })
            .on("click", function () {
                showAllOptions();
                $input.focus();
            })
            .on("input change", function () {
                const isValid = validateInput();
                const val = $input.val().trim();
                $options
                    .find(".inail-timepicker-options")
                    .removeClass("selected active")
                    .attr("aria-selected", "false");
                if (isValid) {
                    const $match = $options
                        .find(".inail-timepicker-options")
                        .filter(function () {
                            return $(this).text() === val;
                        })
                        .first();
                    if ($match.length) {
                        $match.addClass("selected");
                        setActiveOption($match);
                        const dateVal = $match.data("date");
                        $input.data("selected-date", dateVal);
                        $("[data-time-picker-value]").text(
                            "Selezionato: " + val + " (" + dateVal + ")"
                        );
                    } else {
                        const [h, m] = val.split(":").map(Number);
                        if (!isNaN(h) && !isNaN(m)) {
                            const d = new Date();
                            d.setHours(h);
                            d.setMinutes(m);
                            d.setSeconds(0);
                            d.setMilliseconds(0);
                            $input.data("selected-date", d.toString());
                            $("[data-time-picker-value]").text(
                                "Digitato: " + val + " (" + d.toString() + ")"
                            );
                        }
                    }
                } else {
                    $("[data-time-picker-value]").text("Invalid date");
                }
            });

        $container.on("focusout", function (e) {
            if (!$container.has(e.relatedTarget).length) {
                $options.hide();
                $input.attr("aria-expanded", "false");
                validateInput();
                justSelected = false;
            }
        });

        $options
            .on("click", ".inail-timepicker-options", function () {
                justSelected = true;
                selectOption($(this));
            })
            .on("keydown", ".inail-timepicker-options", function (e) {
                const $visible = $options.find(".inail-timepicker-options:visible");
                const currentIndex = $visible.index(this);

                if (e.key === "Enter") {
                    e.preventDefault();
                    selectOption($(this));
                } else if (e.key === "ArrowDown") {
                    e.preventDefault();
                    if (currentIndex + 1 < $visible.length) {
                        setActiveOption($visible.eq(currentIndex + 1));
                    }
                } else if (e.key === "ArrowUp") {
                    e.preventDefault();
                    if (currentIndex > 0) {
                        setActiveOption($visible.eq(currentIndex - 1));
                    } else {
                        $input.focus();
                        $options
                            .find(".inail-timepicker-options")
                            .removeClass("active")
                            .attr("aria-selected", "false");
                    }
                }
            });

        $(document).on("click", function (e) {
            if (!$(e.target).closest(".inail-timepicker-container").length) {
                $options.hide();
                $input.attr("aria-expanded", "false");
            }
        });
    });
});
