#!/usr/bin/python3

import datetime
import json
import os.path
import click

from pathlib import Path

import sys
for root, dirs, _ in os.walk("/usr/lib/python3/dist-packages"):
    for dir_name in dirs:
        if dir_name.startswith("UpgradeCheck"):
            sys.path.append(os.path.join(root, dir_name))
        if dir_name.startswith("DependCheck"):
            sys.path.append(os.path.join(root, dir_name))

from UpgradeCheck.util_common import result_path
from UpgradeCheck.util_conf import KpctConf
from UpgradeCheck.util_log import Log
from UpgradeCheck.util_database import KylinUpGradeDataBase
from UpgradeCheck.util_dbus import ExternalController
from UpgradeCheck.compare_lib import (SelfIncludeCompare, DiffSymCompare, DiffPreupgradeCompare, DiffLddCompare, SysLibInDeb, QtInDebCompare,
                                      DtSysLibInDeb, BaseCompare, DlopenCompare)
from UpgradeCheck.compare_file import (ConfFileCompare, PermissionCompare, DesktopCompare, ServiceFileCompare,
                                       MissingElfTarCompare, DbusUnderControl, PythonImportCompare)

# 默认值（与config.yaml一致，完全与配置文件解耦）
DEFAULT_COMPARE_LIST = ['PermissionCompare', 'ConfFileCompare', 'ServiceFileCompare',
                        'SysLibInDeb', 'SelfIncludeCompare', 'DiffSymCompare',
                        'DiffPreupgradeCompare', 'DiffLddCompare', 'QtInDebCompare',
                        'DtSysLibInDeb', 'DbusUnderControl']
DEFAULT_REPORT_FORMAT = 'all'
DEFAULT_SAVE_PATH = os.path.join(os.path.expanduser('~'), '.kpct', 'UpgradeCheck')
DEFAULT_SOURCE = None

# 当前检测内容，已转为可配置项
compare_list_for_dbus = [
    PermissionCompare,
    ConfFileCompare,
    ServiceFileCompare,
    SysLibInDeb,
    SelfIncludeCompare,
    DiffSymCompare,
    DiffLddCompare,
    QtInDebCompare,
    DtSysLibInDeb,
    DbusUnderControl,
    PythonImportCompare
]


def symbol_init():
    # BaseCompare.symbol_db_path = '/opt/kpct/UpgradeCheck/symbols.db'
    # packages_path = "/var/cache/kylin-system-updater/will_update_pkgs.json"
    # if os.path.exists(packages_path):
    #     with open(packages_path) as f:
    #         content = json.loads(f.read())
    #     BaseCompare.name_version = content["pkgs_upgrade"]
    deb_json_dir = '/var/cache/kpct/symbol'
    json_files = Path(deb_json_dir).glob("*.json")
    # {deb_name:{version:"v1", lib1:[s1, s2, s3...], lib2}}
    # 包名没用
    # {lib1: "s1\ns2\n...", lib2: "s1\ns2\n..."}
    sym_dict = {}
    for file in json_files:
        base_name = os.path.basename(file.as_posix())
        # name = base_name.split('_')[0]
        # version = base_name.split('_')[1].replace('%3', ':')
        with open(file.as_posix(), 'r') as f:
            # {"libname": "sym1\nsym2\n",...}
            content = json.loads(f.read())
        if not content:
            continue
        for elf, syms in content.items():
            sym_dict[elf] = syms
        # sym_dict[name]["version"] = version

    python_import_json = '/var/cache/kpct/python'
    py_json_files = Path(python_import_json).glob("*.json")
    pyi_dict = {}
    pyfile_attr_dict = {}
    for file in py_json_files:
        base_name = os.path.basename(file.as_posix())
        name = base_name.split('_')[0]
        # version = base_name.split('_')[1].replace('%3', ':')
        with open(file.as_posix(), 'r') as f:
            # {"libname": "sym1\nsym2\n",...}
            content = json.loads(f.read())
        if not content:
            continue
        pyi_dict[name] = list(content.keys())
        pyfile_attr_dict = {**pyfile_attr_dict, **content}

    BaseCompare.deb_json_dict = sym_dict
    BaseCompare.python_json_dict = pyi_dict
    BaseCompare.pyfile_json_dict = pyfile_attr_dict



