// 聊天室偏好与每日状态工具，承接从 Blade 内联脚本迁移出的纯数据规整逻辑。

export const BLOCKABLE_SYSTEM_SENDERS = ["钓鱼播报", "星海小博士", "百家乐", "跑马", "神秘箱子"];
export const BLOCKED_SYSTEM_SENDERS_STORAGE_KEY = "chat_blocked_system_senders";
export const CHAT_SOUND_MUTED_STORAGE_KEY = "chat_sound_muted";
// 白名单、localStorage key 与绑定标记共同保证偏好读取可控、事件只注册一次。
let soundMuteEventsBound = false;
let blockMenuEventsBound = false;

/**
 * 规整聊天室偏好对象，过滤非法配置并补齐默认值。
 *
 * @param {Record<string, unknown>|null|undefined} raw
 * @param {string[]} blockableSystemSenders
 * @returns {{blocked_system_senders:string[],sound_muted:boolean}}
 */
export function normalizeChatPreferences(raw, blockableSystemSenders = BLOCKABLE_SYSTEM_SENDERS) {
    // 服务端或旧本地缓存可能包含已下架发送者，规整时只保留当前白名单。
    const blocked = Array.isArray(raw?.blocked_system_senders)
        ? raw.blocked_system_senders.filter((sender) => blockableSystemSenders.includes(sender))
        : [];

    return {
        blocked_system_senders: Array.from(new Set(blocked)),
        sound_muted: Boolean(raw?.sound_muted),
    };
}

/**
 * 解析并标准化状态到期时间。
 *
 * @param {string|null|undefined} expiresAt
 * @returns {Date|null}
 */
export function parseDailyStatusExpiry(expiresAt) {
    if (!expiresAt) {
        return null;
    }

    const parsed = new Date(expiresAt);

    return Number.isNaN(parsed.getTime()) ? null : parsed;
}

/**
 * 将状态对象规整为前端统一结构，并过滤掉已过期状态。
 *
 * @param {Record<string, unknown>|null|undefined} raw
 * @param {number} nowTimestamp
 * @returns {{key:string,label:string,icon:string,group:string,expires_at:string}|null}
 */
export function normalizeDailyStatus(raw, nowTimestamp = Date.now()) {
    if (!raw || typeof raw !== "object") {
        return null;
    }

    const key = String(raw.key ?? raw.daily_status_key ?? "");
    const label = String(raw.label ?? raw.daily_status_label ?? "");
    const icon = String(raw.icon ?? raw.daily_status_icon ?? "");
    const group = String(raw.group ?? raw.daily_status_group ?? "");
    const expiresAt = raw.expires_at ?? raw.daily_status_expires_at ?? null;
    const parsedExpiry = parseDailyStatusExpiry(expiresAt);

    if (!key || !label || !icon || !parsedExpiry) {
        return null;
    }

    if (parsedExpiry.getTime() <= nowTimestamp) {
        return null;
    }

    return {
        key,
        label,
        icon,
        group,
        expires_at: parsedExpiry.toISOString(),
    };
}

/**
 * 从本地缓存读取已屏蔽的系统播报发送者列表。
 *
 * @param {string[]} blockableSystemSenders
 * @returns {string[]}
 */
export function loadBlockedSystemSenders(blockableSystemSenders = BLOCKABLE_SYSTEM_SENDERS) {
    try {
        // 旧 localStorage 可能损坏或被手动篡改，读取后只保留当前允许屏蔽的发送者。
        const saved = JSON.parse(localStorage.getItem(BLOCKED_SYSTEM_SENDERS_STORAGE_KEY) || "[]");

        if (!Array.isArray(saved)) {
            return [];
        }

        return saved.filter((sender) => blockableSystemSenders.includes(sender));
    } catch (error) {
        return [];
    }
}

/**
 * 将屏蔽的系统播报发送者列表写入本地缓存。
 *
 * @param {Iterable<string>} senders
 * @returns {void}
 */
export function persistBlockedSystemSenders(senders) {
    localStorage.setItem(BLOCKED_SYSTEM_SENDERS_STORAGE_KEY, JSON.stringify(Array.from(senders)));
}

/**
 * 判断当前禁音开关是否处于打开状态。
 *
 * @returns {boolean}
 */
export function isSoundMuted() {
    const muteCheckbox = document.getElementById("sound_muted");

    if (muteCheckbox) {
        return Boolean(muteCheckbox.checked);
    }

    return localStorage.getItem(CHAT_SOUND_MUTED_STORAGE_KEY) === "1";
}

/**
 * 同步禁音复选框和本地缓存。
 *
 * @param {boolean} muted 是否禁音
 * @returns {boolean}
 */
export function setSoundMuted(muted) {
    const normalizedMuted = Boolean(muted);
    localStorage.setItem(CHAT_SOUND_MUTED_STORAGE_KEY, normalizedMuted ? "1" : "0");

    const muteCheckbox = document.getElementById("sound_muted");
    if (muteCheckbox) {
        muteCheckbox.checked = normalizedMuted;
    }

    return normalizedMuted;
}

/**
 * 绑定禁音复选框事件，后端保存逻辑由调用方提供。
 *
 * @param {(muted:boolean)=>void|Promise<void>} onChange 禁音变化回调
 * @returns {void}
 */
