(function () {

    let currentNumber = "";
    const MAX_NUMBER_LENGTH = 16;
    let lastInputTime = 0;
    const IS_TOUCH = ("ontouchstart" in window || navigator.maxTouchPoints > 0);
    const INPUT_EVENT = IS_TOUCH ? "touchstart" : "click";

    var search_pageinsize = 20;
    var search_offset = 0;
    var search_lock = false;

    // 번호 표시
    function updateNumberDisplay() {
        $(".number_box .number").text(currentNumber);
    }

    // 번호 포맷
    function formatPhone(number) {
        if (!number) return "";
        if (number.includes("-")) return number;
        const d = number.replace(/\D/g, "");
        if (d.length === 11) return d.replace(/(\d{3})(\d{4})(\d{4})/, "$1-$2-$3");
        if (d.length === 10) return d.replace(/(\d{3})(\d{3})(\d{4})/, "$1-$2-$3");
        return number;
    }

    function createPreviewItem() {
        return $(`
            <a href="#" class="apx_unit" data-user-id="" data-phone="">
            <div class="thumb"></div>
            <div class="who">
                <div class="name"></div>
                <div class="num"><u class="key"></u></div>
            </div>
            </a>
        `);
    }

    function createSearchListItem() {
        return $(`
            <li>
            <a href="#" data-user-id="" data-phone="">
                <div class="thumb"></div>
                <div class="who">
                <div class="name"></div>
                <div class="num"></div>
                </div>
            </a>
            </li>
        `);
    }

    // 연락처에서 번호 선택
    function pickPhone(contact, query) {
        if (!contact || !Array.isArray(contact.phoneNumbers) || contact.phoneNumbers.length === 0) {
            return null;
        }
        const q = (query ?? "").replace(/\D/g, "");
        let chosen = null;

        if (q) {
            chosen = contact.phoneNumbers.find(p => (p.normalizedNumber ?? "").includes(q));
        }
        if (!chosen) chosen = contact.phoneNumbers[0];

        const normalized = chosen?.normalizedNumber ?? "";
        let afterKey = normalized;
        if (q) {
            const idx = normalized.indexOf(q);
            if (idx >= 0) afterKey = normalized.slice(idx + q.length);
        }
        return {
            normalized,
            display: chosen?.display ?? formatPhone(normalized),
            displayAfterKey: afterKey
        };
    }

    // apx 미리보기 렌더
    function renderPreview(results, query) {
        const $preview = $("#apx_preview");
        const $more = $("#apx_more_button");

        $preview.find(".apx_unit").remove();

        if (!Array.isArray(results) || results.length === 0) {
            $preview.addClass("is-empty");
            $more.attr("data-total", "0").text("0").hide();
            return;
        }

        const first = results[0];
        const phone = pickPhone(first, query) || {};

        const $item = createPreviewItem();
        $item.attr("data-user-id", first.userId ?? "");
        $item.attr("data-phone", phone.normalized ?? "");

        if (first.thumbUrl) {
            $item.find(".thumb").css("background-image", `url('${first.thumbUrl}')`);
        } else {
            $item.find(".thumb").removeAttr("style");
        }

        $item.find(".name").text(first.name ?? "");

        const normalized = String(phone.normalized || "").replace(/\D/g, "");
        const q = String(query || "").replace(/\D/g, "");
        const $num = $item.find(".num").empty();

        if (q && normalized) {
            const idx = normalized.indexOf(q);
            if (idx >= 0) {
                $num.append(document.createTextNode(normalized.slice(0, idx)));
                $num.append($("<u/>", { "class": "key", text: q }));
                $num.append(document.createTextNode(normalized.slice(idx + q.length)));
            } else {
                $num.text(phone.display || normalized);
            }
        } else {
            $num.text(phone.display || normalized);
        }

        $preview.prepend($item).removeClass("is-empty");

        $more
            .attr("data-total", String(results.length))
            .text(String(results.length))
            .toggle(results.length >= 2);
    }

    // 전체 검색 리스트 렌더
    function renderSearchList(results) {
        var $list = $("#search_result_list");
        $list.empty();
        if (!Array.isArray(results) || results.length === 0) return;

        search_offset = 0;             
        search_lock = false;          
        $list.scrollTop(0);     

        // 첫 페이지 렌더
        renderSearchListPage(results, search_offset);

        // 스크롤 바인딩(중복 방지)
        $list.off("scroll.searchlist").on("scroll.searchlist", function () {
            if (search_lock) return;

            var el = this;
            var $el = $(this);
            var atBottom = (el.scrollTop + $el.innerHeight()) >= (el.scrollHeight - 2);

            if (!atBottom || search_offset >= results.length) return;

            search_lock = true;
            requestAnimationFrame(function () {
                renderSearchListPage(results, search_offset);
                search_lock = false;
            });
        });
    }

    // 페이지 단위 추가 렌더
    function renderSearchListPage(results, offset) {
        var $list = $("#search_result_list");
        var end = Math.min(offset + search_pageinsize, results.length);
        if (offset >= end) return;

        var currentNum = (typeof window.currentNumber !== "undefined") ? window.currentNumber : "";
        var nodes = [];

        for (var i = offset; i < end; i++) {
            var contact = results[i];
            var phone = pickPhone(contact, currentNum) || {};
            var $li = createSearchListItem();

            $li.find("a")
                .attr("data-user-id", contact.userId ?? "")
                .attr("data-phone", phone.normalized ?? "");

            if (contact.thumbUrl) {
                $li.find(".thumb").css("background-image", "url('" + contact.thumbUrl + "')");
            } else {
                $li.find(".thumb").removeAttr("style");
            }

            $li.find(".name").text(contact.name ?? "");
            $li.find(".num").text(phone.display ?? "");

            nodes.push($li[0]);
        }

        if (nodes.length) {
            $list.append(nodes);
            search_offset = end; // 다음 페이지 시작점 업데이트
        }
    }

    function openSearchList() { $(".search_list").show(); }
    function closeSearchList() { $(".search_list").hide(); }

    // 한 자리 추가
    function addDigit(digit) {
        if (currentNumber.length >= MAX_NUMBER_LENGTH) {
            popAlert?.("16자리까지 입력 가능합니다.");
            return;
        }
        currentNumber += digit;
        updateNumberDisplay();
        try {
            if (typeof searchPad === "function") searchPad();
            if (Array.isArray(window.searchContactByNumber)) {
                renderPreview(window.searchContactByNumber, currentNumber.replace(/\D/g, ""));
            }
        } catch (e) { }
    }

    // 한 자리 삭제
    function deleteDigit() {
        if (currentNumber.length === 0) return;

        currentNumber = currentNumber.slice(0, -1);
        updateNumberDisplay();

        if (currentNumber.length === 0) {
            clearNumber();
            return;
        }

        try {
            if (typeof searchPad === "function") searchPad();
            if (Array.isArray(window.searchContactByNumber)) {
                renderPreview(window.searchContactByNumber, currentNumber.replace(/\D/g, ""));
            }
        } catch (e) { }
    }

    // 전체 초기화
    function clearNumber() {
        currentNumber = "";
        updateNumberDisplay();
        $("#apx_preview").find(".apx_unit").remove();
        $("#apx_more_button").attr("data-total", "0").text("0");
        closeSearchList();
        try { if (typeof searchPad === "function") searchPad(); } catch (e) { }
    }

    // 현재 번호
    function getCurrentPhoneNumber() {
        return currentNumber;
    }

    // 클릭투콜 버튼
    function handleClickToCall() {
        const num = getCurrentPhoneNumber();
        if ($.isEmptyObject(num)) return console.log("전화번호를 입력해주세요.");
        clickToCall(num, "기타");
    }

    // 콜쓰루 버튼
    function handleCallThrough() {
        let num = $.trim($("#display_number").text() || "");

        $("#search_list_layer").hide();

        if (!num) {
            let callHistory = window.localStorage.getArray("callHistory");
            if (!callHistory || !callHistory.length || !callHistory[0].num) {
                console.log("전화번호를 입력해주세요.");
                if (typeof popAlert === "function") popAlert("전화 번호를 확인해 주세요");
                return;
            }
            $("#display_number").text(callHistory[0].num);
            window.callNum = callHistory[0].num;
            return;
        }

        callthrough(num, "기타");
    }

    // 콜백 버튼
    // function handleCallBack() {
    //     const num = getCurrentPhoneNumber();
    //     if ($.isEmptyObject(num)) return console.log("전화번호를 입력해주세요.");
    //     callBack("-1" + num, num, "기타");
    // }

    // 단순 표시
    function viewCallInfo(number) {
        console.log("전화번호 확인:", number);
    }

    // 키패드
    function getDigitText($a) {
        return $a.clone().children("sub").remove().end().text().trim();
    }

    $(function () {
        currentNumber = "";
        updateNumberDisplay();

        // 키패드
        $(".dials").off(".dial").on(`${INPUT_EVENT}.dial`, ".digits a", function (e) {
            e.preventDefault();
            e.stopPropagation();

            const now = Date.now();
            if (now - lastInputTime < 100) return;
            lastInputTime = now;

            const text = getDigitText($(this));
            if (text === "Clear") {
                clearNumber();
            } else if (text === "Delete") {
                deleteDigit();
            } else if (text) {
                addDigit(text);
            }
        });

        // 통화 버튼
        $("#click_to_call").off(".dial").on("click.dial", function (e) {
            e.preventDefault();
            handleClickToCall();
        });
        $("#call_through").off(".dial").on("click.dial", function (e) {
            e.preventDefault();
            handleCallThrough();
        });

        // $("#call_back").off(".dial").on("click.dial", function (e) {
        //   e.preventDefault();
        //   handleCallBack();
        // });

        // 미리보기 선택
        $(document).off(".dial_apx").on("click.dial_apx", ".apx_unit", function (e) {
            e.preventDefault();
            const num = $(this).attr("data-phone") || "";
            if (!num) return;
            currentNumber = num;
            updateNumberDisplay();
            try {
                if (typeof searchPad === "function") searchPad();
                if (Array.isArray(window.searchContactByNumber)) {
                    renderPreview(window.searchContactByNumber, currentNumber.replace(/\D/g, ""));
                }
            } catch (e) { }
        });

        // 더보기 버튼
        $("#apx_more_button").off(".dial_more").on("click.dial_more", function (e) {
            e.preventDefault();
            if (!Array.isArray(window.searchContactByNumber) || window.searchContactByNumber.length === 0) return;

            renderSearchList(window.searchContactByNumber);
            openSearchList();
        });

        // 팝업 닫기
        $("#search_list_close").off(".dial_close").on("click.dial_close", function (e) {
            e.preventDefault();
            closeSearchList();
        });

        // 팝업 선택
        $("#search_result_list").off(".dial_pick").on("click.dial_pick", "a", function (e) {
            e.preventDefault();
            const num = $(this).attr("data-phone") || "";
            if (!num) return;
            currentNumber = num;
            updateNumberDisplay();
            closeSearchList();
            try {
                if (typeof searchPad === "function") searchPad();
                if (Array.isArray(window.searchContactByNumber)) {
                    renderPreview(window.searchContactByNumber, currentNumber.replace(/\D/g, ""));
                }
            } catch (e) { }
        });
    });

    window.addDigit = addDigit;
})();