ns = params_kw.copy()
kb_id = ns.get('kb_id', '')
folder_id = ns.get('id', '')
folder_label = ns.get('label', '全部文件')
if folder_id == '__root__':
    folder_id = ''
    folder_label = '根目录'

db = DBPools()
dbname = get_module_dbname('rag')

rows = []
try:
    async with db.sqlorContext(dbname) as sor:
        if folder_id:
            recs = await sor.sqlExe(
                "SELECT id, file_name, file_type, file_size, file_path, status, chunk_count, created_at FROM documents WHERE kb_id=${kb_id}$ AND folder_id=${folder_id}$ ORDER BY created_at DESC",
                {"kb_id": kb_id, "folder_id": folder_id})
        else:
            recs = await sor.sqlExe(
                "SELECT id, file_name, file_type, file_size, file_path, status, chunk_count, created_at FROM documents WHERE kb_id=${kb_id}$ AND (folder_id IS NULL OR folder_id IN ('','__root__')) ORDER BY created_at DESC",
                {"kb_id": kb_id})
        for r in recs:
            rows.append({
                "id": r.id,
                "file_name": r.file_name,
                "file_type": r.file_type or '',
                "file_size": r.file_size or 0,
                "file_path": r.file_path or '',
                "status": r.status or '',
                "chunk_count": r.chunk_count or 0,
                "created_at": str(r.created_at)[:16] if r.created_at else ''
            })
except:
    return {"widgettype": "Text", "options": {"text": "加载文件列表失败", "cfontsize": 14, "color": "#e74c3c", "halign": "center", "marginTop": "40px"}}

def fmt_size(sz):
    if sz < 1024: return str(sz) + "B"
    elif sz < 1024*1024: return str(round(sz/1024, 1)) + "KB"
    else: return str(round(sz/(1024*1024), 1)) + "MB"

def trunc_name(name, maxlen=28):
    if len(name) > maxlen:
        return name[:maxlen-3] + "..."
    return name

header = {
    "widgettype": "HBox",
    "options": {"width": "100%", "padding": "10px 0", "borderBottom": "1px solid #e0e0e0", "alignItems": "center"},
    "subwidgets": [
        {"widgettype": "Text", "options": {"text": "📄 " + folder_label, "cfontsize": 14, "fontWeight": "bold", "color": "#333"}},
        {"widgettype": "Text", "options": {"text": "（" + str(len(rows)) + " 个文件）", "cfontsize": 12, "color": "#999", "marginLeft": "8px"}},
        {"widgettype": "Text", "options": {"text": "", "css": "filler"}}
    ]
}

file_widgets = [header]

if not rows:
    file_widgets.append({
        "widgettype": "Text", "options": {"text": "暂无文件", "cfontsize": 13, "color": "#aaa", "halign": "center", "marginTop": "40px"}
    })
else:
    for f in rows:
        sc = "#50b86c"; st = "完成"
        if f["status"] == "pending": sc = "#e6a23c"; st = "处理中"
        elif f["status"] == "error": sc = "#f56c6c"; st = "失败"

        file_url = f["file_path"]
        if not file_url.startswith("/idfile"):
            file_url = "/idfile" + file_url
        del_url = "/rag/knowledge_bases_list/delete_file.dspy?_webbricks_=1&kb_id=" + kb_id + "&doc_id=" + f["id"] + "&folder_id=" + folder_id + "&folder_label=" + folder_label
        display_name = trunc_name(f["file_name"])

        row = {
            "widgettype": "HBox",
            "options": {"width": "100%", "padding": "6px 12px", "borderBottom": "1px solid #f0f0f0", "alignItems": "center"},
            "subwidgets": [
                {"widgettype": "Text", "options": {
                    "text": "📄 " + display_name, "cfontsize": 13, "color": "#333",
                    "cwidth": 28, "halign": "left", "overflow": "hidden",
                    "title": f["file_name"]
                }},
                {"widgettype": "Text", "options": {"text": f["file_type"].upper(), "cfontsize": 11, "color": "#999", "cwidth": 5, "halign": "center"}},
                {"widgettype": "Text", "options": {"text": fmt_size(f["file_size"]), "cfontsize": 11, "color": "#999", "cwidth": 8, "halign": "right"}},
                {"widgettype": "Text", "options": {"text": st, "cfontsize": 11, "color": sc, "cwidth": 6, "halign": "center"}},
                {"widgettype": "Text", "options": {"text": f["created_at"], "cfontsize": 11, "color": "#999", "cwidth": 13, "halign": "center"}},
                {
                    "widgettype": "HBox", "options": {"spacing": "14px"},
                    "subwidgets": [
                        {"widgettype": "Text", "options": {"text": "👁", "cfontsize": 14, "css": "clickable", "color": "#4a90d9", "title": "查看"},
                         "binds": [{"wid": "self", "event": "click", "actiontype": "script", "target": "self",
                             "script": "window.open(" + json.dumps(file_url) + ",'_blank')"}]},
                        {"widgettype": "Text", "options": {"text": "⬇", "cfontsize": 14, "css": "clickable", "color": "#50b86c", "title": "下载"},
                         "binds": [{"wid": "self", "event": "click", "actiontype": "script", "target": "self",
                             "script": "var a=document.createElement('a');a.href=" + json.dumps(file_url) + ";a.download='';document.body.appendChild(a);a.click();document.body.removeChild(a)"}]},
                        {"widgettype": "Text", "options": {"text": "🏷", "cfontsize": 14, "css": "clickable", "color": "#1565c0", "title": "添加标签"},
                         "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "PopupWindow",
                             "popup_options": {"title": "为「" + display_name + "」添加标签", "width": "32%", "height": "auto",
                                               "movable": True, "resizable": True, "modal": True},
                             "options": {"url": "./tag_form.dspy?doc_id=" + f["id"] + "&kb_id=" + kb_id}}]},
                        {"widgettype": "Text", "options": {"text": "🗑", "cfontsize": 14, "css": "clickable", "color": "#f56c6c", "title": "删除"},
                         "binds": [{"wid": "self", "event": "click", "actiontype": "script", "target": "self",
                             "script": "if(!confirm('确认删除 ' + decodeURIComponent(" + json.dumps(f["file_name"]) + ") + ' ? 不可恢复'))return;fetch(" + json.dumps(del_url) + ").then(function(r){return r.json()}).then(function(){var u='/rag/knowledge_bases_list/file_list.dspy?_webbricks_=1&kb_id='+encodeURIComponent(" + json.dumps(kb_id) + ")+'&id='+encodeURIComponent(" + json.dumps(folder_id) + ")+'&label='+encodeURIComponent(" + json.dumps(folder_label) + ");fetch(u).then(function(r){return r.json()}).then(function(d){var fp=bricks.getWidgetById('file_list_panel',bricks.app.root);if(fp){fp.clear_widgets();bricks.widgetBuild(d,fp).then(function(w){if(w)fp.add_widget(w)})}})})"}]}
                    ]}
            ]}
        file_widgets.append(row)

result = {"widgettype": "VBox", "options": {"width": "100%", "spacing": "0"}, "subwidgets": file_widgets}
return result