export function bindSoundMuteControl(onChange) {
    if (soundMuteEventsBound || typeof document === "undefined") {
        return;
    }

    soundMuteEventsBound = true;
    document.addEventListener("change", (event) => {
        if (!(event.target instanceof HTMLInputElement) || event.target.id !== "sound_muted") {
            return;
        }

        const muted = setSoundMuted(event.target.checked);

        if (muted && typeof window.EffectSounds !== "undefined") {
            window.EffectSounds.stop();
        }

        if (typeof onChange === "function") {
            void onChange(muted);
        }
    });
}

/**
 * 绑定功能菜单、每日状态编辑与系统播报屏蔽的统一事件代理。
 *
 * @returns {void}
 */
export function bindBlockMenuControls() {
    if (blockMenuEventsBound || typeof document === "undefined") {
        return;
    }

    blockMenuEventsBound = true;

    document.addEventListener("change", (event) => {
        if (!(event.target instanceof HTMLInputElement)) {
            return;
        }

        const sender = event.target.dataset.chatBlockSender;
        if (!sender || typeof window.toggleBlockedSystemSender !== "function") {
            return;
        }

        window.toggleBlockedSystemSender(sender, event.target.checked);
    });

    document.addEventListener("click", (event) => {
        if (!(event.target instanceof Element)) {
            return;
        }

        // 功能菜单由 Blade 动态渲染，使用 document 代理避免重复绑定新节点。
        const featureMenuTrigger = event.target.closest("[data-chat-feature-menu-toggle]");
        if (featureMenuTrigger) {
            event.preventDefault();
            window.toggleFeatureMenu?.(event);

            return;
        }

        // 每日状态编辑器仍保留存量全局函数，这里只负责把 data-* 事件转发出去。
        const dailyStatusCloseButton = event.target.closest("[data-chat-daily-status-close]");
        if (dailyStatusCloseButton) {
            event.preventDefault();
            window.closeDailyStatusEditor?.();

            return;
        }

        const dailyStatusClearButton = event.target.closest("[data-chat-daily-status-clear]");
        if (dailyStatusClearButton) {
            event.preventDefault();
            window.clearDailyStatus?.();

            return;
        }

        const dailyStatusItem = event.target.closest("[data-chat-daily-status-select]");
        if (dailyStatusItem) {
            event.preventDefault();

            const statusKey = dailyStatusItem.getAttribute("data-chat-daily-status-select") || "";
            if (statusKey && typeof window.updateDailyStatus === "function") {
                window.updateDailyStatus(statusKey);
            }

            return;
        }

        if (event.target.closest("[data-chat-daily-status-editor]")) {
            event.stopPropagation();

            return;
        }

        if (event.target.closest("[data-chat-daily-status-overlay]")) {
            window.closeDailyStatusEditor?.();

            return;
        }

        // 快捷功能区包含本地清理、签到和跳转类动作，统一收口到当前代理入口。
        const localClearButton = event.target.closest("[data-chat-feature-local-clear]");
        if (localClearButton) {
            event.preventDefault();
            window.handleFeatureLocalClear?.();

            return;
        }

        const dailyStatusOpenButton = event.target.closest("[data-chat-daily-status-open]");
        if (dailyStatusOpenButton) {
            event.preventDefault();
            window.openDailyStatusEditor?.();

            return;
        }

        const dailySignInButton = event.target.closest("[data-chat-feature-sign-in]");
        if (dailySignInButton) {
            event.preventDefault();
            window.closeFeatureMenu?.();
            window.quickDailySignIn?.();

            return;
        }

        const shortcutButton = event.target.closest("[data-chat-feature-shortcut]");
        if (shortcutButton) {
            event.preventDefault();

            const action = shortcutButton.getAttribute("data-chat-feature-shortcut") || "";
            if (action && typeof window.runFeatureShortcut === "function") {
                window.runFeatureShortcut(action);
            }

            return;
        }

        if (event.target.closest("[data-chat-feature-menu]")) {
            event.stopPropagation();

            return;
        }

        // 系统播报屏蔽菜单需要阻止内部点击冒泡，避免点击复选框时菜单被外层关闭。
        const trigger = event.target.closest("[data-chat-block-menu-toggle]");
        if (trigger) {
            event.preventDefault();
            window.toggleBlockMenu?.(event);
            return;
        }

        if (event.target.closest("[data-chat-block-menu]")) {
            event.stopPropagation();
        }
    });
}

/**
 * 当前登录账号没有服务端偏好时，判断是否需要迁移旧本地偏好。
 *
 * @param {{blocked_system_senders?:string[],sound_muted?:boolean}} serverPreferences
 * @param {string[]} localBlockedSenders
 * @param {boolean} localMuted
 * @returns {boolean}
 */
export function shouldMigrateLocalChatPreferences(serverPreferences, localBlockedSenders, localMuted) {
    // 只有服务端尚无偏好时才迁移旧本地设置，避免覆盖已同步的账号配置。
    const hasServerPreferences = (serverPreferences?.blocked_system_senders || []).length > 0
        || Boolean(serverPreferences?.sound_muted);

    return !hasServerPreferences && (localBlockedSenders.length > 0 || localMuted);
}
