<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>应用市场</title>
    <link rel="stylesheet" href="{{ asset('CmsProUi/component/pear/css/pear.css') }}">
    <link rel="stylesheet" href="{{ asset('CmsProUi/font-awesome/4.7.0/css/font-awesome.min.css') }}">
    <link rel="stylesheet" href="{{ asset('Admin/css/admin.css') }}">
    <link rel="stylesheet" href="{{ asset('Admin/css/variables.css') }}">
    <link rel="stylesheet" href="{{ asset('Admin/css/reset.css') }}">
    <script src="{{ asset('CmsProUi/component/qrcodejs/qrcode.min.js') }}"></script>
    <style>
    .layui-layer-loading .layui-layer-content { white-space: nowrap; }
    .market-wrap { display: flex; min-height: calc(100vh - 120px); }
    .market-sidebar { width: 200px; background: #fff; border-right: 1px solid #e6e6e6; padding: 15px 0; flex-shrink: 0; }
    .market-sidebar h3 { padding: 0 20px; font-size: 14px; color: #333; margin-bottom: 10px; }
    .market-sidebar-item { display: block; padding: 10px 20px; font-size: 13px; color: #666; cursor: pointer; transition: all 0.2s; }
    .market-sidebar-item:hover { background: #f5f5f5; color: #333; }
    .market-sidebar-item.active { background: #e8f5e9; color: #4caf50; font-weight: 600; border-right: 3px solid #4caf50; }
    .market-main { flex: 1; padding: 15px 20px; background: #fafafa; }
    .market-search { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; }
    .market-search-input { display: flex; gap: 8px; width: 360px; flex-shrink: 0; }
    .market-search-input input { flex: 1; }
    /* 排序按钮组 —— Segmented Control */
    .market-sort-bar { display: flex; align-items: center; gap: 8px; margin-left: auto; }
    .market-sort-label { font-size: 13px; color: #666; }
    .market-sort-group { display: inline-flex; padding: 3px; background: #f0f0f0; border-radius: 6px; gap: 2px; }
    .market-sort-btn { display: inline-flex; align-items: center; gap: 4px; padding: 5px 12px; border: none; background: transparent; color: #666; font-size: 13px; border-radius: 4px; cursor: pointer; transition: color 0.2s, background 0.2s, box-shadow 0.2s; white-space: nowrap; text-decoration: none; }
    .market-sort-btn:hover { color: #1e9fff; }
    .market-sort-btn.active { background: #fff; color: #1e9fff; box-shadow: 0 1px 3px rgba(0,0,0,0.08); }
    .market-sort-btn .arrow { font-size: 12px; line-height: 1; }
    .market-app-card { background: #fff; border-radius: 8px; border: 1px solid #e6e6e6; padding: 20px; margin-bottom: 15px; display: flex; gap: 15px; transition: all 0.2s; }
    .market-app-card:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
    .market-app-icon { width: 56px; height: 56px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 28px; color: #fff; flex-shrink: 0; background: #f0f0f0; overflow: hidden; }
    .market-app-featured-badge { position: absolute; top: -6px; right: -6px; background: linear-gradient(135deg, #f97316, #ef4444); color: #fff; font-size: 10px; font-weight: 700; padding: 1px 6px; border-radius: 8px 8px 8px 2px; line-height: 1.5; white-space: nowrap; box-shadow: 0 2px 4px rgba(239,68,68,0.3); z-index: 1; }
    .market-app-info { flex: 1; }
    .market-app-name { font-size: 16px; font-weight: 600; color: #333; margin-bottom: 4px; }
    .market-app-desc { font-size: 13px; color: #999; margin-bottom: 8px; }
    .market-app-meta { display: flex; gap: 15px; font-size: 12px; color: #999; align-items: center; }
    .market-app-meta .rating { color: #ff9800; }
    .market-app-action { display: flex; align-items: center; flex-shrink: 0; }
    .market-empty { text-align: center; padding: 60px 0; color: #999; }
    .market-empty i { font-size: 48px; margin-bottom: 12px; display: block; }
    .market-offline { text-align: center; padding: 40px 0; color: #999; }
    .market-app-icon.clickable { cursor: pointer; }
    .market-app-name.clickable { cursor: pointer; }
    .market-app-name.clickable:hover { color: #4caf50; }
    .app-detail-header { display: flex; gap: 16px; align-items: center; padding-bottom: 16px; border-bottom: 1px solid #eee; margin-bottom: 16px; }
    .app-detail-icon { width: 64px; height: 64px; border-radius: 14px; display: flex; align-items: center; justify-content: center; font-size: 32px; color: #fff; flex-shrink: 0; background: #f0f0f0; overflow: hidden; }
    .app-detail-title { font-size: 20px; font-weight: 600; color: #333; }
    .app-detail-author { font-size: 13px; color: #999; margin-top: 4px; }
    .app-detail-author a { color: #2196f3; text-decoration: none; }
    .app-detail-author a:hover { text-decoration: underline; }
    .app-detail-section { margin-bottom: 16px; }
    .app-detail-section-title { font-size: 14px; font-weight: 600; color: #333; margin-bottom: 8px; padding-bottom: 6px; border-bottom: 1px solid #f0f0f0; }
    .app-detail-desc { font-size: 13px; color: #666; line-height: 1.8; }
    .app-detail-meta { display: flex; flex-wrap: wrap; gap: 16px; }
    .app-detail-meta-item { display: flex; align-items: center; gap: 4px; font-size: 13px; color: #666; }
    .app-detail-meta-item .label { color: #999; }
    .app-detail-meta-item .value { color: #333; font-weight: 500; }
    .app-detail-meta-item .value.free { color: #4caf50; }
    .app-detail-meta-item .value.paid { color: #ff9800; }
    .app-detail-meta-item .value.rating { color: #ff9800; }
    .app-detail-screenshots { display: flex; gap: 10px; overflow-x: auto; padding-bottom: 6px; }
    .app-detail-screenshots img { height: 160px; border-radius: 6px; border: 1px solid #eee; cursor: pointer; transition: transform 0.2s; flex-shrink: 0; }
    .app-detail-screenshots img:hover { transform: scale(1.03); }
    .app-detail-versions { width: 100%; border-collapse: collapse; font-size: 13px; }
    .app-detail-versions th { background: #f5f5f5; padding: 8px 10px; text-align: left; color: #666; font-weight: 600; }
    .app-detail-versions td { padding: 8px 10px; border-bottom: 1px solid #f0f0f0; color: #333; }
    .app-detail-footer { display: flex; justify-content: flex-end; gap: 10px; padding-top: 16px; border-top: 1px solid #eee; margin-top: 16px; }
    .app-detail-require { font-size: 13px; color: #666; }
    .app-detail-require span { display: inline-block; background: #f5f5f5; padding: 2px 8px; border-radius: 3px; margin-right: 6px; margin-bottom: 4px; }
    </style>
</head>
<body>
<div class="pear-container">
    <div class="layui-card">
        <div class="layui-card-body" style="padding:0;">
            <div style="display:flex;justify-content:space-between;align-items:center;padding:0 20px;background:#fff;border-bottom:1px solid #e6e6e6;">
                <div class="market-tabs" style="display:flex;gap:0;">
                    <div class="market-tab" data-tab="market" style="padding:12px 20px;font-size:14px;cursor:pointer;border-bottom:2px solid #4caf50;color:#4caf50;font-weight:600;transition:all 0.2s;"><i class="fa fa-store" style="margin-right:5px;"></i> 应用市场</div>
                    <div class="market-tab" data-tab="purchased" style="padding:12px 20px;font-size:14px;cursor:pointer;border-bottom:2px solid transparent;color:#666;transition:all 0.2s;"><i class="fa fa-download" style="margin-right:5px;"></i> 已购应用</div>
                </div>
                <div>
                    <a href="//v5.cmspro.cn/market/developer/apps" target="_blank" class="layui-btn layui-btn-sm layui-btn-normal"><i class="fa fa-user"></i> 开发者中心</a>
                </div>
            </div>
            <div class="market-wrap">
                <div class="market-sidebar">
                    <div id="categoryList">
                        <div class="market-sidebar-item active" data-category="">全部</div>
                    </div>
                </div>
                <div class="market-main">
                    <div id="siteUnregisteredTip" style="display:none;background:#fff7e6;border:1px solid #ffd591;border-radius:8px;padding:15px 20px;margin-bottom:15px;">
                        <div style="display:flex;align-items:center;gap:15px;">
                            <i class="fa fa-exclamation-triangle" style="font-size:24px;color:#faad14;"></i>
                            <div style="flex:1;">
                                <div style="font-size:14px;font-weight:600;color:#d46b08;">站点未注册</div>
                                <div style="font-size:12px;color:#ad6800;margin-top:4px;">购买付费应用前需先注册站点身份到 v5.cmspro.cn</div>
                            </div>
                            <button class="layui-btn layui-btn-sm layui-btn-warm" id="btnRegisterSite"><i class="fa fa-link"></i> 立即注册</button>
                        </div>
                    </div>
                    <div id="siteMismatchTip" style="display:none;background:#fff7e6;border:1px solid #ffd591;border-radius:8px;padding:15px 20px;margin-bottom:15px;">
                        <div style="display:flex;align-items:center;gap:15px;">
                            <i class="fa fa-exclamation-triangle" style="font-size:24px;color:#faad14;"></i>
                            <div style="flex:1;">
                                <div style="font-size:14px;font-weight:600;color:#d46b08;">域名不一致</div>
                                <div style="font-size:12px;color:#ad6800;margin-top:4px;" id="mismatchDetail"></div>
                            </div>
                            <button class="layui-btn layui-btn-sm" id="btnSyncSite" style="margin-right:8px;"><i class="fa fa-cloud-upload"></i> 同步到服务端</button>
                            <button class="layui-btn layui-btn-sm layui-btn-warm" id="btnReregisterSite"><i class="fa fa-refresh"></i> 重新注册</button>
                        </div>
                    </div>
                    <div class="market-search">
                        <div class="market-search-input">
                            <input type="text" id="searchKeyword" class="layui-input" placeholder="搜索应用...">
                            <button class="layui-btn" id="btnSearch"><i class="fa fa-search"></i> 搜索</button>
                        </div>
                        <div class="market-sort-bar">
                            <span class="market-sort-label">排序</span>
                            <div class="market-sort-group" id="marketSortGroup">
                                <a href="javascript:;" class="market-sort-btn active" data-sort="time">时间<span class="arrow">↓</span></a>
                                <a href="javascript:;" class="market-sort-btn" data-sort="downloads">安装量</a>
                                <a href="javascript:;" class="market-sort-btn" data-sort="views">访问量</a>
                                <a href="javascript:;" class="market-sort-btn" data-sort="rating">评分</a>
                            </div>
                        </div>
                    </div>
                    <div id="marketList"></div>
                    <div id="marketEmpty" class="market-empty" style="display:none;">
                        <i class="fa fa-shopping-bag"></i>
                        <p>暂无应用</p>
                        <p style="font-size:12px;margin-top:5px;">前往"开发者中心"提交您的应用</p>
                    </div>
                    <div id="marketOffline" class="market-offline" style="display:none;">
                        <i class="fa fa-plug" style="font-size:36px;display:block;margin-bottom:10px;"></i>
                        <p>应用市场暂不可用</p>
                        <p style="font-size:12px;">请检查网络连接或联系管理员</p>
                    </div>
                    <div id="marketPager" style="text-align:center;margin-top:15px;"></div>
                </div>
            </div>
        </div>
    </div>
</div>

<script src="{{ asset('CmsProUi/component/layui/layui.js') }}"></script>
<script src="{{ asset('CmsProUi/component/pear/pear.js') }}"></script>
<script>
layui.use(['jquery', 'layer', 'laypage'], function(){
    var $ = layui.jquery,
        layer = layui.layer,
        laypage = layui.laypage;

    $.ajaxSetup({
        headers: {
            'X-CSRF-TOKEN': '{{ csrf_token() }}'
        },
        statusCode: {
            401: function() {
                layer.msg('登录已过期，请重新登录', {icon: 2, time: 1500}, function() {
                    window.location.href = '/admin/login?redirect=' + encodeURIComponent(window.location.pathname + window.location.search);
                });
            }
        }
    });

    var currentCategory = '';
    var currentKeyword = '';
    var currentPage = 1;
    var currentTab = 'market';
    var purchasedItems = []; // 已购应用全部数据（客户端分页用）
    // 排序状态：sort 字段（time/downloads/views/rating），order 方向（asc/desc）
    var currentSort = 'time';
    var currentOrder = 'desc';

    function switchTab(tab) {
        currentTab = tab;
        $('.market-tab').each(function() {
            var isActive = $(this).data('tab') === tab;
            $(this).css({
                'border-bottom': '2px solid ' + (isActive ? '#4caf50' : 'transparent'),
                'color': isActive ? '#4caf50' : '#666',
                'font-weight': isActive ? '600' : 'normal'
            });
        });
        // 已购应用 Tab 隐藏分类侧栏和搜索栏
        if (tab === 'purchased') {
            $('.market-sidebar').hide();
            $('.market-search').hide();
        } else {
            $('.market-sidebar').show();
            $('.market-search').show();
        }
        // 清空已购缓存，切换时重新加载
        purchasedItems = [];
        loadMarketApps(1);
    }
    function compareVersions(v1, v2) {
        var parts1 = (v1 || '0').split('.');
        var parts2 = (v2 || '0').split('.');
        var len = Math.max(parts1.length, parts2.length);
        for (var i = 0; i < len; i++) {
            var n1 = parseInt(parts1[i]) || 0;
            var n2 = parseInt(parts2[i]) || 0;
            if (n1 < n2) return -1;
            if (n1 > n2) return 1;
        }
        return 0;
    }

    var iconColors = ['#4caf50','#2196f3','#ff9800','#9c27b0','#e91e63','#00bcd4','#795548','#607d8b'];

    function resolveIconUrl(url) {
        if (!url) return '';
        if (/^https?:\/\//i.test(url)) return url;
        return '//v5.cmspro.cn' + (url.charAt(0) === '/' ? url : '/' + url);
    }

    var installedApps = {};
    var purchasedApps = {};
    var installedAppsReady = $.get('/api/admin/apps').then(function(res) {
        if (res.code === 0) {
            (res.data || []).forEach(function(app) {
                installedApps[app.app_id.toLowerCase()] = app.version;
            });
        }
        // 返回内层 promise，确保 installedAppsReady 等待两个请求都完成
        return $.get('/api/admin/market/purchase/list', function(res) {
            if (res.code === 0 && res.data) {
                (res.data || []).forEach(function(p) {
                    purchasedApps[(p.app_id || '').toLowerCase()] = true;
                });
            }
        });
    });

    function loadCategories() {
        $.get('/api/admin/market/categories', function(res) {
            if (res.code !== 0 || !res.data) return;
            var html = '<div class="market-sidebar-item active" data-category="">全部</div>';
            (res.data || []).forEach(function(cat) {
                html += '<div class="market-sidebar-item" data-category="'+cat.code+'">'
                    + (cat.icon ? '<i class="'+cat.icon+'" style="margin-right:5px;"></i>' : '')
                    + cat.name + '</div>';
            });
            $('#categoryList').html(html);
            $('.market-sidebar-item').on('click', function() {
                $('.market-sidebar-item').removeClass('active');
                $(this).addClass('active');
                currentCategory = $(this).data('category');
                loadMarketApps(1);
            });
        });
    }

    loadCategories();

    // 检查站点注册状态
    $.get('/api/admin/market/site/status', function(res) {
        if (res.code === 0 && res.data) {
            if (!res.data.registered) {
                // 未注册
                $('#siteUnregisteredTip').show();
            } else if (res.data.domain_match === false) {
                // 域名不一致
                var localDomain = res.data.domain || '';
                var remoteDomain = res.data.remote_domain || '';
                $('#mismatchDetail').html('本地域名 <b>' + localDomain + '</b> 与服务端记录 <b>' + remoteDomain + '</b> 不一致，可能是域名变更或重装系统导致。请选择"同步到服务端"将本地信息更新到服务端，或"重新注册"重新验证。');
                $('#siteMismatchTip').show();
            }
        }
    });

    // 注册站点
    $('#btnRegisterSite').on('click', function() {
        doRegister(false);
    });

    function doRegister(force) {
        var btn = $('#btnRegisterSite');
        btn.attr('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> 注册中...');
        var params = {};
        if (force) params.force = true;
        $.post('/api/admin/market/site/register', params, function(res) {
            btn.attr('disabled', false).html('<i class="fa fa-link"></i> 立即注册');
            if (res.code === 0 && res.data) {
                // 域名验证失败（内网环境），提示人工确认
                if (res.data.verify_failed) {
                    var oldDomain = res.data.old_domain || '';
                    var newDomain = res.data.new_domain || '';
                    layer.open({
                        type: 1,
                        title: '域名验证失败',
                        area: ['520px', '320px'],
                        content: '<div style="padding:25px;">'
                            + '<div style="color:#faad14;font-size:15px;font-weight:600;margin-bottom:15px;"><i class="fa fa-exclamation-triangle"></i> 无法通过公网验证域名</div>'
                            + '<div style="font-size:13px;color:#666;margin-bottom:10px;">可能是内网环境或站点无法从公网访问。服务端记录的域名为 <b>' + oldDomain + '</b>，当前域名为 <b>' + newDomain + '</b>。</div>'
                            + '<div style="font-size:13px;color:#999;margin-bottom:15px;">如果确认当前域名正确，可以跳过验证直接注册（人工确认模式）。</div>'
                            + '<div style="background:#fff7e6;border:1px solid #ffd591;border-radius:4px;padding:10px;font-size:12px;color:#d46b08;"><i class="fa fa-info-circle"></i> 内网环境（localhost/127.0.0.1/内网IP）可以正常使用，但无法通过公网验证。</div>'
                            + '</div>',
                        btn: ['跳过验证，直接注册', '取消'],
                        yes: function(index) {
                            layer.close(index);
                            doRegister(true); // force=true
                        }
                    });
                    return;
                }

                // 注册成功
                var siteKey = res.data.site_key || '';
                var autoWritten = res.data.auto_written;

                if (autoWritten) {
                    layer.open({
                        type: 1,
                        title: '站点注册成功',
                        area: ['500px', '260px'],
                        content: '<div style="padding:25px;">'
                            + '<div style="color:#52c41a;font-size:16px;font-weight:600;margin-bottom:15px;"><i class="fa fa-check-circle"></i> 站点注册成功！</div>'
                            + '<div style="background:#f6ffed;border:1px solid #b7eb8f;border-radius:6px;padding:15px;margin-bottom:15px;">'
                            + '<div style="font-size:13px;color:#389e0d;"><i class="fa fa-check"></i> site_key 已自动写入 .env 文件</div>'
                            + '<div style="font-size:12px;color:#666;margin-top:6px;">站点密钥：</div>'
+ '<code style="display:block;background:#fff;padding:10px;border-radius:4px;font-size:13px;color:#d73a49;word-break:break-all;margin-top:4px;">CMSPRO_SITE_KEY=' + siteKey + '</code>'
                            + '</div>'
                            + '<div style="font-size:13px;color:#faad14;"><i class="fa fa-exclamation-circle"></i> 需重启服务使配置生效，重启后刷新此页面即可购买应用。</div>'
                            + '</div>',
                        btn: ['重启后刷新页面'],
                        yes: function(index) {
                            layer.close(index);
                            location.reload();
                        }
                    });
                } else {
                    layer.msg('注册成功，请重启服务', {icon: 1});
                    setTimeout(function() { location.reload(); }, 2000);
                }
            } else {
                layer.msg(res.message || '注册失败', {icon: 2});
            }
        }).fail(function() {
            btn.attr('disabled', false).html('<i class="fa fa-link"></i> 立即注册');
            layer.msg('注册失败，请检查网络连接', {icon: 2});
        });
    }

    // 同步站点身份到服务端（域名变更后）
    $('#btnSyncSite').on('click', function() {
        var btn = $(this);
        btn.attr('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> 同步中...');
        $.post('/api/admin/market/site/sync', function(res) {
            btn.attr('disabled', false).html('<i class="fa fa-cloud-upload"></i> 同步到服务端');
            if (res.code === 0) {
                layer.msg('站点身份已同步到服务端', {icon: 1});
                setTimeout(function() { location.reload(); }, 1500);
            } else {
                layer.msg(res.message || '同步失败', {icon: 2});
            }
        }).fail(function() {
            btn.attr('disabled', false).html('<i class="fa fa-cloud-upload"></i> 同步到服务端');
            layer.msg('同步失败', {icon: 2});
        });
    });

    // 重新注册站点
    $('#btnReregisterSite').on('click', function() {
        $('#btnRegisterSite').trigger('click');
    });

    function loadMarketApps(page) {
        currentPage = page || 1;

        if (currentTab === 'purchased') {
            // 已购应用：只拉一次全部数据，后续客户端分页
            if (purchasedItems.length > 0) {
                // 已有缓存数据，直接客户端分页
                var total = purchasedItems.length;
                var perPage = 10;
                var start = (currentPage - 1) * perPage;
                var pageItems = purchasedItems.slice(start, start + perPage);
                renderMarketList(pageItems, {
                    total: total,
                    per_page: perPage,
                    current_page: currentPage,
                    last_page: Math.ceil(total / perPage) || 1
                });
                return;
            }

            // 首次加载：拉取全部应用并过滤
            var loadIdx = layer.load(2);
            $.get('/api/admin/market/apps', { page: 1, per_page: 200 }, function(res) {
                layer.close(loadIdx);
                if (res.code !== 0) {
                    $('#marketList').html('');
                    $('#marketOffline').show();
                    return;
                }
                $('#marketOffline').hide();

                var items = (res.data || {}).items || [];

                // 过滤已购应用并缓存
                purchasedItems = items.filter(function(app) {
                    return purchasedApps[(app.app_id || '').toLowerCase()] === true;
                });

                // 客户端分页
                var total = purchasedItems.length;
                var perPage = 10;
                var start = 0;
                var pageItems = purchasedItems.slice(start, start + perPage);

                $.when(installedAppsReady).then(function() {
                    renderMarketList(pageItems, {
                        total: total,
                        per_page: perPage,
                        current_page: 1,
                        last_page: Math.ceil(total / perPage) || 1
                    });
                });
            }).fail(function() {
                layer.close(loadIdx);
                $('#marketList').html('');
                $('#marketOffline').show();
            });
            return;
        }

        // 应用市场 Tab：正常分页请求
        var params = { page: currentPage, per_page: 10 };
        if (currentCategory) params.category = currentCategory;
        if (currentKeyword) params.keyword = currentKeyword;
        params.sort = currentSort;
        params.order = currentOrder;

        var loadIdx = layer.load(2);
        $.get('/api/admin/market/apps', params, function(res) {
            layer.close(loadIdx);
            if (res.code !== 0) {
                $('#marketList').html('');
                $('#marketOffline').show();
                return;
            }
            $('#marketOffline').hide();

            var data = res.data || {};
            var items = data.items || [];
            var pagination = data.pagination || {};

            $.when(installedAppsReady).then(function() {
                renderMarketList(items, pagination);
            });
        }).fail(function() {
            layer.close(loadIdx);
            $('#marketList').html('');
            $('#marketOffline').show();
        });
    }

    function renderMarketList(items, pagination) {
        if (items.length === 0) {
            $('#marketList').html(currentTab === 'purchased'
                ? '<div class="market-empty"><i class="fa fa-download"></i><div>暂无已购应用</div></div>'
                : '');
            $('#marketEmpty').toggle(currentTab !== 'purchased');
            $('#marketPager').html('');
            return;
        }
        $('#marketEmpty').hide();

        var html = '';
        items.forEach(function(app, idx) {
            var appIdLower = (app.app_id || '').toLowerCase();
            var isInstalled = installedApps[appIdLower] !== undefined;
            var hasUpdate = isInstalled && compareVersions(installedApps[appIdLower], app.latest_version) < 0;
            var color = iconColors[idx % iconColors.length];

            var actionBtn = '';
            if (hasUpdate) {
                actionBtn = '<button class="layui-btn layui-btn-sm layui-btn-warm" onclick="installFromMarket(\''+app.app_id+'\')">更新</button>';
            } else if (isInstalled) {
                actionBtn = '<button class="layui-btn layui-btn-sm layui-btn-disabled">已安装</button>';
            } else if (parseFloat(app.price) > 0) {
                if (purchasedApps[appIdLower]) {
                    actionBtn = '<button class="layui-btn layui-btn-sm" onclick="installFromMarket(\''+app.app_id+'\')">安装</button>';
                } else {
                    actionBtn = '<button class="layui-btn layui-btn-sm layui-btn-normal" onclick="purchaseApp(\''+app.app_id+'\', '+parseFloat(app.price).toFixed(2)+')">¥'+parseFloat(app.price).toFixed(2)+' 购买</button>';
                }
            } else {
                actionBtn = '<button class="layui-btn layui-btn-sm" onclick="installFromMarket(\''+app.app_id+'\')">安装</button>';
            }

            html += '<div class="market-app-card">'
                + '<div style="position:relative;display:inline-block;">'
                + '<div class="market-app-icon clickable" onclick="showAppDetail(\''+app.app_id+'\')">' + (app.icon ? '<img src="'+resolveIconUrl(app.icon)+'" style="width:100%;height:100%;object-fit:cover;border-radius:12px;" onerror="this.style.display=\'none\';this.nextElementSibling||(this.parentNode.innerHTML+=\'<i class=\\\'fa fa-puzzle-piece\\\'></i>\');">' : '<i class="fa fa-puzzle-piece"></i>') + '</div>'
                + (app.is_featured ? '<span class="market-app-featured-badge">推荐</span>' : '')
                + '</div>'
                + '<div class="market-app-info">'
                + '<div class="market-app-name clickable" onclick="showAppDetail(\''+app.app_id+'\')">'+app.name+'</div>'
                + '<div class="market-app-desc">'+(app.description||'')+'</div>'
                + '<div class="market-app-meta">'
                + (app.category ? '<span style="background:#f0f0f0;padding:1px 6px;border-radius:3px;font-size:11px;">'+app.category.name+'</span>' : '')
                + (app.price > 0 ? '<span style="color:#ff9800;font-weight:600;">¥'+parseFloat(app.price).toFixed(2)+'</span>' : '<span style="color:#4caf50;">免费</span>')
                + '<span>v'+app.latest_version+'</span>'
                + '<span>by '+app.author+'</span>'
                + '<span class="rating">★'+(app.rating != null ? parseFloat(app.rating).toFixed(1) : '-')+'</span>'
                + '<span>下载 '+(app.downloads||0)+'</span>'
                + (isInstalled ? '<span style="color:#4caf50;">已安装 v'+installedApps[appIdLower]+'</span>' : '')
                + '</div>'
                + '</div>'
                + '<div class="market-app-action">'+actionBtn+'</div>'
                + '</div>';
        });

        $('#marketList').html(html);

        if (pagination.total > pagination.per_page) {
            laypage.render({
                elem: 'marketPager',
                count: pagination.total,
                limit: pagination.per_page,
                curr: currentPage,
                jump: function(obj, first) {
                    if (!first) loadMarketApps(obj.curr);
                }
            });
        } else {
            $('#marketPager').html('');
        }
    }

    loadMarketApps(1);

    // Tab 切换
    $(document).on('click', '.market-tab', function() {
        switchTab($(this).data('tab'));
    });

    $('.market-sidebar-item').on('click', function() {
        $('.market-sidebar-item').removeClass('active');
        $(this).addClass('active');
        currentCategory = $(this).data('category');
        loadMarketApps(1);
    });

    $('#btnSearch').on('click', function() {
        currentKeyword = $('#searchKeyword').val().trim();
        loadMarketApps(1);
    });

    $('#searchKeyword').on('keydown', function(e) {
        if (e.keyCode === 13) {
            currentKeyword = $(this).val().trim();
            loadMarketApps(1);
        }
    });

    // 排序按钮：同字段点击切换升降序，不同字段默认降序
    $('#marketSortGroup').on('click', '.market-sort-btn', function() {
        var $btn = $(this);
        var sort = $btn.data('sort');
        if (sort === currentSort) {
            currentOrder = currentOrder === 'desc' ? 'asc' : 'desc';
        } else {
            currentSort = sort;
            currentOrder = 'desc';
        }
        // 更新按钮 UI：清除所有 active 和箭头，给当前按钮加 active 和方向箭头
        $('#marketSortGroup .market-sort-btn').removeClass('active').find('.arrow').remove();
        $btn.addClass('active').append('<span class="arrow">' + (currentOrder === 'asc' ? '↑' : '↓') + '</span>');
        loadMarketApps(1);
    });

    window.installFromMarket = function(appId) {
        layer.confirm('确定要从市场安装此应用吗？', {icon:3}, function(idx) {
            layer.close(idx);
            var loadIdx = layer.load(2, {content:'正在下载安装包...', time:0});
            $.post('/api/admin/market/install/'+appId, function(res) {
                layer.close(loadIdx);
                if (res.code === 0) {
                    layer.msg('安装成功', {icon:1});
                    // 重新拉取已安装应用列表，获取真实版本号，避免误判为可更新
                    $.get('/api/admin/apps', function(res2) {
                        installedApps = {};
                        if (res2.code === 0) {
                            (res2.data || []).forEach(function(app) {
                                installedApps[app.app_id.toLowerCase()] = app.version;
                            });
                        }
                        loadMarketApps(currentPage);
                    });
                } else {
                    layer.msg(res.message, {icon:2});
                }
            }).fail(function() {
                layer.close(loadIdx);
                layer.msg('安装失败，请检查网络连接', {icon:2});
            });
        });
    };

    window.showAppDetail = function(appId) {
        var loadIdx = layer.load(2);
        $.get('/api/admin/market/apps/'+appId, function(res) {
            layer.close(loadIdx);
            if (res.code !== 0 || !res.data) {
                layer.msg(res.message || '获取应用详情失败', {icon:2});
                return;
            }
            var app = res.data;
            var appIdLower = (app.app_id || '').toLowerCase();
            var isInstalled = installedApps[appIdLower] !== undefined;
            var hasUpdate = isInstalled && installedApps[appIdLower] !== app.latest_version;
            var color = iconColors[0];

            var html = '<div style="padding:15px 15px;">';

            html += '<div class="app-detail-header">';
            html += '<div class="app-detail-icon">' + (app.icon ? '<img src="'+resolveIconUrl(app.icon)+'" style="width:100%;height:100%;object-fit:cover;border-radius:14px;" onerror="this.style.display=\'none\';this.nextElementSibling||(this.parentNode.innerHTML+=\'<i class=\\\'fa fa-puzzle-piece\\\'></i>\');">' : '<i class="fa fa-puzzle-piece"></i>') + '</div>';
            html += '<div>';
            html += '<div class="app-detail-title">'+app.name+'</div>';
            html += '<div class="app-detail-author">by '+(app.author_url ? '<a href="'+app.author_url+'" target="_blank">'+app.author+'</a>' : app.author)+'</div>';
            html += '</div></div>';

            html += '<div class="app-detail-section">';
            html += '<div class="app-detail-section-title">基本信息</div>';
            html += '<div class="app-detail-meta">';
            if (app.category) {
                html += '<div class="app-detail-meta-item"><span class="label">分类：</span><span class="value">'+app.category.name+'</span></div>';
            }
            html += '<div class="app-detail-meta-item"><span class="label">最新版本：</span><span class="value">v'+app.latest_version+'</span></div>';
            html += '<div class="app-detail-meta-item"><span class="label">价格：</span><span class="value '+(app.price > 0 ? 'paid' : 'free')+'">'+(app.price > 0 ? '¥'+parseFloat(app.price).toFixed(2) : '免费')+'</span></div>';
            html += '<div class="app-detail-meta-item"><span class="label">评分：</span><span class="value rating">★'+(app.rating != null ? parseFloat(app.rating).toFixed(1) : '-')+'</span></div>';
            html += '<div class="app-detail-meta-item"><span class="label">下载量：</span><span class="value">'+(app.downloads||0)+'</span></div>';
            html += '<div class="app-detail-meta-item"><span class="label">访问量：</span><span class="value">'+(app.view_count||0)+'</span></div>';
            if (isInstalled) {
                html += '<div class="app-detail-meta-item"><span class="label">本地版本：</span><span class="value" style="color:#4caf50;">v'+installedApps[appIdLower]+'</span></div>';
            }
            html += '</div></div>';

            if (app.cmspro_require) {
                html += '<div class="app-detail-section">';
                html += '<div class="app-detail-section-title">系统要求</div>';
                html += '<div class="app-detail-require"><span>CmsPro ≥ '+app.cmspro_require+'</span></div>';
                html += '</div>';
            }

            if (app.description) {
                html += '<div class="app-detail-section">';
                html += '<div class="app-detail-section-title">应用介绍</div>';
                html += '<div class="app-detail-desc">'+app.description+'</div>';
                html += '</div>';
            }

            if (app.screenshots && app.screenshots.length > 0) {
                html += '<div class="app-detail-section">';
                html += '<div class="app-detail-section-title">应用截图</div>';
                html += '<div class="app-detail-screenshots">';
                (app.screenshots || []).forEach(function(src, idx) {
                    var fullSrc = resolveIconUrl(src);
                    html += '<img src="'+fullSrc+'" onclick="previewMarketScreenshots('+idx+');">';
                });
                html += '</div></div>';
                // 将截图数据挂载到 window 供预览函数使用
                html += '<script>window._currentScreenshots = ' + JSON.stringify(app.screenshots.map(function(s){return resolveIconUrl(s);})) + ';<\/script>';
            }

            if (app.versions && app.versions.length > 0) {
                html += '<div class="app-detail-section">';
                html += '<div class="app-detail-section-title">版本记录</div>';
                html += '<table class="app-detail-versions"><thead><tr><th>版本</th><th>更新说明</th><th>大小</th><th>发布时间</th></tr></thead><tbody>';
                (app.versions || []).forEach(function(v) {
                    html += '<tr>';
                    html += '<td>v'+v.version+'</td>';
                    html += '<td>'+(v.changelog||'-')+'</td>';
                    html += '<td>'+(v.package_size ? (v.package_size/1024).toFixed(1)+'KB' : '-')+'</td>';
                    html += '<td>'+(v.create_time||'-')+'</td>';
                    html += '</tr>';
                });
                html += '</tbody></table></div>';
            }

            html += '<div class="app-detail-footer">';
            if (hasUpdate) {
                html += '<button class="layui-btn layui-btn-warm" onclick="layer.closeAll();setTimeout(function(){installFromMarket(\''+app.app_id+'\')},150);">更新</button>';
            } else if (isInstalled) {
                html += '<button class="layui-btn layui-btn-disabled">已安装</button>';
            } else if (parseFloat(app.price) > 0) {
                if (purchasedApps[appIdLower]) {
                    html += '<button class="layui-btn" onclick="layer.closeAll();setTimeout(function(){installFromMarket(\''+app.app_id+'\')},150);">安装</button>';
                } else {
                    html += '<button class="layui-btn layui-btn-normal" onclick="layer.closeAll();setTimeout(function(){purchaseApp(\''+app.app_id+'\', '+parseFloat(app.price).toFixed(2)+')},150);">¥'+parseFloat(app.price).toFixed(2)+' 购买安装</button>';
                }
            } else {
                html += '<button class="layui-btn" onclick="layer.closeAll();setTimeout(function(){installFromMarket(\''+app.app_id+'\')},150);">安装</button>';
            }
            html += '<button class="layui-btn layui-btn-primary" onclick="layer.closeAll()">关闭</button>';
            html += '</div>';

            html += '</div>';

            layer.open({
                type: 1,
                title: '应用详情',
                area: ['620px', '520px'],
                maxmin: true,
                shadeClose: true,
                content: html
            });
        }).fail(function() {
            layer.close(loadIdx);
            layer.msg('获取应用详情失败，请检查网络连接', {icon:2});
        });
    };

    window.purchaseApp = function(appId, price) {
        layer.open({
            type: 1,
            title: '购买应用 - ¥' + price.toFixed(2),
            area: ['420px', '440px'],
            content: '<div style="padding:20px;" id="purchasePanel">'
                + '<div style="margin-bottom:15px;">请选择支付方式：</div>'
                + '<div style="display:flex;gap:10px;flex-wrap:wrap;margin-bottom:15px;" id="payMethodBtns">'
                + '<button class="layui-btn" onclick="doPurchase(\''+appId+'\',\'wechat\')"><i class="fa fa-wechat"></i> 微信支付</button>'
                + '<button class="layui-btn layui-btn-normal" onclick="doPurchase(\''+appId+'\',\'alipay\')"><i class="fa fa-alipay"></i> 支付宝</button>'
                + '</div>'
                + '<div id="payQrCode" style="display:none;text-align:center;">'
                + '<div id="qrCodeContainer" style="display:inline-block;padding:10px;background:#fff;border:1px solid #e6e6e6;border-radius:8px;"></div>'
                + '<p id="payPriceText" style="font-size:16px;font-weight:600;color:#e74c3c;margin-top:12px;"></p>'
                + '<p style="font-size:13px;color:#666;margin-top:6px;">请使用<span id="payChannelName">手机</span>扫描二维码完成支付</p>'
                + '<p id="countdownText" style="font-size:12px;color:#999;margin-top:6px;"></p>'
                + '</div>'
                + '</div>',
            end: function() { 
                if (window.purchasePollTimer) clearInterval(window.purchasePollTimer);
                window.purchaseInProgress = false; 
            }
        });
    };

    window.doPurchase = function(appId, channel) {
        // 防重入：防止双击或重复点击导致多个倒计时定时器冲突
        if (window.purchaseInProgress) {
            layer.msg('正在处理中，请稍候...', {icon: 16, time: 1500});
            return;
        }
        window.purchaseInProgress = true;

        var loadIdx2 = layer.load(2);
        $('#payMethodBtns').hide();
        
        $.ajax({
            url: '/api/admin/market/purchase/create',
            type: 'POST',
            data: {
                app_id: appId,
                channel: channel
            },
            headers: {
                'X-CSRF-TOKEN': '{{ csrf_token() }}',
                'Content-Type': 'application/x-www-form-urlencoded',
                'Accept': 'application/json'
            },
            timeout: 30000,
            beforeSend: function(xhr) {
                layer.msg('正在创建订单...', {icon: 16, time: 0});
            }
        }).done(function(res) {
            layer.close(loadIdx2);

            if (res.code !== 0) {
                layer.msg('订单创建失败：' + (res.message || '未知错误'), {icon: 2});
                $('#payMethodBtns').show();
                window.purchaseInProgress = false;
                return;
            }
            
            var data = res.data || {};

            if (data.qr_code) {
                $('#payQrCode').show();
                $('#payChannelName').text(channel === 'wechat' ? '微信' : '支付宝');
                $('#payPriceText').text('¥' + parseFloat(data.price || 0).toFixed(2));
                $('#qrCodeContainer').html('');
                new QRCode(document.getElementById('qrCodeContainer'), {
                    text: data.qr_code,
                    width: 200,
                    height: 200,
                    colorDark: '#000000',
                    colorLight: '#ffffff',
                    correctLevel: QRCode.CorrectLevel.M
                });

                // 倒计时 5 分钟
                var remainSec = 300;
                function updateCountdown() {
                    var m = Math.floor(remainSec / 60);
                    var s = remainSec % 60;
                    $('#countdownText').text('有效期剩余 ' + m + ':' + (s < 10 ? '0' : '') + s);
                    remainSec--;
                    if (remainSec < 0) {
                        if (window.purchasePollTimer) clearInterval(window.purchasePollTimer);
                        $('#qrCodeContainer').html('<p style="color:#999;padding:20px;">二维码已过期，请重新下单</p>');
                        $('#countdownText').text('订单已超时');
                        $('#payMethodBtns').show();
                        $('#payQrCode').hide();
                    }
                }
                updateCountdown();
                var cdTimer = setInterval(updateCountdown, 1000);

                pollPurchaseStatus(appId, data.out_trade_no, cdTimer);
            } else if (data.pay_url) {
                window.open(data.pay_url, '_blank');
                pollPurchaseStatus(appId, data.out_trade_no, null);
            } else {
                layer.msg('未获取到支付信息', {icon: 2});
                $('#payMethodBtns').show();
                window.purchaseInProgress = false;
            }
        }).fail(function(xhr, status, error) {
            layer.close(loadIdx2);

            var errorMsg = '创建订单失败';
            if (xhr.status === 0) {
                errorMsg = '网络连接失败，请检查网络连接';
            } else if (xhr.status === 401) {
                errorMsg = '登录已过期，请重新登录';
                setTimeout(function() {
                    top.location.href = '/admin/login';
                }, 1500);
            } else if (xhr.status === 403) {
                errorMsg = '权限不足，无法创建订单';
            } else if (xhr.status === 422) {
                errorMsg = '请求参数不合法';
            } else if (xhr.status === 500) {
                errorMsg = '服务器内部错误';
            } else if (xhr.responseJSON) {
                errorMsg = xhr.responseJSON.message || xhr.responseJSON.error || errorMsg;
            } else if (xhr.responseText) {
                try {
                    var errorData = JSON.parse(xhr.responseText);
                    errorMsg = errorData.message || errorData.error || errorMsg;
                } catch (e) {
                    if (xhr.responseText.length < 500) {
                        errorMsg = xhr.responseText;
                    } else {
                        errorMsg = '服务器返回异常';
                    }
                }
            } else {
                errorMsg = 'HTTP ' + xhr.status + ' 错误';
            }
            
            layer.msg(errorMsg, {icon: 2});
            $('#payMethodBtns').show();
            window.purchaseInProgress = false;
        });
    };

    window.pollPurchaseStatus = function(appId, outTradeNo, cdTimer) {
        var pollCount = 0;
        var pollTimer = setInterval(function() {
            pollCount++;
            if (pollCount > 60) {
                clearInterval(pollTimer);
                if (cdTimer) clearInterval(cdTimer);
                return;
            }
            $.get('/api/admin/market/purchase/status', { out_trade_no: outTradeNo }, function(res) {
                if (res.code === 0 && res.data && res.data.paid) {
                    clearInterval(pollTimer);
                    if (cdTimer) clearInterval(cdTimer);
                    layer.closeAll();
                    layer.msg('购买成功！可前往应用列表安装', {icon: 1, time: 2500});
                    purchasedApps[appId.toLowerCase()] = true;
                    loadMarketApps(currentPage);
                }
            });
        }, 3000);
        window.purchasePollTimer = pollTimer;
    };

    // 应用截图预览（支持左右切换）
    window.previewMarketScreenshots = function(index) {
        var photos = (window._currentScreenshots || []).map(function(src, i) {
            return { alt: '截图 ' + (i + 1), src: src };
        });
        if (photos.length === 0) return;
        layer.photos({
            photos: { data: photos },
            shade: 0.8,
            anim: 5
        });
    };
});
</script>
</body>
</html>
