(function () {
    var HOST_SALARY_USD = 'HOST_SALARY_USD';

    var state = emptyHostState();
    var policyAutoScrollPending = false;

    function $(id) {
        return document.getElementById(id);
    }

    function emptyHostState() {
        return {
            profile: {
                loading: true,
                name: '',
                uid: '',
                avatar: '',
            },
            agency: {
                loading: true,
                shortId: '',
                name: '',
                avatar: '',
            },
            salary: {
                loading: true,
                available: 0,
                monthKey: '',
                month: '',
                currencyKey: '',
                currency: '',
                useCurrentMonth: false,
            },
            level: {
                loading: true,
                current: 0,
                nextLevelNo: 0,
                currentRequired: 0,
                currentValue: 0,
                nextValue: 0,
                needed: 0,
            },
            policy: {
                loading: true,
                loaded: false,
                found: false,
                policy: null,
            },
            messages: [],
            processingMessages: {},
        };
    }

    function setSkeleton(element, loading, text) {
        if (!element) return;
        element.classList.toggle('skeleton-line', !!loading);
        if (loading) {
            element.textContent = '';
            return;
        }
        element.textContent = text || '';
    }

    function avatarData(text, background, foreground) {
        var value =
            String(text || 'Y')
                .trim()
                .charAt(0) || 'Y';
        var letter = value.replace(/[<>&"']/g, '');
        var svg =
            '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96">' +
            '<rect width="96" height="96" rx="48" fill="' +
            background +
            '"/>' +
            '<text x="50%" y="54%" text-anchor="middle" dominant-baseline="middle" fill="' +
            foreground +
            '" font-family="Arial, sans-serif" font-size="38" font-weight="800">' +
            letter +
            '</text>' +
            '</svg>';
        return 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg);
    }

    function t(key, fallback) {
        return window.HyAppI18n && window.HyAppI18n.t
            ? window.HyAppI18n.t(key, fallback)
            : fallback || key;
    }

    function money(value) {
        var number = Number(value || 0);
        return number.toLocaleString('en-US', {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2,
        });
    }

    function integer(value) {
        var number = Number(value || 0);
        return number.toLocaleString('en-US', {
            maximumFractionDigits: 0,
        });
    }

    function initial(text) {
        return String(text || '')
            .trim()
            .charAt(0)
            .toUpperCase();
    }

    function hasAccessToken() {
        return (
            window.HyAppAPI &&
            window.HyAppAPI.getAccessToken &&
            !!window.HyAppAPI.getAccessToken()
        );
    }

    function unwrapData(payload) {
        if (!payload || typeof payload !== 'object') return payload;
        return Object.prototype.hasOwnProperty.call(payload, 'data')
            ? payload.data
            : payload;
    }

    function firstValue(source, keys) {
        if (!source) return '';
        for (var i = 0; i < keys.length; i += 1) {
            var value = source[keys[i]];
            if (value !== undefined && value !== null && value !== '') {
                return value;
            }
        }
        return '';
    }

    function toNumber(value) {
        var number = Number(value);
        return Number.isFinite(number) ? number : 0;
    }

    function safeRequest(factory) {
        return factory().catch(function (error) {
            if (window.console && window.console.warn) {
                window.console.warn('[host-center] api failed', error);
            }
            return null;
        });
    }

    function currentLocale() {
        var lang =
            window.HyAppI18n && window.HyAppI18n.lang
                ? window.HyAppI18n.lang()
                : 'en';
        var map = {
            en: 'en-US',
            ar: 'ar',
            tr: 'tr-TR',
            es: 'es-ES',
            zh: 'zh-CN',
            id: 'id-ID',
        };
        return map[lang] || 'en-US';
    }

    function currentMonthName() {
        try {
            return new Date().toLocaleString(currentLocale(), {
                month: 'long',
            });
        } catch (_) {
            return 'June';
        }
    }

    function salaryMonthLabel(salary) {
        if (salary.monthKey) return t(salary.monthKey, salary.month);
        if (salary.useCurrentMonth) return currentMonthName();
        return salary.month || currentMonthName();
    }

    function salaryCurrencyLabel(salary) {
        if (salary.currencyKey) return t(salary.currencyKey, salary.currency);
        return salary.currency || t('host_center.currency_usd', 'USD');
    }

    function formatMode(value) {
        var text = String(value || '')
            .replace(/[_-]+/g, ' ')
            .trim();
        if (!text) return '-';
        return text.replace(/\b\w/g, function (letter) {
            return letter.toUpperCase();
        });
    }

    function formatDate(ms) {
        var value = toNumber(ms);
        if (!value) return '';
        try {
            return new Date(value).toLocaleDateString(currentLocale(), {
                year: 'numeric',
                month: 'short',
                day: 'numeric',
            });
        } catch (_) {
            return '';
        }
    }

    function commandID(prefix, id) {
        return [
            prefix,
            id || '0',
            Date.now(),
            Math.random().toString(16).slice(2),
        ].join('-');
    }

    function normalizeInvitationMessage(item) {
        var invitation = (item && item.invitation) || item || {};
        var inviter = (item && item.inviter) || {};
        var id = String(
            invitation.invitation_id || invitation.invitationId || ''
        );
        var type = firstValue(invitation, [
            'invitation_type',
            'invitationType',
        ]);
        var agencyName = firstValue(invitation, ['agency_name', 'agencyName']);
        var inviterName =
            firstValue(inviter, ['username', 'name', 'display_user_id']) ||
            firstValue(invitation, ['inviter_user_id', 'inviterUserId']) ||
            t('host_center.inviter', 'Inviter');
        return {
            id: id,
            type: type,
            name: inviterName,
            account:
                firstValue(inviter, ['display_user_id', 'displayUserID']) ||
                firstValue(inviter, ['user_id', 'userId']) ||
                firstValue(invitation, ['inviter_user_id', 'inviterUserId']),
            avatar: firstValue(inviter, ['avatar']),
            title: invitationMessageTitle(type, inviterName, agencyName),
        };
    }

    function invitationMessageTitle(type, inviterName, agencyName) {
        if (type === 'host') {
            return t(
                'host_center.host_invitation',
                '{name} invited you to join {agency}'
            )
                .replace('{name}', inviterName)
                .replace(
                    '{agency}',
                    agencyName || t('host_center.agency', 'Agency')
                );
        }
        if (type === 'agency') {
            return t(
                'host_center.agency_invitation',
                '{name} invited you to create agency {agency}'
            )
                .replace('{name}', inviterName)
                .replace(
                    '{agency}',
                    agencyName || t('host_center.agency', 'Agency')
                );
        }
        if (type === 'bd') {
            return t(
                'host_center.bd_invitation',
                '{name} invited you to become BD'
            ).replace('{name}', inviterName);
        }
        return t(
            'host_center.role_invitation',
            '{name} sent you an invitation'
        ).replace('{name}', inviterName);
    }

    function renderUnread() {
        var dot = $('messageUnreadDot');
        if (dot) dot.hidden = state.messages.length <= 0;
    }

    function createMessageAvatar(message) {
        var avatar = document.createElement('div');
        avatar.className = 'message-avatar';
        if (!message.avatar) {
            avatar.textContent = initial(message.name || 'M') || 'M';
            return avatar;
        }
        var img = document.createElement('img');
        img.src = message.avatar;
        img.alt = '';
        img.addEventListener('error', function () {
            avatar.textContent = initial(message.name || 'M') || 'M';
        });
        avatar.appendChild(img);
        return avatar;
    }

    function renderMessages() {
        var list = $('messageList');
        var empty = $('messageEmpty');
        if (!list || !empty) return;
        list.textContent = '';
        empty.hidden = state.messages.length > 0;
        empty.textContent = t('host_center.no_messages', 'No messages');
        state.messages.forEach(function (message) {
            var card = document.createElement('article');
            var user = document.createElement('div');
            var copy = document.createElement('div');
            var title = document.createElement('div');
            var meta = document.createElement('div');
            var actions = document.createElement('div');
            var agree = document.createElement('button');
            var refuse = document.createElement('button');
            card.className = 'message-card';
            user.className = 'message-user';
            copy.className = 'message-copy';
            title.className = 'message-name';
            meta.className = 'message-id';
            actions.className = 'message-actions';
            agree.className = 'message-action agree';
            refuse.className = 'message-action refuse';
            agree.type = 'button';
            refuse.type = 'button';
            agree.disabled = Boolean(state.processingMessages[message.id]);
            refuse.disabled = Boolean(state.processingMessages[message.id]);
            title.textContent = message.title;
            meta.textContent = message.account ? 'ID: ' + message.account : '';
            agree.textContent = t('host_center.agree', 'Agree');
            refuse.textContent = t('host_center.refuse', 'Refuse');
            agree.addEventListener('click', function () {
                processInvitationMessage(message, 'accept');
            });
            refuse.addEventListener('click', function () {
                processInvitationMessage(message, 'reject');
            });
            user.appendChild(createMessageAvatar(message));
            copy.appendChild(title);
            copy.appendChild(meta);
            user.appendChild(copy);
            actions.appendChild(agree);
            actions.appendChild(refuse);
            card.appendChild(user);
            card.appendChild(actions);
            list.appendChild(card);
        });
        renderUnread();
    }

    function policyAmount(minor) {
        return '$' + money(toNumber(minor) / 100);
    }

    function renderProfile() {
        var image = $('profileAvatar');
        var fallback = $('profileAvatarFallback');
        var badge = $('profileBadge');
        var profile = state.profile;
        var agency = state.agency;
        var loading = !!profile.loading;

        setSkeleton($('profileName'), loading, profile.name || '');
        setSkeleton(
            $('profileUID'),
            loading,
            profile.uid ? 'UID: ' + profile.uid : ''
        );
        fallback.classList.toggle('avatar-skeleton', loading);
        if (loading) {
            image.hidden = true;
            image.removeAttribute('src');
            fallback.hidden = false;
            fallback.textContent = '';
            badge.hidden = true;
            badge.replaceChildren();
            badge.classList.remove('skeleton-line');
            return;
        }

        fallback.textContent = initial(profile.name || profile.uid) || 'Y';

        if (agency.loading) {
            badge.hidden = false;
            setSkeleton(badge, true, '');
        } else if (agency.shortId) {
            badge.hidden = false;
            badge.classList.remove('skeleton-line');
            renderAgencyBadge(badge, agency);
        } else {
            badge.hidden = true;
            badge.classList.remove('skeleton-line');
            badge.replaceChildren();
        }

        if (!profile.avatar) {
            image.hidden = true;
            image.removeAttribute('src');
            fallback.hidden = false;
            return;
        }
        image.onload = function () {
            image.hidden = false;
            fallback.hidden = true;
        };
        image.onerror = function () {
            image.hidden = true;
            fallback.hidden = false;
        };
        image.src = profile.avatar;
    }

    function renderAgencyBadge(container, agency) {
        container.replaceChildren();
        var avatar = document.createElement('span');
        avatar.className = 'agency-badge-avatar';
        var fallbackText =
            initial(agency.name || agency.shortId) ||
            t('host_center.agency', 'Agency').charAt(0);
        if (agency.avatar) {
            var img = document.createElement('img');
            img.src = agency.avatar;
            img.alt = '';
            img.addEventListener('error', function () {
                avatar.textContent = fallbackText;
            });
            avatar.appendChild(img);
        } else {
            avatar.textContent = fallbackText;
        }

        var text = document.createElement('span');
        text.className = 'agency-badge-id';
        text.textContent = t(
            'host_center.agency_short_id',
            'Agency ID: {id}'
        ).replace('{id}', agency.shortId);
        container.appendChild(avatar);
        container.appendChild(text);
    }

    function renderIncome() {
        var salary = state.salary;
        var loading = !!salary.loading;
        setSkeleton($('availableSalary'), loading, money(salary.available));
        setSkeleton(
            $('incomeFoot'),
            loading,
            t(
                'host_center.salary_month_note',
                '{month} settlement · {currency}'
            )
                .replace('{month}', salaryMonthLabel(salary))
                .replace('{currency}', salaryCurrencyLabel(salary))
        );
        var coinIcon = document.querySelector('.coin-icon');
        if (coinIcon) coinIcon.classList.toggle('skeleton-coin', loading);
    }

    function renderLevel() {
        var level = state.level;
        var loading = !!level.loading;
        if (loading) {
            setSkeleton($('currentLevel'), true, '');
            setSkeleton($('nextLevelNeed'), true, '');
            setSkeleton($('levelStatus'), true, '');
            $('levelProgress').style.width = '38%';
            $('levelProgress').classList.add('skeleton-fill');
            return;
        }
        var currentRequired = toNumber(level.currentRequired);
        var currentValue = toNumber(level.currentValue);
        var nextValue = toNumber(level.nextValue);
        var need =
            level.needed !== undefined && level.needed !== null
                ? toNumber(level.needed)
                : Math.max(0, nextValue - currentValue);
        var denominator = Math.max(1, nextValue - currentRequired);
        var currentInLevel = Math.max(0, currentValue - currentRequired);
        var percent =
            nextValue > currentRequired
                ? Math.min(
                      100,
                      Math.round((currentInLevel / denominator) * 100)
                  )
                : 100;

        $('currentLevel').textContent = t(
            'host_center.level_value',
            'Lv. {level}'
        ).replace('{level}', String(level.current || 0));
        $('nextLevelNeed').textContent = money(need);
        $('currentLevel').classList.remove('skeleton-line');
        $('nextLevelNeed').classList.remove('skeleton-line');
        $('levelStatus').classList.remove('skeleton-line');
        $('levelProgress').style.width = percent + '%';
        $('levelProgress').classList.remove('skeleton-fill');
        $('levelStatus').textContent = t(
            'host_center.current_diamonds',
            'Current diamonds: {value}'
        ).replace('{value}', integer(currentValue));
    }

    function appendPolicyCell(parent, label, value) {
        var cell = document.createElement('div');
        cell.className = 'policy-cell';
        var labelNode = document.createElement('span');
        labelNode.className = 'policy-cell-label';
        labelNode.textContent = label;
        var valueNode = document.createElement('strong');
        valueNode.className = 'policy-cell-value';
        valueNode.textContent = value;
        cell.appendChild(labelNode);
        cell.appendChild(valueNode);
        parent.appendChild(cell);
    }

    function policyHighlightLevelNo() {
        var current = toNumber(state.level && state.level.current);
        return current > 0 ? current : 0;
    }

    function isPolicyOpen() {
        var modal = $('policyModal');
        return !!modal && !modal.hidden;
    }

    function scrollPolicyLevelIntoView(row) {
        if (!policyAutoScrollPending || !row || !isPolicyOpen()) return;
        policyAutoScrollPending = false;
        var run = window.requestAnimationFrame || window.setTimeout;
        run(function () {
            try {
                row.scrollIntoView({
                    behavior: 'smooth',
                    block: 'center',
                    inline: 'nearest',
                });
            } catch (_) {
                var container = row.closest('.policy-sheet-body');
                if (container) {
                    container.scrollTop =
                        row.offsetTop -
                        Math.max(
                            0,
                            (container.clientHeight - row.offsetHeight) / 2
                        );
                }
            }
        });
    }

    function renderPolicy() {
        var summary = state.policy || {};
        var policy = summary.policy || {};
        var list = $('policyLevelList');
        var empty = $('policyEmpty');
        if (!list || !empty) return;

        list.textContent = '';
        if (summary.loading) {
            setSkeleton($('policyName'), true, '');
            setSkeleton($('policyMeta'), true, '');
            empty.hidden = false;
            empty.textContent = '';
            empty.classList.add('policy-skeleton-block');
            return;
        }
        $('policyName').classList.remove('skeleton-line');
        $('policyMeta').classList.remove('skeleton-line');
        empty.classList.remove('policy-skeleton-block');
        if (!summary.found || !policy || !policy.name) {
            $('policyName').textContent = 'Platform policy';
            $('policyMeta').textContent = '';
            empty.hidden = false;
            empty.textContent = 'No platform policy configured.';
            policyAutoScrollPending = false;
            return;
        }

        var from = formatDate(policy.effective_from_ms);
        var to = formatDate(policy.effective_to_ms);
        var meta = [
            'Mode: ' + formatMode(policy.settlement_mode),
            'Trigger: ' + formatMode(policy.settlement_trigger_mode),
        ];
        if (from || to) {
            meta.push('Effective: ' + (from || '-') + ' - ' + (to || 'No end'));
        }
        $('policyName').textContent = policy.name || 'Current policy';
        $('policyMeta').textContent = meta.join(' / ');
        empty.hidden = true;
        empty.textContent = '';

        var levels = Array.isArray(policy.levels) ? policy.levels : [];
        if (!levels.length) {
            empty.hidden = false;
            empty.textContent = 'No policy levels configured.';
            policyAutoScrollPending = false;
            return;
        }

        var highlightedRow = null;
        var activeLevelNo = policyHighlightLevelNo();
        levels.forEach(function (level) {
            var row = document.createElement('div');
            row.className = 'policy-level-row';
            var levelNo = toNumber(level.level_no);
            row.dataset.levelNo = String(levelNo || '');
            if (levelNo > 0 && levelNo === activeLevelNo) {
                row.className += ' is-current-level';
                highlightedRow = row;
            }
            var head = document.createElement('div');
            head.className = 'policy-row-head';
            var title = document.createElement('strong');
            title.className = 'policy-level';
            title.textContent = 'Lv. ' + (levelNo || '-');
            var required = document.createElement('span');
            required.className = 'policy-effective';
            required.textContent =
                integer(level.required_diamonds) + ' diamonds';
            head.appendChild(title);
            head.appendChild(required);

            var grid = document.createElement('div');
            grid.className = 'policy-grid';
            appendPolicyCell(
                grid,
                'Host salary',
                policyAmount(level.host_salary_usd_minor)
            );
            var hostCoinReward = toNumber(level.host_coin_reward);
            // Host 端只展示主播能直接获得的有效奖励；为 0 或缺失时隐藏，避免把无收益项误读成待完成权益。
            if (hostCoinReward > 0) {
                appendPolicyCell(
                    grid,
                    'Host coin reward',
                    integer(hostCoinReward)
                );
            }
            row.appendChild(head);
            row.appendChild(grid);
            list.appendChild(row);
        });
        if (highlightedRow) {
            scrollPolicyLevelIntoView(highlightedRow);
        } else {
            policyAutoScrollPending = false;
        }
    }

    function render() {
        renderProfile();
        renderIncome();
        renderLevel();
        renderPolicy();
        renderMessages();
    }

    function applyProfile(payload) {
        var profile = unwrapData(payload);
        if (!profile) return;

        var name = firstValue(profile, [
            'username',
            'nickname',
            'name',
            'display_name',
        ]);
        var uid = firstValue(profile, [
            'display_user_id',
            'default_display_user_id',
            'uid',
            'user_id',
        ]);
        var avatar = firstValue(profile, ['avatar', 'avatar_url', 'avatarUrl']);

        state.profile = {
            loading: false,
            name: name || state.profile.name,
            uid: uid || state.profile.uid,
            avatar:
                avatar ||
                avatarData(
                    initial(name || uid || state.profile.name),
                    '#dbc8ff',
                    '#7d57c7'
                ),
        };
    }

    function applyAgency(payload) {
        var data = unwrapData(payload);
        var agency = data && data.agency ? data.agency : data;
        if (!agency) {
            return;
        }
        var shortId = firstValue(agency, [
            'short_id',
            'shortId',
            'display_user_id',
            'displayUserId',
            'agency_id',
            'agencyId',
        ]);
        state.agency = {
            loading: false,
            shortId: shortId ? String(shortId) : '',
            name: firstValue(agency, ['name', 'agency_name', 'agencyName']),
            avatar: firstValue(agency, ['avatar', 'avatar_url', 'avatarUrl']),
        };
    }

    function displayAmountForAsset(assetType, amount) {
        if (assetType === HOST_SALARY_USD) return toNumber(amount) / 100;
        return toNumber(amount);
    }

    function findBalance(payload, assetType) {
        var data = unwrapData(payload);
        var balances =
            data && Array.isArray(data.balances) ? data.balances : [];
        for (var i = 0; i < balances.length; i += 1) {
            if (
                balances[i].asset_type === assetType ||
                balances[i].assetType === assetType
            ) {
                return balances[i];
            }
        }
        return null;
    }

    function applyWallet(payload) {
        var balance = findBalance(payload, HOST_SALARY_USD);
        if (!balance) {
            state.salary = Object.assign({}, state.salary, {
                loading: false,
                available: 0,
                monthKey: '',
                month: '',
                currencyKey: 'host_center.currency_usd',
                currency: 'USD',
                useCurrentMonth: true,
            });
            return;
        }

        var amount = firstValue(balance, [
            'available_amount',
            'availableAmount',
        ]);
        state.salary = Object.assign({}, state.salary, {
            loading: false,
            available: displayAmountForAsset(HOST_SALARY_USD, amount),
            monthKey: '',
            month: '',
            currencyKey: 'host_center.currency_usd',
            currency: 'USD',
            useCurrentMonth: true,
        });
    }

    function applyLevelProgress(progress) {
        if (!progress) return;
        state.level = {
            loading: false,
            current: toNumber(
                firstValue(progress, ['current_level', 'currentLevel'])
            ),
            nextLevelNo: toNumber(
                firstValue(progress, ['next_level', 'nextLevel'])
            ),
            currentRequired: toNumber(
                firstValue(progress, [
                    'current_required_diamonds',
                    'currentRequiredDiamonds',
                ])
            ),
            currentValue: toNumber(
                firstValue(progress, ['current_value', 'currentValue'])
            ),
            nextValue: toNumber(
                firstValue(progress, [
                    'next_required_diamonds',
                    'nextRequiredDiamonds',
                    'current_value',
                    'currentValue',
                ])
            ),
            needed: toNumber(
                firstValue(progress, [
                    'needed_for_next_level',
                    'neededForNextLevel',
                ])
            ),
        };
    }

    function fallbackLevelProgress() {
        return {
            loading: false,
            current: 0,
            nextLevelNo: 0,
            currentRequired: 0,
            currentValue: 0,
            nextValue: 1,
            needed: 0,
        };
    }

    function levelProgressFromPolicy(policy, progress) {
        var levels =
            policy && Array.isArray(policy.levels) ? policy.levels : [];
        var currentValue = toNumber(
            firstValue(progress, [
                'total_diamonds',
                'totalDiamonds',
                'gift_diamond_total',
                'giftDiamondTotal',
            ])
        );
        if (!levels.length) {
            return Object.assign(fallbackLevelProgress(), {
                currentValue: currentValue,
            });
        }

        var current = null;
        var next = null;
        levels.forEach(function (level) {
            if (!level) return;
            var required = toNumber(
                firstValue(level, ['required_diamonds', 'requiredDiamonds'])
            );
            if (required <= currentValue) {
                if (
                    !current ||
                    required >
                        toNumber(
                            firstValue(current, [
                                'required_diamonds',
                                'requiredDiamonds',
                            ])
                        )
                ) {
                    current = level;
                }
                return;
            }
            if (
                !next ||
                required <
                    toNumber(
                        firstValue(next, [
                            'required_diamonds',
                            'requiredDiamonds',
                        ])
                    )
            ) {
                next = level;
            }
        });

        var currentRequired = current
            ? toNumber(
                  firstValue(current, ['required_diamonds', 'requiredDiamonds'])
              )
            : 0;
        var nextRequired = next
            ? toNumber(
                  firstValue(next, ['required_diamonds', 'requiredDiamonds'])
              )
            : currentRequired;
        var currentLevel = current
            ? toNumber(firstValue(current, ['level_no', 'levelNo', 'level']))
            : 0;
        var nextLevel = next
            ? toNumber(firstValue(next, ['level_no', 'levelNo', 'level']))
            : currentLevel;

        return {
            current_level: currentLevel,
            current_required_diamonds: currentRequired,
            current_value: currentValue,
            next_level: nextLevel,
            next_required_diamonds: nextRequired,
            needed_for_next_level: next
                ? Math.max(0, nextRequired - currentValue)
                : 0,
        };
    }

    function applyPolicy(payload) {
        var data = unwrapData(payload);
        if (!data || !data.found || !data.policy) {
            // 线上策略未配置或旧网关返回空数据时，等级区域不能停在骨架态；展示空进度比持续 loading 更能说明真实状态。
            state.level = fallbackLevelProgress();
            state.policy = {
                loading: false,
                loaded: true,
                found: false,
                policy: null,
            };
            return;
        }
        // 新网关直接返回 level_progress；旧网关只有 policy/progress 时，H5 按同一套档位和当前钻石累计计算目标进度。
        applyLevelProgress(
            firstValue(data, ['level_progress', 'levelProgress']) ||
                levelProgressFromPolicy(
                    data.policy,
                    firstValue(data, [
                        'progress',
                        'salary_progress',
                        'salaryProgress',
                    ])
                )
        );
        state.policy = {
            loading: false,
            loaded: true,
            found: true,
            policy: data.policy,
        };
    }

    function toast(message) {
        if (!message) return;
        if (window.HyAppToast && window.HyAppToast.show) {
            window.HyAppToast.show(message);
        }
    }

    function loadPolicy() {
        if (!window.HyAppAPI || !window.HyAppAPI.hostCenter) {
            renderPolicy();
            return Promise.resolve(false);
        }
        if (!hasAccessToken()) {
            renderPolicy();
            return Promise.resolve(false);
        }
        state.policy = Object.assign({}, state.policy, { loading: true });
        renderPolicy();
        return safeRequest(function () {
            return window.HyAppAPI.hostCenter.platformPolicy();
        }).then(function (payload) {
            if (payload) {
                applyPolicy(payload);
            } else {
                // 失败分支同样要结束主卡片 loading，否则页面会像线上截图一样一直显示紫色骨架条。
                state.level = fallbackLevelProgress();
                state.policy = {
                    loading: false,
                    loaded: false,
                    found: false,
                    policy: null,
                };
                toast(
                    t(
                        'host_center.load_failed',
                        'Load failed. Try again later.'
                    )
                );
            }
            renderPolicy();
            return !!payload;
        });
    }

    function loadRoleInvitations() {
        if (
            !window.HyAppAPI ||
            !window.HyAppAPI.roleInvitations ||
            !window.HyAppAPI.roleInvitations.list ||
            !hasAccessToken()
        ) {
            state.messages = [];
            renderMessages();
            return Promise.resolve(false);
        }
        return window.HyAppAPI.roleInvitations
            .list('pending', 50)
            .then(function (payload) {
                var items =
                    (payload && (payload.items || payload.invitations)) || [];
                state.messages = items
                    .map(normalizeInvitationMessage)
                    .filter(function (item) {
                        return !!item.id;
                    });
                renderMessages();
                return true;
            })
            .catch(function (error) {
                if (window.console && window.console.warn) {
                    window.console.warn('[host-center] messages failed', error);
                }
                state.messages = [];
                renderMessages();
                return false;
            });
    }

    function processInvitationMessage(message, action) {
        if (
            !message ||
            !message.id ||
            !window.HyAppAPI ||
            !window.HyAppAPI.roleInvitations ||
            !window.HyAppAPI.roleInvitations.process
        ) {
            return;
        }
        state.processingMessages[message.id] = true;
        renderMessages();
        window.HyAppAPI.roleInvitations
            .process(message.id, {
                command_id: commandID('role-invite-' + action, message.id),
                action: action,
                reason: 'h5_message_center',
            })
            .then(function () {
                state.messages = state.messages.filter(function (item) {
                    return item.id !== message.id;
                });
                toast(
                    t(
                        action === 'accept'
                            ? 'host_center.invitation_accepted'
                            : 'host_center.invitation_rejected',
                        action === 'accept'
                            ? 'Invitation accepted.'
                            : 'Invitation rejected.'
                    )
                );
                renderMessages();
                return loadRealData();
            })
            .catch(function (error) {
                toast(
                    (error && error.message) ||
                        t(
                            'host_center.process_failed',
                            'Process failed. Try again later.'
                        )
                );
            })
            .finally(function () {
                delete state.processingMessages[message.id];
                renderMessages();
            });
    }

    function openMessages() {
        var modal = $('messageModal');
        if (!modal) return;
        renderMessages();
        modal.hidden = false;
        modal.setAttribute('aria-hidden', 'false');
        document.body.classList.add('modal-open');
    }

    function closeMessages() {
        var modal = $('messageModal');
        if (!modal) return;
        modal.hidden = true;
        modal.setAttribute('aria-hidden', 'true');
        document.body.classList.remove('modal-open');
    }

    function requestPolicy() {
        if (!window.HyAppAPI || !window.HyAppAPI.hostCenter) {
            return Promise.resolve(null);
        }
        return safeRequest(function () {
            return window.HyAppAPI.hostCenter.platformPolicy();
        });
    }

    function loadRealData() {
        if (!window.HyAppAPI) return Promise.resolve(false);
        if (window.HyAppParams && window.HyAppParams.parse) {
            window.HyAppParams.parse();
        }
        if (!hasAccessToken()) return Promise.resolve(false);

        return Promise.all([
            safeRequest(function () {
                return window.HyAppAPI.user.me();
            }),
            safeRequest(function () {
                return window.HyAppAPI.hostCenter.agency();
            }),
            safeRequest(function () {
                return window.HyAppAPI.wallet.balances([HOST_SALARY_USD]);
            }),
            requestPolicy(),
        ]).then(function (results) {
            applyProfile(results[0]);
            applyAgency(results[1]);
            applyWallet(results[2]);
            if (results[3]) {
                applyPolicy(results[3]);
            } else {
                applyPolicy(null);
            }
            render();

            var hasAnyData = results.some(function (item) {
                return !!item;
            });
            if (!hasAnyData) {
                toast(
                    t(
                        'host_center.load_failed',
                        'Load failed. Try again later.'
                    )
                );
            }
            return hasAnyData;
        });
    }

    function openWithdrawExchange() {
        var params = new URLSearchParams(window.location.search);
        params.set('identity', 'HOST');
        params.set('salaryType', HOST_SALARY_USD);
        params.set('asset_type', HOST_SALARY_USD);
        if (!params.has('mode')) params.set('mode', 'withdraw');
        window.location.href =
            '../withdraw-exchange/index.html?' + params.toString();
    }

    function openPolicy() {
        var modal = $('policyModal');
        if (!modal) return;
        policyAutoScrollPending = true;
        modal.hidden = false;
        modal.setAttribute('aria-hidden', 'false');
        document.body.classList.add('modal-open');
        renderPolicy();
        policyAutoScrollPending = true;
        loadPolicy();
    }

    function closePolicy() {
        var modal = $('policyModal');
        if (!modal) return;
        modal.hidden = true;
        modal.setAttribute('aria-hidden', 'true');
        document.body.classList.remove('modal-open');
        policyAutoScrollPending = false;
    }

    function bindEvents() {
        $('backButton').addEventListener('click', function () {
            if (window.HyAppBridge) window.HyAppBridge.back();
        });

        $('incomeWithdrawExchangeButton').addEventListener(
            'click',
            openWithdrawExchange
        );

        document
            .querySelectorAll('[data-action="policy"]')
            .forEach(function (button) {
                button.addEventListener('click', openPolicy);
            });
        document
            .querySelectorAll('[data-action="messages"]')
            .forEach(function (button) {
                button.addEventListener('click', openMessages);
            });
        document
            .querySelectorAll('[data-close-policy]')
            .forEach(function (button) {
                button.addEventListener('click', closePolicy);
            });
        $('messageBackdrop').addEventListener('click', closeMessages);
        $('messageCloseButton').addEventListener('click', closeMessages);
        document.addEventListener('keydown', function (event) {
            if (event.key === 'Escape') {
                closePolicy();
                closeMessages();
            }
        });
    }

    var initialized = false;

    function init() {
        if (initialized) return;
        initialized = true;
        render();
        bindEvents();
        loadRealData().then(function (loaded) {
            loadRoleInvitations();
            if (window.HyAppBridge) {
                window.HyAppBridge.ready({
                    page: 'host-center',
                    mock: false,
                });
            }
        });
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    window.addEventListener('hyapp:i18n-ready', function () {
        render();
    });

    window.addEventListener('hyapp:role-invitation-processed', function () {
        loadRealData();
    });
})();
