from common.container import Container
from common.errors import KareErrors as IError
from common.package import Package
import os
from install.resource import *
from common.log import Log
from common.utils import RequireRoot, GlobalSingleton
from pathlib import Path
from remove.remove import Remove
from common.whitelist import WhiteList
import dbus
import subprocess
import dbus.service

@RequireRoot
class Install(IError, Container, GlobalSingleton):
    
    LOCK_FILE = "/var/lock/kare-install.lock"
    flag = False

    """
    @brief 安装类 处理deb包相关逻辑
    @param base_env: 安装环境
    @param packages: 包列表
    """
    def __init__(self, base_env, packages,chroot):
        GlobalSingleton.__init__(self)
        # {package: {version :包版本, base_env: 安装环境, path: 存储路径， file: 文件路径}}
        self.log = Log("/var/log/kare/kare-install.log")
        self.base_env = base_env
        self.upgrade = False
        self.chroot = chroot
        # 获取安装包列表绝对路径
        self.packages = [os.path.abspath(package) for package in packages]
        # 实例化父类， 获取父类相关能力，如：创建容器，删除容器等
        Container.__init__(self, self.is_shadow(base_env), self.log, chroot,True)
        # 检测包是否存在
        self.check_package()
        self.preinstall()
        for p in self.packages:
            self.list_files, self.container_list_files, self.desktop_list = [], [], []
            self.icons, self.desktops = None, None
            # 将dpkg实例化
            self.copy_file(p, "/tmp/kare-tmp.deb")
            p = "/tmp/kare-tmp.deb"
            d = Package(p, self.log,self.chroot)
            if d.container_name == "dkmsContainer" or d.package_name == "virtualbox" or d.container_name == "virtualbox-qt":
            # 检查dkms必要目录是否存在
                self.base_env = "shadow"
                Container.__init__(self, self.is_shadow(self.base_env), self.log, self.chroot, True)
                self.preinstall()
                self.check_dkms_opt_ko_path()
            if d.package_name == "com.iflyrec.assistant":
                self.base_env = "shadow"
                Container.__init__(self, self.is_shadow(self.base_env), self.log, self.chroot, True)
                self.preinstall()
            if d.is_biometric(d.package):
                self.base_env = "v10sp1"
                Container.__init__(self, self.is_shadow(self.base_env), self.log, self.chroot)
                self.preinstall()
            if not self.chroot:
                self.check_installation(d)
            self.is_package_installed(d)
            if d.container_name == "v10sp1Driver":
                self.base_env = "v10sp1"
                Container.__init__(self, self.is_shadow(self.base_env), self.log, self.chroot)
                os.system("echo '' > {}/usr/bin/kare-hook.py".format(self.PACKAGE_SAVE_PATH + d.container_name + "/merge"))
                d.cups_pre_install(self.PACKAGE_SAVE_PATH + d.container_name + "/upper")
                self.preinstall()
            # 创建容器，包括创建容器目录，overlay目录挂载等
            self.create_container(d.container_name)
            if d.container_name == "dkmsContainer":
                os.system("echo '' > {}/usr/bin/kare-hook.py".format(self.PACKAGE_SAVE_PATH + d.container_name + "/merge"))
            # 包存储路径 /opt/kare-applications/package_name + _ + _ package_version/merge
            package_path = self.PACKAGE_SAVE_PATH + d.container_name + "/merge"
            # 解压缩包，获取包解压缩路径 /tmp目录下
            unpack_path = d.unpack()
            if unpack_path == None:
                self.log.error(self.PACKAGE_UNPACK_FAIL[1])
                raise RuntimeError(self.PACKAGE_UNPACK_FAIL)
            w = WhiteList(d.package_name, d.container_name)
            # w.update_usr_desktops(unpack_path)
            # 服务处理，包括创建service文件，服务Exec字段处理，安装service文件等
            services = Service(d, unpack_path, self.log)
            services.edit_vp_service_file(d, services.services_list)
            services.edit_vp_initd_service_file(d, services.initd_services_list)
            d.services_install(services.services_list)
            self.log.info("应用包 {} services文件列表：{}".format(d.package_name, services.services_list))
            d.services_install(services.initd_services_list)
            self.log.info("应用包 {} services文件列表：{}".format(d.package_name, services.initd_services_list))

            # 安资源管理逻辑
            # TODO 部分应用Exec字段中，执行文件内容为start.sh run.sh 等，容易重复，需要修改为 容器名-start.sh
            self.resource_manager(d, unpack_path, services.services_list+services.initd_services_list)
            # 配置文件更新
            self.update_container_list_files(unpack_path, package_path)
            self.updata_config(d)

            # 安装逻辑
            self.install(package_path, d)
            if not self.chroot:
                try:
                    os.chmod(package_path + "/config.json", 0o766)
                except Exception as e:
                    self.log.error(e)
                    raise RuntimeError(self.PACKAGE_INSTALL_FAIL)

            
            self.postinstall(unpack_path, d, package_path)
            if d.is_biometric(d.package):
                bio_files = d.copy_biometric_file(d.driver,d.package,package_path)
                conf = self.get_config_json(self.INSTALL_JSON, d.package_name)
                conf["file"] = list(set(conf.get("file", [])).union(set(bio_files)))
                conf["bio_driver_name"] = d.driver
                self.set_config_json(self.INSTALL_JSON, d.package_name, conf)

            # 白名单文件处理
            w.update_services()
            w.update_bin_files()
            w.create_symbol_link()
            self.ksaf_set_for_kare(d)
            del d, w, services
            os.remove("/tmp/kare-tmp.deb")

    """
    @brief 检测包是否存在，
    """
    def check_package(self):
        for package in self.packages:
            if not os.path.exists(package):
                self.log.error(self.PACKAGE_NOT_EXIST[1])
                raise RuntimeError(self.PACKAGE_NOT_EXIST)

    def update_container_list_files(self, unpack_path, package_path):
        base_path = os.path.dirname(package_path) + "/upper/"
        merge_base_path = os.path.dirname(package_path) + "/merge/"
        for root, dirs, files in os.walk(unpack_path):
            rel_path = os.path.relpath(root, unpack_path)
            if rel_path == '.':
                rel_path = ''
            for f in files:
                file_entry = os.path.join(rel_path, f) if rel_path else f
                if file_entry.endswith(".bak"):
                    continue
                # if os.path.exists(f"{base_path}{file_entry}"):
                self.container_list_files.append(f"{base_path}{file_entry}")
                self.container_list_files.append(f"{merge_base_path}{file_entry}")

    """
    @brief 处理安装前逻辑， 检测基础环境，检测包是否存在等，检测生效容器
    """
    def preinstall(self):
        self.log.info("============ 安装前检测 ============")
        # 检测基础环境是否存在
        self.release_path = self.get_release_path(self.base_env)
        if self.release_path == None:
            self.log.error(self.RELEASE_NOT_EXIST[1])
            raise RuntimeError(self.RELEASE_NOT_EXIST)
        if self.base_env.startswith("upgrade-"):
            # TODO 异常抛出码提示
            # self.log.error(self.RELEASE_NOT_EXIST[1])
            raise RuntimeError(self.RELEASE_NOT_EXIST)       

    """
    @brief 检查dkms必要目录是否存在,若不存在则创建
    """
    def check_dkms_opt_ko_path(self):
        lib_modules = Path(self.LIB_MODULES)
        target_base = Path(self.OPT_SYSTEM_LIB_MODULES)
        if self.is_ostree and lib_modules.exists():
            for entry in lib_modules.iterdir():
                module_name = entry.name
                target_dir = target_base / module_name
                # 如果目标目录不存在则创建
                if not target_dir.exists():
                    target_dir.mkdir(parents=True, exist_ok=True)
        var_lib_dkms_path = Path(self.VAR_LIB_DKMS)
        if self.is_ostree and not var_lib_dkms_path.exists():
            var_lib_dkms_path.mkdir(parents=True, exist_ok=True)

    """
    @brief 检测包是否已经安装
    """
    def is_package_installed(self, package:Package):
        data = self.get_config_json(self.INSTALL_JSON, package.package_name)        
        if data != None:
            self.log.info(f"包{package.package_name}已安装")
            if data["base_env"] != self.base_env:
                self.base_env = data["base_env"]
                self.preinstall()
                Container.__init__(self,  self.is_shadow(self.base_env), self.log, self.chroot,True)
                # self.log.error(self.PACKAGE_ALREADY_EXISTS[1])
                # raise RuntimeError(self.PACKAGE_ALREADY_EXISTS)
            Remove([package.package_name])
            self.log.info("============ Reinstall ============")
        else:
            if self.container_installed(package.package_name):
                self.log.error(self.PACKAGE_DPKG_EXISTS[1])
                raise RuntimeError(self.PACKAGE_DPKG_EXISTS)

    """
    @brief 创建容器
    """
    def create_container(self, package):
        self.log.info("============ 创建容器 ============")
        self.container.create_container(self.release_path, package)
        arch = self.get_build_arch()
        if self.base_env == "shadow":
            target = self.PACKAGE_SAVE_PATH + package + "/merge/usr/bin/"
            self.copy_file("/usr/share/kare/container-scripts/agent.py", target)
            self.copy_file("/usr/share/kare/container-scripts/fix_depends.py", target)
            self.copy_file("/usr/share/kare/container-scripts/kare-hook.py", target)
            self.copy_file("/usr/share/kare/container-scripts/kare-apt.py", target)
            if arch == "loongarch64":
                shutil.copy("/usr/share/kare/plugins/tini/tini_host", self.PACKAGE_SAVE_PATH + package + "/merge/usr/bin/tini")
            else:
                self.copy_file("/usr/share/kare/plugins/tini/tini", target)

    """
    @brief  容器内调用kare-apt安装包
    @param  package_path deb包存储决绝路径
    @param  package package实例

    """    
    def install(self, package_path, package:Package):
        self.log.info("============ 安装命令构建 ============")
        self.log.info("============ Building installation command ============")
        self.container.start_container()
        if self.chroot:
            cmd = "/usr/bin/python3 /usr/bin/agent.py {}".format(package.package)
            exec = self.container.exec(package_path, cmd)
            self.log.info(f'通过chroot安装应用命令:{exec}')
            ret = subprocess.run(exec.split()).returncode
        else:
            cmd = "/usr/bin/python3 /usr/bin/agent.py {}".format(package.package)
            exec = self.container.exec(package_path, cmd, install=True)
            ret = self.run_command_realtime(exec, self.log)
        if ret != 0:
            self.log.error("安装失败")
            Remove([package.package_name])
            # package.clean_package(package_path.rsplit("/", 1)[0], package.is_driver, self.upgrade)
            # # 清理因升级导致原有包残留
            # self.set_config_json(self.INSTALL_JSON, package.package_name)
            # package.remove_package(package.package_name)
            raise RuntimeError(self.PACKAGE_INSTALL_FAIL)
    
    def diff_resource(self, package_path, base_share_path, path, file):
        diffs = []
        try:
            self.icons.find_container_files(package_path + path, base_share_path + path, diffs)
        except FileNotFoundError as e:
            self.log.error(e)
            return
        for diff in diffs:
            if diff.is_symlink():
                # 查询源文件
                source = Path(package_path + diff.resolve().as_posix())
                link = Path(base_share_path + path) / diff.name
                link.parent.mkdir(parents=True, exist_ok=True)
                link.symlink_to(source)
                file.append(link.as_posix())
                self.list_files.append(link.as_posix())
            else:
                target = base_share_path + path + "/" + diff.name
                self.copy_file(diff.as_posix(), target)
                file.append(target)
                self.list_files.append(target + "/" + diff.name)

    def desktop_postinstall(self, d:Package, unpack_path, file):
        package_path = self.PACKAGE_SAVE_PATH + d.container_name + "/upper"
        base_share_path = "/opt/kare" if self.is_ostree else ""
        try:
            container_desktops = [i for i in os.listdir(package_path+self.APPLICATIONS_PATH) if i.endswith(".desktop")]
        except FileNotFoundError as e:
            self.log.error(e)
            container_desktops = []
        try:
            autostart_desktops = [i for i in os.listdir(package_path+self.AUTOSTART_PATH) if i.endswith(".desktop")]
        except FileNotFoundError as e:
            self.log.error(e)
            autostart_desktops = []
        edit_desktops = []
        names = [name.rsplit("/", 1)[-1] for name in file]
        desktop_whitelist = self.get_config_json(self.WHITELIST_DESKTOP_FILE) 
        for desktop in container_desktops:
            if desktop not in names and d.package_name not in desktop and desktop not in desktop_whitelist:
                continue
            edit_desktop = unpack_path + f"{self.APPLICATIONS_PATH}/{desktop}"
            self.copy_file(package_path + self.APPLICATIONS_PATH + f"/{desktop}", edit_desktop)
            if os.path.exists(edit_desktop) is False:
                link_desktop = Path(package_path + "/" + edit_desktop.split("/", 3)[-1])
                resolve = link_desktop.resolve().as_posix()
                if resolve.startswith("/var"):
                    resolve = "/" + resolve.split("/", 2)[-1]
                resolve_desktop = package_path + resolve
                self.run_command(f"rm -rf {edit_desktop}")
                self.copy_file(resolve_desktop, edit_desktop)
            edit_desktops.append(edit_desktop)
            self.desktops.desktops_list.append(Path(edit_desktop))

        for desktop in autostart_desktops:
            if desktop not in names and d.package_name not in desktop and desktop not in desktop_whitelist:
                continue
            edit_desktop = unpack_path + f"{self.AUTOSTART_PATH}/{desktop}"
            self.log.info(f"============{edit_desktop}")
            self.copy_file(package_path + self.AUTOSTART_PATH + f"/{desktop}", edit_desktop)
            if os.path.exists(edit_desktop) is False:
                link_desktop = Path(package_path + "/" + edit_desktop.split("/", 3)[-1])
                resolve = link_desktop.resolve().as_posix()
                if resolve.startswith("/var"):
                    resolve = "/" + resolve.split("/", 2)[-1]
                resolve_desktop = package_path + resolve
                self.run_command(f"rm -rf {edit_desktop}")
                self.copy_file(resolve_desktop, edit_desktop)
            edit_desktops.append(edit_desktop)
            self.desktops.desktops_list.append(Path(edit_desktop))
            
        self.desktops.edit_vp_desktop_file(d.package_name, edit_desktops)
        [self.kare_vp_cp(desktop, self.chroot, log=self.log) for desktop in self.desktops.desktops_list]
        self.log.info(f"postinst 处理desktop文件列表{edit_desktops}")
        d.install(postinst=True)
        
        # target_path = base_share_path + self.APPLICATIONS_PATH
        # for x in edit_desktops:
        #     target_desktop_path = target_path + f"/{x.rsplit('/')[-1]}"
        #     self.copy_file(x, target_desktop_path)
        #     os.chmod(target_desktop_path, 0o644)
        #     file.append(target_desktop_path)

        # d.install(True)
        # exec_dir = unpack_path+"/usr/bin/"
        # try:
        #     exec_target_path = base_share_path + self.EXEC_PATH
        #     for exec in os.listdir(exec_dir):
        #         self.copy_file(exec_dir+exec, exec_target_path)
        #         file.append(exec_target_path+"/"+exec)
        # except FileNotFoundError as e:
        #     self.log.error(f"{e}")


    """
    @brief  解决postinst中, 部分目录下icon是通过postinst生成(非改名)
    """  
    def icon_postinstall(self, d:Package, file):
        package_path = self.PACKAGE_SAVE_PATH + d.container_name + "/upper"

        base_share_path = "/opt/kare" if self.is_ostree else ""
        # mimetypes
        self.diff_resource(package_path, base_share_path, self.MIMETYPES_PATH, file)
        # 图片
        hicolor_path = Path(package_path + self.ICON_HICOLOR_PATH)
        if hicolor_path.exists():
            for hicolor in hicolor_path.iterdir():
                hicolor_apps_path = hicolor / "apps"
                if hicolor_apps_path.exists():
                    self.diff_resource(package_path, base_share_path, self.ICON_HICOLOR_PATH+f"/{hicolor_apps_path.parts[-2]}/apps", file)
        
        # pixmaps
        pixmaps = Path(package_path + self.PIXMAPS_PATH)
        if pixmaps.exists():
            for icon in pixmaps.iterdir():
                target = base_share_path + self.SCALABLE_APPS_PATH + "/" + icon.name
                target_pixmaps = base_share_path + self.PIXMAPS_PATH + "/" + icon.name
                self.copy_file(icon.as_posix(), target)
                self.copy_file(icon.as_posix(), target_pixmaps)
                try:
                    os.chmod(target, 0o644)
                    file.append(target)
                    file.append(target_pixmaps)
                    self.list_files.append(target)
                except Exception:
                    continue
        
        self.run_command(f"update-desktop-database {base_share_path}/usr/share/applications")
        self.run_command(f"update-mime-database {base_share_path}/usr/share/mime")

    """
    @brief  依赖补充，其他代理设置，配置修改相关
    """  
    def postinstall(self, unpack_path, d:Package, package_path):

        self.log.info("============ postinstall脚本执行 ============")
        # 删除tmp目录下文件
        # DKMS 调用宿主机 
        keyword="dkms"
        if keyword.lower() in d.container_name.lower():
            self.log.info("============ DKMS 调用宿主机 ============")
            self.run_command("update-initramfs -u")
        
        self.log.info("============ SANE-localhost检测 ============")
        net_conf = '{}/{}/merge/etc/sane.d/net.conf'.format(self.PACKAGE_SAVE_PATH, d.container_name)
        if os.path.exists(net_conf):
            localhost_flag = False
            self.log.info("net.conf 存在")
            with open(net_conf, 'r') as f:
                content = f.readlines()
            for line in content:
                if line.strip() == "localhost":
                    localhost_flag = True
                    break
            if not localhost_flag:
                with open(net_conf, 'a') as f:
                    f.write('localhost\n')
                    self.log.info("localhost 写入成功")
            else:
                self.log.info("localhost 已存在，跳过此项")
        else:
            self.log.info("net.conf 未找到")
            self.log.info(net_conf)

        # 驱动相关操作
        if "v10sp1Driver" in d.container_name and self.is_ostree:
            self.log.info("============ v10sp1Driver ============")
            driver_conf = {
                "path" : self.PACKAGE_SAVE_PATH + d.container_name,
                "base_env": self.base_env,
                "upgrade": False,
                "driver":d.is_driver,
                "file": [],
                "container_file": []
            }
            self.set_config_json(self.INSTALL_JSON, "v10sp1Driver", driver_conf)
            cups_files, restart_cups = d.cups_post_install(self.PACKAGE_SAVE_PATH+d.container_name+"/upper", d.package_name)
            install_conf = self.get_config_json(self.INSTALL_JSON, d.package_name)
            install_conf["file"] = list(set(self.list_files).union(set(cups_files)))
            self.set_config_json(self.INSTALL_JSON, d.package_name, install_conf)
            if restart_cups:
                self.run_command("systemctl restart cups.service")
            

        if "dkmsContainer" in d.container_name and self.is_ostree:
            self.log.info("============ dkmsContainer ============")
            diff_ko=[]
            pre_ko_list=[]
            now_ko_list=[]
            dkms_conf = self.get_config_json(self.INSTALL_JSON, "dkmsContainer")
            if dkms_conf is not None:
                pre_ko_list = dkms_conf.get("kos", None)

            get_dkms_driver_list_cmd = "dkms status"
            exec = self.container.exec(f'{self.PACKAGE_SAVE_PATH}{d.container_name}/merge', get_dkms_driver_list_cmd)
            output = self.run_command_status_output(exec)
            if output[0] == 0:
                now_ko_list = output[1].splitlines()
            else:
                self.log.info(f"获取的dkms列表失败")
            print(f'pre_ko_list={pre_ko_list}')
            print(f'now_ko_list={now_ko_list}')

            diff_ko = [x for x in now_ko_list if x not in pre_ko_list]
            conf = {
                "path" : dkms_conf.get("path",""),
                "base_env": dkms_conf.get("base_env",""),
                "upgrade": dkms_conf.get("upgrade",False),
                "driver":dkms_conf.get("driver",False),
                "dkms":dkms_conf.get("dkms",False),
                "file": dkms_conf.get("file",""),
                "container_file": dkms_conf.get("container_file",""),
                "kos":now_ko_list
            }
            self.set_config_json(self.INSTALL_JSON, "dkmsContainer", conf)
            package_conf = self.get_config_json(self.INSTALL_JSON, d.package_name)
            package_conf = {
                "version": package_conf.get("version"),
                "upgrade": package_conf.get("upgrade",False),
                "base_env": package_conf.get("base_env",""),
                "path": package_conf.get("path",""),
                "driver":package_conf.get("driver",False),
                "dkms":package_conf.get("dkms",False),
                "file": package_conf.get("file", []),
                "container_file": package_conf.get("container_file", []),
                "desktop_files": package_conf.get("desktop_files", []),
                "kos":diff_ko
            }
            self.set_config_json(self.INSTALL_JSON, d.package_name, package_conf)
            self.copy_config_for_dkms(unpack_path,d)
        
        if self.chroot and self.base_env == "shadow": # 卸载掉chroot共享的目录  构建crun的config.json
            package_path = self.PACKAGE_SAVE_PATH + d.container_name + "/merge"
            self.container.build_config_json(package_path, "pwd")
            self.container.umount_share_dirs(d.container_name)
            entries = os.listdir(package_path)
            for entry in entries:
                full_path = os.path.join(package_path, entry)
                if os.path.isdir(full_path):  # 判断是否是目录
                    ret = self.run_command_status_output(f"umount -l {full_path}")
                    self.log.info(f"卸载挂载点{full_path}结果: {ret}")

        conf = self.get_config_json(self.INSTALL_JSON, d.package_name)
        file = conf.get("file", [])
        if "dkmsContainer" in d.container_name and self.is_ostree:
            k = Ko(d, unpack_path)
            k.find_ko()
            for ko in k.ko_list:
                file.append(ko)
                self.list_files.append(ko)

        if d.package_name == "reader-middleware-ecp-cmcc":
            file_path = "/etc/systemd/system/pcscd.service"
            with open(file_path, 'w') as f:
                f.write("[Unit]\n")
                f.write("Description=PC/SC Smart Card Daemon\n\n")
                f.write("[Service]\n")
                f.write("ExecStart=kare run reader-middleware-ecp-cmcc /usr/sbin/pcscd --foreground --auto-exit\n")
                f.write("ExecReload=kare run reader-middleware-ecp-cmcc /usr/sbin/pcscd --hotplug\n")
                f.write("[Install]\n")
                f.write("WantedBy=multi-user.target\n")
            print(f"文件已创建并写入内容: {file_path}")
            self.run_command(f"systemctl restart pcscd.service")
            self.run_command(f"systemctl enable pcscd.service")

        if d.package_name == "lval":
            self.run_command("kare run lval '/opt/APPS/LVUAAgentInstBaseRoot/bin/dvc-watermark.sh'")

        if d.package_name == "insight-client":
            cmd = '''bash -c 'mkdir -p /opt/zyjmonitor/yqt/client/client-helper && echo "xdg-open \\"http://127.0.0.1:6090/index\\"" > /opt/zyjmonitor/yqt/client/client-helper/helper.conf' '''
            exec = self.container.exec(f'{self.PACKAGE_SAVE_PATH}{d.container_name}/merge', cmd)
            output = self.run_command_status_output(exec)
            if output[0] == 0:
                self.log.info(f"insight-client 创建目录和文件成功")
            else:
                self.log.info(f"insight-client 创建目录和文件失败")

        if d.package_name == "com.jy.gpywebsocketserver":
            # 创建脚本内容
            script_content = '''#!/bin/bash

export LD_LIBRARY_PATH=/opt/apps/com.jy.gpywebsocketserver/files/bin:$LD_LIBRARY_PATH
export QT_PLUGIN_PATH=/opt/apps/com.jy.gpywebsocketserver/files/bin/plugins
cd /opt/apps/com.jy.gpywebsocketserver/files/bin/
./gpywebSocketServer &
./jywebsocketstart &'''
            
            cmd = f'''bash -c "echo '{script_content}' > /opt/apps/com.jy.gpywebsocketserver/files/gpywebSocketServer-run.sh"'''
            exec = self.container.exec(f'{self.PACKAGE_SAVE_PATH}{d.container_name}/merge', cmd)
            output = self.run_command_status_output(exec)
            if output[0] == 0:
                self.log.info(f"com.jy.gpywebsocketserver 脚本写入成功")
            else:
                self.log.info(f"com.jy.gpywebsocketserver 脚本写入失败")
                
        self.icon_postinstall(d, file)
        self.desktop_postinstall(d, unpack_path, file)
        self.update_kare_desktops_to_container(package_path)
        d._clean_vp_path()
        conf["file"] = list(set(file))
        self.set_config_json(self.INSTALL_JSON, d.package_name, conf)
        # 桌面文件覆盖问题
        if self.chroot is False:
            try:
                uid, user = self.get_user_by_login1
            except TypeError as e:
                self.log.error("未获取到当前用户, 桌面文件覆盖问题不处理")
                self.log.error(e)
                return
            user_desktop = "/home/" + user + "/桌面/"
            self.log.info("用户桌面路径：{}".format(user_desktop))
            if os.path.exists(user_desktop) is False:
                return
            user_desktops = [i for i in os.listdir(user_desktop) if i.endswith(".desktop")]
            for f in self.desktop_list:
                if f.split("/")[-1] in user_desktops:
                    self.copy_file(f, user_desktop)
                    os.chmod(user_desktop+f.split("/")[-1], 0o755)
                    os.chown(user_desktop+f.split("/")[-1], uid, uid)
                    self.log.info("用户桌面文件：{} 拷贝成功".format(f.split("/")[-1]))
        self.remove_dir(unpack_path)

    """
    @brief  方向更新desktop文件至容器内,解决自启问题
    """  
    def update_kare_desktops_to_container(self, package_path):
        if "lbrowser" in package_path or "browser360-cn-stable" in package_path:
            return
        base =  "/opt/kare" if self.is_ostree else ""
        for desktop in set(self.desktops.desktops_list):
            path = Path(desktop.parts[0]).joinpath(*desktop.parts[3:])
            source = base + path.as_posix()
            target = package_path + path.as_posix()
            self.copy_file(target , target + ".bak")
            self.list_files.append(target + ".bak")
            try:
                self.copy_file(source , target)
            except Exception as e:
                self.log.error(e)

    """
    @brief  资源处理
    """  
    def resource_manager(self, d: Package, unpack_path: str, service_list):
        self.log.info("============ 资源处理 ============")
        self.desktops = Desktop(d, unpack_path, self.log)
        self.log.info("应用包 {} desktop文件列表：{}".format(d.package_name, self.desktops.desktops_list))
        # services = Service(d, unpack_path, self.log)
        # self.log.info("应用包 {} services文件列表：{}".format(d.package_name, services.services_list))
        rules = Udev(d, unpack_path, self.log)
        self.log.info("应用包 {} rules文件列表：{}".format(d.package_name, rules.rules_list))
        rules.edit_vp_dbus_udev_file(d, rules.rules_list)
        h5s = Html(d, unpack_path).h5_list
        # self.log.info("应用包 {} h5s文件列表：{}".format(d.package_name, h5s))
        self.icons = Icon(d, unpack_path)
        self.icons.find_icons_files()
        # self.log.info("应用包 {} icons文件列表：{}".format(d.package_name, icons))
        mimes = Mime(d, unpack_path, self.log)
        self.log.info("应用包 {} mime文件列表：{}".format(d.package_name, mimes.mime_list))
        # try:
        #     gsettings = Gsettings(d, unpack_path).gsettings_list
        #     self.log.info("应用包 {} gsettings文件列表：{}".format(d.package_name, gsettings))
        #     [self.kare_vp_cp(gsetting,False, 5, log=self.log) for gsetting in gsettings]
        # except FileNotFoundError as e:
        #     self.log.error("gsettings文件不存在")

        try:
            d_bus = Dbus(d, unpack_path, self.log)
            d_bus.edit_vp_dbus_service_file(d, d_bus.dbus_list)
            self.log.info("应用包 {} dbus文件列表：{}".format(d.package_name, d_bus.dbus_list))
            [self.kare_vp_cp(bus, self.chroot, log=self.log) for bus in d_bus.dbus_list]
        except FileNotFoundError as e:
            self.log.error("dbus文件不存在")

        self.desktops.edit_vp_desktop_file(d.package_name, self.desktops.desktops_list)
        #DKMS 类实例化 文件拷贝可以参考desktop
        # services.edit_vp_service_file(d, services.services_list)
        [self.kare_vp_cp(desktop, self.chroot, log=self.log) for desktop in self.desktops.desktops_list]
        [self.kare_vp_cp(service, self.chroot, log=self.log) for service in service_list]
        [self.kare_vp_cp(rule, self.chroot, log=self.log) for rule in rules.rules_list]
        [self.kare_vp_cp(mime, self.chroot, log=self.log ) for mime in mimes.mime_list]
        [self.kare_vp_cp(h5, self.chroot, log=self.log) for h5 in h5s]
        [self.kare_vp_cp(icon, self.chroot,icons=True, log=self.log) for icon in self.icons.icons_list]

        self._update_list_files(os.path.dirname(self.VP_DEBIAN_PATH))
        VpManager(d, self.desktops.desktops_list)

        
    """
    @brief  修改相关配置文件
    """  
    def updata_config(self, d:Package):
        self.log.info("============ 配置文件更新 ============")
        package_conf = {
            "version": d.package_version,
            "upgrade": self.upgrade,
            "base_env": self.base_env,
            "path": self.PACKAGE_SAVE_PATH + d.container_name if self.chroot == False else "/opt/kare-applications/" + d.container_name,
            "driver":d.is_driver or d.is_biometric(d.package),
            "dkms":d.is_dkms_driver,
            "file": self.list_files,
            "container_file": self.container_list_files,
            "desktop_files": self.desktop_list
        }
        self.set_config_json(self.INSTALL_JSON, d.package_name, package_conf)
        self.log.info("============ 更新dkmsContainer ko文件============")
        if d.is_dkms_driver:
            conf = self.get_config_json(self.INSTALL_JSON, "dkmsContainer")
            if conf is None:
                get_dkms_driver_list_cmd = "dkms status"
                exec = self.container.exec(f'{self.PACKAGE_SAVE_PATH}{d.container_name}/merge', get_dkms_driver_list_cmd)
                output = self.run_command_status_output(exec)
                if output[0] == 0:
                    output_lines = output[1].splitlines()
                    dkms_conf = {
                        "path" : self.PACKAGE_SAVE_PATH + d.container_name,
                        "base_env": self.base_env,
                        "upgrade": False,
                        "driver": False,
                        "dkms": True,
                        "file": [],
                        "container_file": [],
                        "kos":output_lines
                        }
                    self.set_config_json(self.INSTALL_JSON, "dkmsContainer", dkms_conf)
                else:
                    self.log.info(f"获取的dkms列表失败")
        self.log.info("============ Resources processed ============")
        # TODO
        Container.__init__(self, self.is_shadow(self.base_env), self.log, self.chroot,True)

    def _update_list_files(self, package_path):
        package_path = os.path.abspath(package_path)
        base_path = "/opt/kare/" if self.is_ostree else "/"
        for root, dirs, files in os.walk(package_path):
            rel_path = os.path.relpath(root, package_path)
            if rel_path == '.':
                rel_path = ''
            # 处理目录
            # for d in dirs:
            #     dir_entry = os.path.join(rel_path, d) if rel_path else d
            #     self.list_files.append(f"{base_path}{dir_entry}")
            # 处理文件
            for f in files:
                file_entry = os.path.join(rel_path, f) if rel_path else f
                if file_entry.endswith(".rules") and file_entry.startswith("etc/"):
                    self.list_files.append(f"/{file_entry}")
                elif file_entry.startswith("etc/init.d"):
                    self.list_files.append(f"/{file_entry}")
                elif file_entry.endswith(".desktop"):
                    if file_entry.startswith("etc/xdg/autostart"):
                        self.desktop_list.append(f"/{file_entry}")
                        self.list_files.append(f"/{file_entry}")
                    else:
                        self.list_files.append(f"{base_path}{file_entry}")
                        self.desktop_list.append(f"{base_path}{file_entry}")
                else:
                    self.list_files.append(f"{base_path}{file_entry}")

    def check_installation(self, d:Package):
        try:
            bus = dbus.SystemBus()
            proxy = bus.get_object(
                "com.kylin.kysdk.applicationsec",
                "/com/kylin/kysdk/applicationsec"
            )
            interface = dbus.Interface(
                proxy,
                dbus_interface="com.kylin.kysdk.applicationsec.antiinstall"
            )
            result = interface.GetPackageInstallStatus(d.package_name)
        except Exception as e:
            self.log.error(f"获取安全安装状态 DBus 调用失败: {e}")
            return True

        if result == 0:
            return True
        else:
            raise RuntimeError(self.KYSEC_REJECT_INSTALL)

    def ksaf_set_for_kare(self, d):
        app_files = list(set(self.list_files)| set(self.container_list_files))
        # self.log.info(f"打标记文件列表{app_files}")
        try:
            result = self.ksaf_set_label_for_kare(app_files, d.package_name)
            if result == 0:
                self.log.info("kare 应用标记设置成功")
            elif result == -1:
                self.log.error("kare 应用标记设置失败,参数错误")
            else:
                self.log.error("kare 应用标记设置失败")
        except Exception as e:
            self.log.error(f"kare 应用标记设置失败, 未知错误{e}")
        try:
            result = self.ksaf_exectl_xattr_multi_set(app_files, len(app_files))
            if result >= 0:
                self.log.info(f"执行控制接口设置成功,设置文件数量{result}")
            else:
                self.log.error("执行控制接口设置失败")
        except Exception as e:
            self.log.error(f"执行控制接口设置失败, 未知错误{e}")
        self.run_command("echo 3 > /proc/sys/vm/drop_caches")
    
    def copy_config_for_dkms(self, unpack_path, d):
        self.log.info(f"处理dkms配置文件的拷贝")
        if not os.path.exists(self.ETC_DKMS_CONFIG):
            self.log.error("dkms 配置文件不存在")
            return
        
        with open(self.ETC_DKMS_CONFIG) as file:
            conf = self.get_config_json(self.ETC_DKMS_CONFIG)
            for item in conf:
                src = item.get("src")
                dst = item.get("dst")

                src_dir = Path(self.PACKAGE_SAVE_PATH + d.container_name + "/merge" + src) 
                dst_dir = Path(dst)
                file_type = item.get('type', '.conf')
            
                if not src_dir.exists() or not src_dir.is_dir():
                    continue
                dst_dir.mkdir(parents=True, exist_ok=True)
                for file in src_dir.iterdir():
                    if file.is_file() and file.suffix == file_type and os.path.exists(unpack_path + src + file.name ):
                        dest_file = dst_dir / file.name
                        try:
                            shutil.copy(file, dest_file)
                            self.log.info(f"dkms:{file} -> {dest_file}")
                            package_conf = self.get_config_json(self.INSTALL_JSON, d.package_name)
                            file_list = package_conf.get("file", [])
                            file_list.append(str(dest_file))
                            conf = {
                                "version": package_conf.get("version"),
                                "upgrade": package_conf.get("upgrade",False),
                                "base_env": package_conf.get("base_env",""),
                                "path": package_conf.get("path",""),
                                "driver":package_conf.get("driver",False),
                                "dkms":package_conf.get("dkms",False),
                                "file": file_list,
                                "container_file": package_conf.get("container_file", []),
                                "desktop_files": package_conf.get("desktop_files", []),
                                "kos":package_conf.get("kos", [])
                            }
                            self.set_config_json(self.INSTALL_JSON, d.package_name, conf)
                        except Exception as e:
                            pass

