<!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') }}">
    <style>
        .version-card { padding: 16px; background: #fff; border-radius: 4px; margin-bottom: 12px; }
        .version-card .label { color: #666; display: inline-block; width: 80px; }
        .version-card .value { color: #333; font-weight: 500; }
        .version-card .badge { padding: 2px 8px; border-radius: 10px; font-size: 12px; margin-left: 6px; }
        .badge-green { background: #5fb878; color: #fff; }
        .badge-blue { background: #1e9fff; color: #fff; }
        .badge-orange { background: #ffb800; color: #fff; }
        .diff-tip { padding: 8px 12px; background: #fff7e6; border: 1px solid #ffd591; border-radius: 4px; margin-bottom: 10px; color: #d46b08; }
    </style>
</head>
<body>
<div class="pear-container">

    <!-- 版本信息卡 -->
    <div class="layui-card">
        <div class="layui-card-header">版本修复</div>
        <div class="layui-card-body">
            <div class="version-card">
                <div style="margin-bottom:10px;">
                    <span class="label">当前版本：</span>
                    <span class="value">{{ $currentVersion ?: '未知' }}</span>
                    @if($currentBuild)
                        <span class="badge badge-blue">Build {{ $currentBuild }}</span>
                    @endif
                </div>
                <div style="margin-bottom:10px;">
                    <span class="label">最新版本：</span>
                    <span class="value" id="latestVersion">检查中...</span>
                    <span class="badge badge-green" id="latestBadge" style="display:none;">有新版本</span>
                </div>
                <div style="margin-bottom:10px;" id="changelogBox" style="display:none;">
                    <span class="label">更新日志：</span>
                    <span id="changelogText" style="color:#666;"></span>
                </div>
                <div>
                    <button class="layui-btn" id="btnPrepare" disabled>
                        <i class="fa fa-download"></i> 下载并对比
                    </button>
                    <button class="layui-btn layui-btn-warm" id="btnRecheck">
                        <i class="fa fa-refresh"></i> 重新检查
                    </button>
                </div>
            </div>
        </div>
    </div>

    <!-- 差异文件列表 -->
    <div class="layui-card" id="diffCard" style="display:none;">
        <div class="layui-card-header">
            差异文件列表 <span id="diffCountTip" style="color:#999;font-size:13px;margin-left:10px;"></span>
        </div>
        <div class="layui-card-body">
            <div class="diff-tip">
                <i class="fa fa-info-circle"></i>
                修复仅覆盖/新增选中文件，不删除本地多余文件，不修改版本号。受保护路径（.env、config/、storage/、vendor/ 等）已自动跳过。
            </div>
            <table id="diff-table" lay-filter="diff-table"></table>
            <div style="margin-top:12px;display:flex;justify-content:space-between;align-items:center;">
                <div>
                    <button class="layui-btn layui-btn-primary" id="btnFullExecute">
                        <i class="fa fa-refresh"></i> 全量修复
                    </button>
                </div>
                <div>
                    <button class="layui-btn" id="btnExecute">
                        <i class="fa fa-wrench"></i> 修复选中
                    </button>
                    <button class="layui-btn layui-btn-normal" id="btnCleanup">
                        <i class="fa fa-trash"></i> 清理临时文件
                    </button>
                </div>
            </div>
        </div>
    </div>

</div>

<script type="text/html" id="diff-status-tpl">
@verbatim
{{# if(d.status === 'added'){ }}
    <span class="layui-badge layui-bg-green">新增</span>
{{# } else { }}
    <span class="layui-badge layui-bg-orange">修改</span>
{{# } }}
@endverbatim
</script>

<script type="text/html" id="diff-hash-tpl">
@verbatim
    <span title="{{ d.local_hash }}">{{ d.local_hash ? d.local_hash.substring(0, 12) + '...' : '-' }}</span>
@endverbatim
</script>

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

    $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' } });

    var latestVersion = '';
    var diffData = [];

    // 检查最新版本
    function checkLatest() {
        $('#latestVersion').text('检查中...');
        $('#btnPrepare').attr('disabled', true);

        $.get('/admin/versionmgr/api/repair/check', function(res) {
            if (res.code !== 0) {
                $('#latestVersion').html('<span style="color:red;">' + res.message + '</span>');
                return;
            }
            var data = res.data;
            latestVersion = data.latest_version;
            $('#latestVersion').text(data.latest_version + (data.latest_build ? ' (Build ' + data.latest_build + ')' : ''));
            $('#btnPrepare').attr('disabled', false);

            if (data.has_update) {
                $('#latestBadge').show();
            } else {
                $('#latestBadge').hide();
            }

            if (data.changelog) {
                $('#changelogBox').show();
                $('#changelogText').text(data.changelog);
            }
        }).fail(function() {
            $('#latestVersion').html('<span style="color:red;">检查失败</span>');
        });
    }

    // 下载并对比
    var pollTimer = null;
    var progressLayerIdx = null;
    var prepareDone = false;

    // 进度状态映射
    var stageMap = {
        'downloading':       { pct: 15, text: '正在下载...', step: '📦 正在下载程序包' },
        'extracting':        { pct: 45, text: '正在解压...', step: '📂 正在解压文件' },
        'comparing':         { pct: 75, text: '正在对比...', step: '🔍 正在比对文件差异' },
        'awaiting_selection':{ pct: 100,text: '对比完成',    step: '✅ 对比完成' },
        'failed':            { pct: 0,  text: '失败',        step: '❌ 处理失败' }
    };

    function openProgressPanel() {
        progressLayerIdx = layer.open({
            type: 1,
            title: '下载与对比进度',
            shade: [0.5, '#000'],
            shadeClose: 0,
            closeBtn: 0,
            area: ['480px', '200px'],
            content: '' +
                '<div style="padding:25px 25px 10px;">' +
                '  <div id="repairStepName" style="font-size:15px;margin-bottom:14px;">准备开始...</div>' +
                '  <div class="layui-progress" lay-filter="repairBar">' +
                '    <div class="layui-progress-bar layui-bg-blue" lay-percent="0%"></div>' +
                '  </div>' +
                '  <div id="repairProgressTip" style="margin-top:12px;color:#999;font-size:13px;"></div>' +
                '</div>',
            success: function(layero) {
                layui.element.render('progress');
            }
        });
    }

    function updateProgress(status, detail) {
        var info = stageMap[status] || { pct: 0, text: status, step: status };
        $('#repairStepName').text(info.step);
        $('#repairProgressTip').text(info.text);

        var $bar = $('.layui-progress[lay-filter="repairBar"] .layui-progress-bar');
        $bar.attr('lay-percent', info.pct + '%');
        $bar.css('width', info.pct + '%');
        $bar.text(info.pct + '%');
    }

    function startPolling() {
        if (pollTimer) clearInterval(pollTimer);
        pollTimer = setInterval(function() {
            if (prepareDone) {
                clearInterval(pollTimer);
                pollTimer = null;
                return;
            }
            $.get('/admin/versionmgr/api/repair/status', function(res) {
                if (res.code !== 0) return;
                var data = res.data;
                updateProgress(data.status, data);

                if (data.status === 'failed') {
                    clearInterval(pollTimer);
                    pollTimer = null;
                }
            });
        }, 1500);
    }

    function stopPolling() {
        if (pollTimer) {
            clearInterval(pollTimer);
            pollTimer = null;
        }
    }

    $('#btnPrepare').on('click', function() {
        if (!latestVersion) {
            layer.msg('未获取到最新版本号', {icon: 2});
            return;
        }

        layer.confirm('确定下载完整程序包并与本地对比？此操作可能需要几分钟。', {icon: 3}, function(idx) {
            layer.close(idx);

            prepareDone = false;
            openProgressPanel();
            startPolling();

            $.post('/admin/versionmgr/api/repair/prepare', {to_version: latestVersion}, function(res) {
                prepareDone = true;
                stopPolling();

                if (res.code !== 0) {
                    updateProgress('failed');
                    setTimeout(function() {
                        layer.close(progressLayerIdx);
                        layer.msg(res.message, {icon: 2});
                    }, 1200);
                    return;
                }

                updateProgress('awaiting_selection');

                diffData = res.data.diff_files;
                setTimeout(function() {
                    layer.close(progressLayerIdx);
                    $('#diffCard').show();
                    $('#diffCountTip').text('共 ' + res.data.diff_count + ' 个差异文件');

                    table.render({
                        elem: '#diff-table',
                        data: diffData,
                        page: {layout: ['count', 'prev', 'page', 'next', 'limit'], groups: 5, limit: 50},
                        cols: [[
                            {type: 'checkbox'},
                            {title: '文件路径', field: 'path', minWidth: 400},
                            {title: '状态', field: 'status', align: 'center', width: 80, templet: '#diff-status-tpl'},
                            {title: '本地大小', field: 'local_size', width: 100, templet: function(d) {
                                if (!d.local_size) return '-';
                                return formatSize(d.local_size);
                            }},
                            {title: '远程大小', field: 'remote_size', width: 100, templet: function(d) {
                                return formatSize(d.remote_size);
                            }},
                            {title: '本地 Hash', field: 'local_hash', width: 140, templet: '#diff-hash-tpl'}
                        ]],
                        done: function() {
                            // 默认全选
                            setTimeout(function() {
                                $('#diff-table').next('.layui-table-view').find('.layui-table-fixed-l .layui-form-checkbox').each(function() {
                                    if (!$(this).hasClass('layui-form-checked')) {
                                        $(this).trigger('click');
                                    }
                                });
                            }, 200);
                        }
                    });
                }, 800);
            }).fail(function(xhr) {
                prepareDone = true;
                stopPolling();
                setTimeout(function() {
                    layer.close(progressLayerIdx);
                    if (xhr.status === 401) { window.location.href = '/admin/login'; return; }
                    layer.msg('网络异常', {icon: 2});
                }, 800);
            });
        });
    });

    // 页面关闭时停止轮询
    $(window).on('beforeunload', function() {
        stopPolling();
    });

    // 重新检查
    $('#btnRecheck').on('click', function() {
        $('#diffCard').hide();
        diffData = [];
        checkLatest();
    });

    // 执行修复（通用）
    function doRepair(files) {
        if (!files || files.length === 0) {
            layer.msg('没有要修复的文件', {icon: 2});
            return;
        }

        layer.confirm('确定执行修复？将覆盖 ' + files.length + ' 个文件，覆盖前会自动备份。', {icon: 3}, function(idx) {
            layer.close(idx);

            var loadingIdx = layer.load(2, {shade: [0.5, '#000']});

            $.post('/admin/versionmgr/api/repair/execute', {files: files}, function(res) {
                layer.close(loadingIdx);

                if (res.code !== 0) {
                    layer.alert('修复失败：' + res.message, {icon: 2, title: '修复失败'});
                    return;
                }

                var data = res.data;
                var html = '修复完成！<br><br>' +
                    '成功：' + data.success_count + ' 个文件<br>' +
                    '失败：' + data.failed_count + ' 个文件<br>' +
                    '跳过：' + data.skipped_count + ' 个文件<br>';

                if (data.migration_executed) {
                    html += '数据库迁移：已执行<br>';
                }

                if (data.failed_files && data.failed_files.length > 0) {
                    html += '<br>失败文件：<br>';
                    data.failed_files.forEach(function(f) {
                        html += '• ' + f.path + '（' + f.error + '）<br>';
                    });
                }

                html += '<br>备份文件：<br><code style="font-size:12px;word-break:break-all;">' + data.backup_path + '</code>';

                layer.alert(html, {icon: data.failed_count > 0 ? 3 : 1, title: '修复结果', area: ['500px', '400px']});

                $('#diffCard').hide();
                diffData = [];
                checkLatest();
            }).fail(function(xhr) {
                layer.close(loadingIdx);
                if (xhr.status === 401) { window.location.href = '/admin/login'; return; }
                layer.msg('网络异常', {icon: 2});
            });
        });
    }

    // 全量修复
    $('#btnFullExecute').on('click', function() {
        if (!diffData || diffData.length === 0) {
            layer.msg('没有差异文件可修复', {icon: 2});
            return;
        }
        var files = diffData.map(function(item) { return item.path; });
        doRepair(files);
    });

    // 修复选中
    $('#btnExecute').on('click', function() {
        var checkStatus = table.checkStatus('diff-table');
        var selected = checkStatus.data;

        if (selected.length === 0) {
            layer.msg('请至少选择一个文件', {icon: 2});
            return;
        }

        var files = selected.map(function(item) { return item.path; });
        doRepair(files);
    });

    // 清理临时文件
    $('#btnCleanup').on('click', function() {
        layer.confirm('确定清理临时文件？清理后需要重新下载对比。', {icon: 3}, function(idx) {
            layer.close(idx);
            $.post('/admin/versionmgr/api/repair/cleanup', function(res) {
                if (res.code === 0) {
                    layer.msg('清理完成', {icon: 1});
                    $('#diffCard').hide();
                    diffData = [];
                } else {
                    layer.msg(res.message, {icon: 2});
                }
            });
        });
    });

    // 格式化文件大小
    function formatSize(bytes) {
        if (bytes < 1024) return bytes + 'B';
        if (bytes < 1048576) return (bytes / 1024).toFixed(1) + 'KB';
        return (bytes / 1048576).toFixed(1) + 'MB';
    }

    // 初始化
    checkLatest();
});
</script>
</body>
</html>
