(function () {
    var viewport = document.getElementById('appViewport');
    var page = document.getElementById('page');
    var dailyRoot = document.getElementById('dailyTasks');
    var exclusiveRoot = document.getElementById('exclusiveTasks');
    var stateRoot = document.getElementById('taskState');
    var backButton = document.getElementById('backButton');
    var COMMAND_PREFIX = 'task_claim_command:';
    var COIN_IMAGE = './assets/coin.png';
    var GAME_IMAGE = './assets/figma-game-icon.webp';

    var state = {
        loading: true,
        error: '',
        sections: [],
        claiming: {},
    };

    var mockData = {
        server_time_ms: Date.now(),
        next_refresh_at_ms: Date.now() + 6 * 60 * 60 * 1000,
        sections: [
            {
                section: 'daily',
                items: [
                    mockTask(
                        'daily-mic',
                        'daily',
                        'Use the microphone for 1 min',
                        'mic_online_minute',
                        0,
                        1000000,
                        1100,
                        'in_progress',
                        false,
                        'mic'
                    ),
                    mockTask(
                        'daily-game',
                        'daily',
                        'Use the microphone for 1 min',
                        'game_spend_coin',
                        1000000,
                        1000000,
                        1100,
                        'completed',
                        true,
                        'gamepad'
                    ),
                    mockTask(
                        'daily-gift',
                        'daily',
                        'Use the microphone for 1 min',
                        'gift_spend_coin',
                        1000000,
                        1000000,
                        1100,
                        'claimed',
                        false,
                        'gift'
                    ),
                ],
            },
            {
                section: 'exclusive',
                items: [
                    mockTask(
                        'exclusive-game-preview',
                        'exclusive',
                        'Use the microphone for 1 min',
                        'game_spend_coin',
                        0,
                        1000000,
                        1100,
                        'in_progress',
                        false,
                        'game_preview'
                    ),
                    mockTask(
                        'exclusive-game',
                        'exclusive',
                        'Use the microphone for 1 min',
                        'game_spend_coin',
                        1000000,
                        1000000,
                        1100,
                        'completed',
                        true,
                        'gamepad'
                    ),
                    mockTask(
                        'exclusive-gift',
                        'exclusive',
                        'Use the microphone for 1 min',
                        'gift_spend_coin',
                        1000000,
                        1000000,
                        1100,
                        'claimed',
                        false,
                        'gift'
                    ),
                ],
            },
        ],
    };

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

    function mockTask(
        id,
        type,
        title,
        metric,
        progress,
        target,
        reward,
        status,
        claimable,
        iconKey
    ) {
        return {
            task_id: id,
            task_type: type,
            task_day:
                type === 'daily'
                    ? new Date().toISOString().slice(0, 10)
                    : 'lifetime',
            title: title,
            metric_type: metric,
            progress_value: progress,
            target_value: target,
            reward_coin_amount: reward,
            status: status,
            claimable: claimable,
            icon_key: iconKey,
            icon_url: iconKey === 'game_preview' ? GAME_IMAGE : '',
            action_type:
                iconKey === 'gift'
                    ? 'gift_panel'
                    : iconKey === 'gamepad'
                      ? 'room_random_game'
                      : 'wallet',
            action_param: iconKey === 'gamepad' ? 'dice' : '',
            action_payload: iconKey === 'gamepad' ? { game_id: 'dice' } : {},
        };
    }

    function isMockMode() {
        var params = new URLSearchParams(window.location.search || '');
        return params.get('mock') === '1' || params.get('mock') === 'true';
    }

    function escapeHTML(value) {
        return String(value == null ? '' : value)
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;');
    }

    function escapeAttr(value) {
        return escapeHTML(value).replace(/`/g, '&#96;');
    }

    function clampProgress(item) {
        var target = Math.max(
            0,
            Number(item.target_value || item.targetValue || 0)
        );
        var progress = Math.max(
            0,
            Number(item.progress_value || item.progressValue || 0)
        );
        return {
            target: target,
            progress: target > 0 ? Math.min(progress, target) : progress,
        };
    }

    function formatProgress(item) {
        var values = clampProgress(item);
        return String(values.progress) + '/' + String(values.target);
    }

    function formatReward(value) {
        var amount = Number(value || 0);
        if (!Number.isFinite(amount)) return '0';
        if (amount >= 1000000) return trimNumber(amount / 1000000) + 'M';
        if (amount >= 1000) return trimNumber(amount / 1000) + 'k';
        return String(amount);
    }

    function trimNumber(value) {
        var rounded = Math.round(value * 10) / 10;
        return String(rounded).replace(/\.0$/, '');
    }

    function claimKey(item) {
        return [
            item.task_id || item.taskId,
            item.task_type || item.taskType,
            item.task_day || item.taskDay,
        ].join('|');
    }

    function commandStorageKey(item) {
        return COMMAND_PREFIX + claimKey(item);
    }

    function commandID(item) {
        var storageKey = commandStorageKey(item);
        var cached = window.sessionStorage.getItem(storageKey);
        if (cached) return cached;
        // 领取命令以任务主键和页面时间组成，保存在 sessionStorage；如果请求超时但服务端已入账，用户重试会继续用同一 command_id 命中后端幂等。
        var next =
            'h5-task-claim-' +
            Date.now() +
            '-' +
            Math.random().toString(16).slice(2) +
            '-' +
            String(item.task_id || item.taskId || '');
        window.sessionStorage.setItem(storageKey, next);
        return next;
    }

    function clearCommandID(item) {
        window.sessionStorage.removeItem(commandStorageKey(item));
    }

    function normalizeSections(payload) {
        var sections =
            payload && Array.isArray(payload.sections) ? payload.sections : [];
        var byName = sections.reduce(function (map, section) {
            map[String(section.section || '')] = Array.isArray(section.items)
                ? section.items
                : [];
            return map;
        }, {});
        return [
            { section: 'daily', items: byName.daily || [] },
            { section: 'exclusive', items: byName.exclusive || [] },
        ];
    }

    function iconKind(item) {
        var key = String(item.icon_key || item.iconKey || '').toLowerCase();
        var metric = String(
            item.metric_type || item.metricType || ''
        ).toLowerCase();
        if (key.indexOf('mic') >= 0 || metric.indexOf('mic') >= 0) return 'mic';
        if (key.indexOf('gift') >= 0 || metric.indexOf('gift') >= 0)
            return 'gift';
        if (key.indexOf('game') >= 0 || metric.indexOf('game') >= 0)
            return 'gamepad';
        if (key.indexOf('cp') >= 0 || metric.indexOf('cp') >= 0) return 'cp';
        if (key.indexOf('mood') >= 0 || metric.indexOf('mood') >= 0)
            return 'mood';
        return 'coin';
    }

    function iconHTML(item) {
        var iconURL = item.icon_url || item.iconUrl || '';
        if (iconURL) {
            // 后台 icon_url 是可配置资源，可能因为地址过期、跨域或资源未上传而加载失败；失败时用内置图标兜底，不能让任务列表留下空方块。
            return [
                '<span class="task-icon is-image" data-icon-fallback="',
                escapeAttr(iconKind(item)),
                '"><img src="',
                escapeAttr(iconURL),
                '" alt="" /></span>',
            ].join('');
        }
        return (
            '<span class="task-icon">' + svgForIcon(iconKind(item)) + '</span>'
        );
    }

    function svgForIcon(kind) {
        if (kind === 'mic') {
            return '<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="#fff" d="M12 3a4 4 0 0 0-4 4v5a4 4 0 0 0 8 0V7a4 4 0 0 0-4-4Zm-6 8.5a1 1 0 0 1 2 0V12a4 4 0 0 0 8 0v-.5a1 1 0 1 1 2 0V12a6 6 0 0 1-5 5.92V20h3a1 1 0 1 1 0 2H8a1 1 0 1 1 0-2h3v-2.08A6 6 0 0 1 6 12v-.5Z"/></svg>';
        }
        if (kind === 'gift') {
            return '<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="#fff" d="M8.2 4.2A3 3 0 0 1 12 5a3 3 0 0 1 3.8-.8A3.1 3.1 0 0 1 17 8h2a1 1 0 0 1 1 1v3h-7V8h-2v4H4V9a1 1 0 0 1 1-1h2a3.1 3.1 0 0 1 1.2-3.8ZM9 6a1 1 0 0 0 .2 2H11a2 2 0 0 0-2-2Zm4 2h1.8A1 1 0 1 0 13 6a2 2 0 0 0 0 2ZM5 14h6v6H6a1 1 0 0 1-1-1v-5Zm8 6v-6h6v5a1 1 0 0 1-1 1h-5Z"/></svg>';
        }
        if (kind === 'cp') {
            return '<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="#fff" d="M7.5 6A3.5 3.5 0 0 1 12 9.35 3.5 3.5 0 1 1 16.5 6c2.45 0 4.5 1.9 4.5 4.35 0 4.25-6.05 8.05-8.35 9.35a1.3 1.3 0 0 1-1.3 0C9.05 18.4 3 14.6 3 10.35 3 7.9 5.05 6 7.5 6Z"/></svg>';
        }
        if (kind === 'mood') {
            return '<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="#fff" d="M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18Zm-3 7.2a1.2 1.2 0 1 1 0-2.4 1.2 1.2 0 0 1 0 2.4Zm6 0a1.2 1.2 0 1 1 0-2.4 1.2 1.2 0 0 1 0 2.4Zm-6.3 3.35a1 1 0 0 1 1.4.1 2.5 2.5 0 0 0 3.8 0 1 1 0 0 1 1.5 1.3 4.5 4.5 0 0 1-6.8 0 1 1 0 0 1 .1-1.4Z"/></svg>';
        }
        if (kind === 'coin') {
            return '<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="#fff" d="M12 3c4.42 0 8 2.02 8 4.5V16c0 2.76-3.58 5-8 5s-8-2.24-8-5V7.5C4 5.02 7.58 3 12 3Zm0 2C8.14 5 6 6.47 6 7.5S8.14 10 12 10s6-1.47 6-2.5S15.86 5 12 5Zm6 5.3c-1.45 1.05-3.6 1.7-6 1.7s-4.55-.65-6-1.7V12c0 1.2 2.33 3 6 3s6-1.8 6-3v-1.7Zm0 5c-1.45 1.05-3.6 1.7-6 1.7s-4.55-.65-6-1.7V16c0 1.2 2.33 3 6 3s6-1.8 6-3v-.7Z"/></svg>';
        }
        return '<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="#fff" d="M8 9h8a4 4 0 0 1 0 8h-.5a2 2 0 0 1-1.6-.8l-.9-1.2h-2l-.9 1.2a2 2 0 0 1-1.6.8H8a4 4 0 0 1 0-8Zm.5 3H7v1.5h1.5V15H10v-1.5h1.5V12H10v-1.5H8.5V12Zm6.5.5a1 1 0 1 0 0-2 1 1 0 0 0 0 2Zm2.5 2.5a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z"/></svg>';
    }

    function actionState(item) {
        if (item.status === 'claimed') {
            return {
                label: t('tasks.claimed', 'Claimed'),
                className: 'is-claimed',
                disabled: true,
            };
        }
        if (item.claimable) {
            return {
                label: t('tasks.claim', 'Claim'),
                className: 'is-claimable',
                disabled: false,
            };
        }
        return {
            label: t('tasks.go', 'Go'),
            className: 'is-go',
            disabled: false,
        };
    }

    function renderSection(root, items) {
        if (!items.length) {
            root.innerHTML =
                '<div class="task-state">' +
                escapeHTML(t('tasks.empty', 'No tasks yet.')) +
                '</div>';
            return;
        }
        root.innerHTML = items.map(renderTaskRow).join('');
    }

    function renderTaskRow(item) {
        var action = actionState(item);
        var key = claimKey(item);
        var loading = Boolean(state.claiming[key]);
        var label = loading ? t('tasks.claiming', 'Claiming...') : action.label;
        return [
            '<article class="task-row" data-task-key="',
            escapeAttr(key),
            '">',
            iconHTML(item),
            '<div class="task-main">',
            '<strong class="task-title">',
            escapeHTML(
                item.title || item.description || t('tasks.untitled', 'Task')
            ),
            '</strong>',
            '<span class="task-progress">',
            escapeHTML(formatProgress(item)),
            '</span>',
            '<span class="task-reward"><img src="',
            COIN_IMAGE,
            '" alt="" aria-hidden="true" /><span>',
            escapeHTML(
                formatReward(item.reward_coin_amount || item.rewardCoinAmount)
            ),
            '</span></span>',
            '</div>',
            '<button class="task-action ',
            action.className,
            loading ? ' is-loading' : '',
            '" type="button" data-task-action="',
            escapeAttr(key),
            '"',
            action.disabled || loading ? ' disabled' : '',
            '>',
            escapeHTML(label),
            '</button>',
            '</article>',
        ].join('');
    }

    function render() {
        var sections = normalizeSections({ sections: state.sections });
        var daily = sections[0].items;
        var exclusive = sections[1].items;
        renderSection(dailyRoot, daily);
        renderSection(exclusiveRoot, exclusive);
        bindIconFallbacks();
        renderState();
        updateScale();
    }

    function bindIconFallbacks() {
        Array.prototype.slice
            .call(document.querySelectorAll('[data-icon-fallback] img'))
            .forEach(function (image) {
                image.addEventListener(
                    'error',
                    function () {
                        var wrapper = image.parentElement;
                        if (!wrapper) return;
                        wrapper.classList.remove('is-image');
                        wrapper.innerHTML = svgForIcon(
                            wrapper.getAttribute('data-icon-fallback') || 'coin'
                        );
                    },
                    { once: true }
                );
            });
    }

    function renderState() {
        if (state.loading) {
            stateRoot.hidden = false;
            stateRoot.textContent = t('tasks.loading', 'Loading...');
            return;
        }
        if (state.error) {
            stateRoot.hidden = false;
            stateRoot.textContent = state.error;
            return;
        }
        stateRoot.hidden = true;
        stateRoot.textContent = '';
    }

    function loadTasks() {
        state.loading = true;
        state.error = '';
        renderState();
        if (isMockMode()) {
            applyPayload(mockData);
            return;
        }
        if (!window.HyAppAPI || !window.HyAppAPI.task) {
            state.loading = false;
            state.error = t('tasks.apiUnavailable', 'Task API unavailable.');
            render();
            return;
        }
        window.HyAppAPI.task
            .tabs()
            .then(applyPayload)
            .catch(function (error) {
                state.loading = false;
                state.error =
                    error.message || t('tasks.loadFailed', 'Load failed.');
                state.sections = [];
                render();
            });
    }

    function applyPayload(payload) {
        var sections = normalizeSections(payload);
        state.sections = sections.map(function (section) {
            return {
                section: section.section,
                items: section.items,
            };
        });
        state.loading = false;
        state.error = '';
        render();
    }

    function findTask(key) {
        var sections = normalizeSections({ sections: state.sections });
        for (
            var sectionIndex = 0;
            sectionIndex < sections.length;
            sectionIndex += 1
        ) {
            var items = sections[sectionIndex].items;
            for (var itemIndex = 0; itemIndex < items.length; itemIndex += 1) {
                if (claimKey(items[itemIndex]) === key) return items[itemIndex];
            }
        }
        return null;
    }

    function claimTask(item) {
        var key = claimKey(item);
        state.claiming[key] = true;
        render();
        if (isMockMode()) {
            // mock 只服务本地视觉和交互验收，不触发真实发奖；真实页面仍必须通过后端 claim 接口刷新钱包和任务状态。
            item.status = 'claimed';
            item.claimable = false;
            state.claiming[key] = false;
            showToast(t('tasks.claimSuccess', 'Reward claimed.'));
            render();
            return;
        }
        // H5 只提交任务列表返回的 task_day/task_type/task_id，避免页面自行推算每日刷新周期；服务端负责判断当天是否仍可领取。
        window.HyAppAPI.task
            .claim({
                task_id: item.task_id || item.taskId,
                task_type: item.task_type || item.taskType,
                task_day: item.task_day || item.taskDay,
                command_id: commandID(item),
            })
            .then(function () {
                clearCommandID(item);
                showToast(t('tasks.claimSuccess', 'Reward claimed.'));
                return window.HyAppAPI.task.tabs();
            })
            .then(applyPayload)
            .catch(function (error) {
                state.claiming[key] = false;
                showToast(
                    error.message || t('tasks.claimFailed', 'Claim failed.')
                );
                render();
            });
    }

    function goTask(item) {
        var actionType = item.action_type || item.actionType || 'none';
        if (!actionType || actionType === 'none') {
            showToast(t('tasks.noAction', 'No action configured.'));
            return;
        }
        var payload = {
            task_id: item.task_id || item.taskId || '',
            task_type: item.task_type || item.taskType || '',
            task_day: item.task_day || item.taskDay || '',
            action_type: actionType,
            action_param: item.action_param || item.actionParam || '',
            action_payload: item.action_payload || item.actionPayload || {},
        };
        // H5 不猜测原生房间/钱包/礼物页面的具体路由，只把后台配置的跳转元数据原样交给 App；App 侧可按 action_type 做统一分发。
        if (window.HyAppBridge && window.HyAppBridge.openTaskAction) {
            window.HyAppBridge.openTaskAction(payload);
            return;
        }
        if (window.HyAppBridge && window.HyAppBridge.post) {
            window.HyAppBridge.post('taskAction', payload);
            return;
        }
        window.dispatchEvent(
            new CustomEvent('hyapp:task-action', {
                detail: payload,
            })
        );
    }

    function showToast(message) {
        if (window.HyAppToast && window.HyAppToast.show) {
            window.HyAppToast.show(message);
            return;
        }
        window.dispatchEvent(
            new CustomEvent('hyapp:toast', {
                detail: { message: message },
            })
        );
    }

    function onTaskAction(event) {
        var button = event.target.closest('[data-task-action]');
        if (!button) return;
        var item = findTask(button.getAttribute('data-task-action'));
        if (!item) return;
        if (item.claimable) {
            claimTask(item);
            return;
        }
        goTask(item);
    }

    function updateScale() {
        document.documentElement.style.setProperty('--app-scale', '1');
        if (!viewport || !page) return;
        var height = Math.max(page.scrollHeight, window.innerHeight || 0);
        viewport.style.minHeight = height + 'px';
        document.body.style.minHeight = height + 'px';
    }

    function bindEvents() {
        page.addEventListener('click', onTaskAction);
        window.addEventListener('resize', updateScale);
        if (backButton) {
            backButton.addEventListener('click', function () {
                if (window.HyAppBridge && window.HyAppBridge.back) {
                    window.HyAppBridge.back();
                    return;
                }
                window.history.back();
            });
        }
    }

    bindEvents();
    loadTasks();
    if (window.HyAppBridge && window.HyAppBridge.ready) {
        window.HyAppBridge.ready({ page: 'tasks' });
    }
})();