def compare_for_dbus():
    start_time = datetime.datetime.now()
    symbol_init()
    kuc_log = Log().getlog()
    kuc_log.info('===== Upgrade升级检测: 信息检测开始')
    db_path = '{}/{}'.format(result_path, 'collect_information.db')
    kuc_process = ExternalController()
    progress_percect = 22

    if not os.path.exists(result_path):
        os.makedirs(result_path)

    if not os.path.exists(db_path):
        kuc_log.error('===== Upgrade升级检测: 数据库文件不存在，请重新运行collect后再试')
    else:
        kdb = KylinUpGradeDataBase(db_path)
        for compare in compare_list_for_dbus:
            obj = compare(kuc_log, kdb)
            obj.run()
            progress_percect += 2
            kuc_process.send_progress_signal(progress_percect)
        kdb.close()

    end_time = datetime.datetime.now()
    kuc_log.info("===== 扫描运行时间：{}s".format((end_time - start_time).total_seconds()))
    kuc_process.send_progress_signal(50)

    from UpgradeCheck.report import BaseInfo
    write_enablePackages_file = []
    import re
    round_1 = r'\((.*?)\)'
    for res in obj.status:
        write_enablePackages_file.append(re.findall(round_1, res[0])[0].strip())

    with open("{}/{}".format(result_path, "enablePackages"), 'w') as f:
        f.write(json.dumps(list(set(write_enablePackages_file))))
    base_report = BaseInfo(obj.compare_result, result_path)
    base_report.create_report()
    kuc_log.info("===== Upgrade报告生成完毕")

    end_time = datetime.datetime.now()
    kuc_log.info("===== Upgrade升级检测: 信息检测结束")
    kuc_log.info("===== Upgrade信息检测时间：{}s".format((end_time - start_time).total_seconds()))

@click.command()
@click.option('--dbus', is_flag=True, help="判断是否为dbus调用")
@click.option('--compare-list', '-l', 'compare_list_opt', multiple=True, help='指定比较项列表，如:PermissionCompare,ConfFileCompare')
@click.option('--save-path', '-s', 'save_path_opt', help='输出文件存放路径')
@click.option('--source', 'source_opt', help='目标源，用于符号对比:kylin-v4|kylin-v10|kylin-v10-sp1|custom|或指定.list文件')
@click.option('--report-format', '-r', 'report_format_opt', type=click.Choice(['all', 'excel', 'html']), help='输出结果格式')
def main(dbus, compare_list_opt, save_path_opt, source_opt, report_format_opt):
    if dbus:
        compare_for_dbus()
        return
    start_time = datetime.datetime.now()

    kuc_log = Log().getlog()
    kuc_log.info('===== Upgrade升级检测: 信息检测开始')

    # 检查是否有任何CLI参数被提供
    has_cli_args = any([
        compare_list_opt, save_path_opt, source_opt, report_format_opt
    ])

    if has_cli_args:
        # CLI模式：使用硬编码默认值
        save_path = save_path_opt if save_path_opt else DEFAULT_SAVE_PATH
        report_format = report_format_opt if report_format_opt else DEFAULT_REPORT_FORMAT
        source = source_opt if source_opt else DEFAULT_SOURCE

        # compare_list 默认为全选
        if compare_list_opt:
            compare_list = []
            for item in compare_list_opt:
                if ',' in item:
                    compare_list.extend([eval(i.strip()) for i in item.split(',')])
                else:
                    compare_list.append(eval(item.strip()))
        else:
            compare_list = [eval(i) for i in DEFAULT_COMPARE_LIST]
    else:
        # 配置模式：完全使用配置文件
        kpct_conf = KpctConf(kuc_log)
        save_path = kpct_conf.save_path
        report_format = kpct_conf.report_format
        source = kpct_conf.source
        compare_list = [eval(i) for i in kpct_conf.compare_list]

    if source:
        DiffSymCompare.target_source = source
    db_path = '{}/{}'.format(save_path, 'collect_information.db')

    if not os.path.exists(save_path):
        os.makedirs(save_path)

    if not os.path.exists(db_path):
        kuc_log.error('===== Upgrade升级检测: 数据库文件不存在，请重新运行collect后再试')
        return

    kdb = KylinUpGradeDataBase(db_path)
    obj = None
    for compare in compare_list:
        obj = compare(kuc_log, kdb)
        obj.run()
    kdb.close()

    # 如果没有执行任何比较器，使用默认空集合
    if obj is None:
        obj = type('obj', (), {'return_deb_set': set(), 'unfix_deb_set': set(), 'compare_result': {}})()

    # 写入enablePackages和disablePackages
    enable_list = list(obj.return_deb_set)
    disable_list = list(obj.return_deb_set | obj.unfix_deb_set)
    from UpgradeCheck.report import BaseInfo

    with open("{}/{}".format(result_path, "enablePackages"), 'w') as f1:
        json.dump(enable_list, f1)
    with open("{}/{}".format(result_path, "disablePackages"), 'w') as f2:
        json.dump(disable_list, f2)

    end_time = datetime.datetime.now()
    kuc_log.info("===== 扫描运行时间：{}s".format((end_time - start_time).total_seconds()))

    from UpgradeCheck.report import BaseInfo

    base_report = BaseInfo(obj.compare_result, save_path)
    if report_format == 'all':
        kuc_log.info("===== 生成html及excel报告")
        base_report.create_report()
        base_report.create_excel_report()
    elif report_format == 'excel':
        kuc_log.info("===== 生成excel报告")
        base_report.create_excel_report()
    kuc_log.info("===== Upgrade报告生成完毕")

    end_time = datetime.datetime.now()
    kuc_log.info("===== Upgrade升级检测: 信息检测结束")
    kuc_log.info("===== Upgrade信息检测时间：{}s".format((end_time - start_time).total_seconds()))


if __name__ == "__main__":
    main()
