<?php viewLoad('public/header'); ?>
<style>
html, body { height: 100%; margin: 0; padding: 0; }
#rpPage { display: flex; height: 100%; gap: 12px; box-sizing: border-box; padding: 8px; }
#rpTreePanel { flex: 1; min-width: 0; display: flex; flex-direction: column; }
#rpRolePanel { flex: 0.8; min-width: 0; display: flex; flex-direction: column; }
#rpFormPanel { width: 460px; flex-shrink: 0; border-left: 1px solid #eee; padding-left: 12px; overflow-y: auto; }
#rpSiteFilter { margin-bottom: 8px; }
#rpTreeList, #rpRoleGrid { flex: 1; min-height: 0; }
.perm-form-row { margin-bottom: 12px; }
.perm-form-row label { display: block; font-size: 12px; color: #666; margin-bottom: 4px; }
.perm-group-title { font-weight: bold; margin: 10px 0 4px; color: #0C6C9E; }
.perm-buttons { display: flex; gap: 8px; margin-top: 12px; }
.perm-empty-tip { color: #999; font-size: 13px; }
.rp-hl td { background: #fdecec !important; color: #d0312d !important; }
</style>

<div id="rpPage">
    <div id="rpTreePanel">
        <div id="rpTreeList"></div>
    </div>
    <div id="rpRolePanel">
        <div id="rpSiteFilter"></div>
        <div id="rpRoleGrid"></div>
    </div>
    <div id="rpFormPanel">
        <div id="rpTitle" class="perm-group-title"></div>
        <div id="rpEmptyTip" class="perm-empty-tip"><?=lg('请同时选中一个角色和一个权限')?></div>
        <div id="rpForm" style="display:none;">
            <div class="perm-form-row">
                <label><?=lg('类型')?></label>
                <div id="rpTypeList"></div>
            </div>
            <div class="perm-form-row">
                <label><?=lg('数据域')?></label>
                <div id="rpScopeBox"></div>
            </div>
            <div id="rpExtraArea"></div>
            <div class="perm-buttons">
                <div id="rpSaveBtn"></div>
                <div id="rpRevokeBtn"></div>
            </div>
        </div>
    </div>
</div>

<script>
$(function () {
    var sites = <?=json_encode($sites, JSON_UNESCAPED_UNICODE)?>;

    var typeLabels = {
        view: <?=json_encode(lg('查看'))?>, add: <?=json_encode(lg('添加'))?>, edit: <?=json_encode(lg('编辑'))?>,
        delete: <?=json_encode(lg('删除'))?>, import: <?=json_encode(lg('导入'))?>, export: <?=json_encode(lg('导出'))?>,
        done: <?=json_encode(lg('执行'))?>, check1: <?=json_encode(lg('初审'))?>, check2: <?=json_encode(lg('复审'))?>,
        check3: <?=json_encode(lg('终审'))?>
    };
    var scopeItems = [
        { value: 1, text: <?=json_encode(lg('仅查看/编辑自己'))?> },
        { value: 2, text: <?=json_encode(lg('查看本部门/编辑自己'))?> },
        { value: 3, text: <?=json_encode(lg('查看本部门/编辑本部门'))?> }
    ];

    var allPermNodes = [];
    var allRoles = [];
    var selectedCode = null;
    var selectedRoleId = null;
    var selectedRoleName = null;
    var grants = {}; // 当前选中角色的 code -> grant row
    var highlightedRoleIds = [];   // 选中权限时，拥有它的角色集合
    var highlightedCodes = [];     // 选中角色时，它拥有的权限码集合
    var currentExtraInputs = {};

    // 类型列表/数据域下拉只创建一次，切换节点时用 .option() 更新内容，不重新创建 widget
    var typeListInstance = $('#rpTypeList').dxList({
        dataSource: [],
        keyExpr: 'key',
        displayExpr: 'name',
        selectionMode: 'multiple',
        showSelectionControls: true,
        height: 140
    }).dxList('instance');

    var scopeBoxInstance = $('#rpScopeBox').dxSelectBox({
        dataSource: scopeItems,
        valueExpr: 'value',
        displayExpr: 'text'
    }).dxSelectBox('instance');

    var treeListInst = $('#rpTreeList').dxTreeList({
        dataSource: [],
        keyExpr: 'sys_permission_code',
        parentIdExpr: 'sys_permission_parent_code',
        rootValue: null,
        height: '100%',
        autoExpandAll: true,
        allowColumnResizing: true,
        hoverStateEnabled: true,
        focusedRowEnabled: true,
        filterRow: { visible: true },
        toolbar: {
            items: [
                { location: 'before', widget: 'dxButton', options: { text: <?=json_encode(lg('全部展开'))?>, onClick: function () { expandCollapseAll(true); } } },
                { location: 'before', widget: 'dxButton', options: { text: <?=json_encode(lg('全部收起'))?>, onClick: function () { expandCollapseAll(false); } } }
            ]
        },
        columns: [
            { dataField: 'sys_permission_name', caption: <?=json_encode(lg('名称'))?> },
            { dataField: 'sys_permission_code', caption: 'Code', width: 90 },
            { dataField: 'sys_permission_enabled', caption: <?=json_encode(lg('启用'))?>, dataType: 'boolean', width: 70 }
        ],
        onRowPrepared: function (e) {
            if (e.rowType !== 'data') { return; }
            var code = e.data.sys_permission_code;
            if (code === selectedCode || highlightedCodes.indexOf(code) !== -1) {
                e.rowElement.addClass('rp-hl');
            }
        },
        onRowClick: function (e) {
            selectedCode = e.data.sys_permission_code;
            treeListInst.repaint();
            loadRolesOfCode(selectedCode);
            refreshFormVisibility();
        }
    }).dxTreeList('instance');

    // dxTreeList 没有 expandAll()/collapseAll() 方法（那是 dxDataGrid 分组功能的方法），
    // 树形节点的展开/收起要遍历 forEachNode 后逐个调用 expandRow/collapseRow
    function expandCollapseAll(expand) {
        treeListInst.forEachNode(function (node) {
            if (expand) { treeListInst.expandRow(node.key); } else { treeListInst.collapseRow(node.key); }
        });
    }

    var roleGridInst = $('#rpRoleGrid').dxDataGrid({
        dataSource: [],
        keyExpr: 'sys_role_id',
        height: '100%',
        allowColumnResizing: true,
        columnAutoWidth: true,
        hoverStateEnabled: true,
        focusedRowEnabled: true,
        filterRow: { visible: true },
        columns: [
            { dataField: 'sys_role_name', caption: <?=json_encode(lg('角色名称'))?> },
            { dataField: 'sys_site_name', caption: <?=json_encode(lg('站点'))?> }
        ],
        onRowPrepared: function (e) {
            if (e.rowType !== 'data') { return; }
            if (highlightedRoleIds.indexOf(e.data.sys_role_id) !== -1) {
                e.rowElement.addClass('rp-hl');
            }
        },
        onRowClick: function (e) {
            selectedRoleId = e.data.sys_role_id;
            selectedRoleName = e.data.sys_role_name;
            loadGrantsOfRole(selectedRoleId).then(function () {
                highlightedCodes = Object.keys(grants);
                treeListInst.repaint();
                refreshFormVisibility();
            });
        }
    }).dxDataGrid('instance');

    $('#rpSiteFilter').dxSelectBox({
        dataSource: [{ sys_site_id: null, sys_site_name: <?=json_encode(lg('全部站点'))?> }].concat(sites),
        valueExpr: 'sys_site_id',
        displayExpr: 'sys_site_name',
        value: null,
        onValueChanged: function (e) {
            var filtered = e.value ? allRoles.filter(function (r) { return r.sys_role_lnk_site_id === e.value; }) : allRoles;
            roleGridInst.option('dataSource', filtered);
        }
    });

    function loadRolesOfCode(code) {
        return $.ajax({ url: APP.HOST + '/rolePermission/rolesOfCode', method: 'POST', contentType: 'application/json', data: JSON.stringify({ code: code }) })
            .then(function (res) { highlightedRoleIds = res.data || []; roleGridInst.repaint(); });
    }

    function loadGrantsOfRole(roleId) {
        grants = {};
        return $.ajax({ url: APP.HOST + '/role/grantsOf', method: 'POST', contentType: 'application/json', data: JSON.stringify({ roleId: roleId }) })
            .then(function (res) {
                (res.data || []).forEach(function (g) { grants[g.sys_role_permission_lnk_permission_code] = g; });
            });
    }

    function refreshFormVisibility() {
        if (!selectedCode || !selectedRoleId) {
            $('#rpEmptyTip').show();
            $('#rpForm').hide();
            $('#rpTitle').text('');
            return;
        }
        $('#rpEmptyTip').hide();
        $('#rpForm').show();
        $('#rpTitle').text(selectedRoleName + ' / ' + selectedCode);

        var node = allPermNodes.find(function (n) { return n.sys_permission_code === selectedCode; });
        if (!node) { return; }

        var types = node.sys_permission_types || {};
        var typeItems = Object.keys(types).map(function (k) { return { key: k, name: types[k] || typeLabels[k] || k }; });
        var grant = grants[selectedCode] || { sys_role_permission_types: [], sys_role_permission_data_scope: 1, sys_role_permission_extra_values: {} };

        typeListInstance.option('dataSource', typeItems);
        typeListInstance.option('selectedRowKeys', grant.sys_role_permission_types);

        scopeBoxInstance.option('value', grant.sys_role_permission_data_scope);

        currentExtraInputs = renderExtraFields(node.sys_permission_extra_schema, grant.sys_role_permission_extra_values || {});
    }

    function renderExtraFields(schema, values) {
        var $area = $('#rpExtraArea').empty();
        var inputs = {};
        (schema || []).forEach(function (group) {
            $('<div class="perm-group-title">').text(group.caption || group.group).appendTo($area);
            (group.items || []).forEach(function (item) {
                var field = item.field || item.fields;
                var $row = $('<div class="perm-form-row">').appendTo($area);
                if (item.type === 'input') {
                    var $box = $('<div>').appendTo($row);
                    $box.dxNumberBox({ placeholder: item.caption, value: values[field] || 0 });
                    inputs[field] = { get: function () { return $box.dxNumberBox('instance').option('value'); } };
                } else {
                    var $chk = $('<div>').appendTo($row);
                    $chk.dxCheckBox({ text: item.caption, value: !!values[field] });
                    inputs[field] = { get: function () { return $chk.dxCheckBox('instance').option('value'); } };
                }
            });
        });
        return inputs;
    }

    $('#rpSaveBtn').dxButton({
        text: <?=json_encode(lg('保存'))?>, type: 'default',
        onClick: function () {
            if (!selectedCode || !selectedRoleId) { return; }
            var extraValues = {};
            Object.keys(currentExtraInputs).forEach(function (field) { extraValues[field] = currentExtraInputs[field].get(); });

            $.ajax({
                url: APP.HOST + '/role/grant', method: 'POST', contentType: 'application/json',
                data: JSON.stringify({
                    roleId: selectedRoleId, code: selectedCode,
                    types: typeListInstance.option('selectedRowKeys'),
                    dataScope: scopeBoxInstance.option('value'),
                    extraValues: extraValues
                })
            }).then(function (res) {
                if (res.code === 0) {
                    grants[selectedCode] = {
                        sys_role_permission_types: typeListInstance.option('selectedRowKeys'),
                        sys_role_permission_data_scope: scopeBoxInstance.option('value'),
                        sys_role_permission_extra_values: extraValues
                    };
                    highlightedCodes = Object.keys(grants);
                    treeListInst.repaint();
                    loadRolesOfCode(selectedCode);
                    DevExpress.ui.notify(<?=json_encode(lg('已保存'))?>, 'success', 1200);
                }
            });
        }
    });

    $('#rpRevokeBtn').dxButton({
        text: <?=json_encode(lg('撤销'))?>, stylingMode: 'outlined', type: 'danger',
        onClick: function () {
            if (!selectedCode || !selectedRoleId) { return; }
            $.ajax({ url: APP.HOST + '/role/revoke', method: 'POST', contentType: 'application/json', data: JSON.stringify({ roleId: selectedRoleId, code: selectedCode }) })
                .then(function (res) {
                    if (res.code === 0) {
                        delete grants[selectedCode];
                        highlightedCodes = Object.keys(grants);
                        treeListInst.repaint();
                        loadRolesOfCode(selectedCode);
                        DevExpress.ui.notify(<?=json_encode(lg('已撤销'))?>, 'success', 1200);
                    }
                });
        }
    });

    Promise.all([
        $.ajax({ url: APP.HOST + '/permission/tree', method: 'GET' }),
        $.ajax({ url: APP.HOST + '/role/grid', method: 'POST', contentType: 'application/json', data: '{}' })
    ]).then(function (results) {
        allPermNodes = results[0].data || [];
        allRoles = (results[1].data && results[1].data.data) || [];
        treeListInst.option('dataSource', allPermNodes);
        roleGridInst.option('dataSource', allRoles);
    });
});
</script>

<?php viewLoad('public/footer'); ?>
