# Copyright (c) 2025 Huawei Technologies Co., Ltd.
# openUBMC is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#         http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
import argparse
import json
import logging
import os
from pathlib import Path
from typing import Dict, Any


DEFAULT_TEMP_PATH = 'temp/opt/bmc/apps/mbd_interface'


class MDBMarkdownGenerator:
    def __init__(self, mdb_root: str, interface_type: str):
        self.mdb_root = mdb_root
        self.interface_type = interface_type
        self.md_content = []

    # 解析类型定义
    @staticmethod
    def _resolve_type(definition: Dict) -> str:
        if definition.get('baseType') == 'Dictionary':
            return definition.get('$ref', '').split('#/defs/')[-1]
        return definition.get('baseType', 'unknown')

    # 生成并保存文档
    def generate(self, output_dir: str):
        mdbtree = self._read_json_files()
        os.makedirs(output_dir, exist_ok=True)

        for interface_name, interface_def in sorted(mdbtree.items()):
            self.md_content.append(f"# {interface_name}")

            # 生成属性章节
            props_section = self._generate_properties_table(interface_def.get('properties', {}))
            if props_section:
                self.md_content.append(props_section)

            # 生成方法章节
            methods_section = self._generate_methods_section(interface_def.get('methods', {}))
            if methods_section:
                self.md_content.append(methods_section)

            # 生成自定义类型章节
            defs_section = self._generate_defs_section(interface_def.get('defs', {}))
            if defs_section:
                self.md_content.append(defs_section)

        # 写入文件
        output_path = Path(output_dir) / f'{self.interface_type}_interface.md'
        with output_path.open('w', encoding='utf-8') as f:
            f.write('\n\n'.join(self.md_content))
        logging.info(f'文档已生成“{output_path}')

    # 读取所有接口JSON文件
    def _read_json_files(self) -> Dict[str, Any]:
        mdbtree = {}
        json_dir = Path(self.mdb_root) / 'json' / 'intf' / 'mdb' / 'bmc' / self.interface_type
        for json_path in json_dir.rglob('*.json'):
            try:
                with json_path.open(encoding='utf-8') as f:
                    content = json.load(f)
            except (IOError, json.JSONDecodeError) as e:
                logging.warning(f"读取文件 {json_path} 失败 - {str(e)}")
                continue

            for key, value in content.items():
                if f'bmc.{self.interface_type}' in key:
                    mdbtree[key] = value
                    if 'defs' in content:
                        mdbtree[key]['defs'] = content['defs']
        return mdbtree

    # 生成属性表格
    def _generate_properties_table(self, properties: Dict[str, Any]) -> str:
        if not properties:
            return ''
        table = [
            '**==属性==**',
            '| 属性名 | 类型 | 可读写 | 信号通知 | 描述 |',
            "|-------|------|-------|---------|------|"
        ]

        for prop_name, prop_def in properties.items():
            prop_type = self._resolve_type(prop_def)
            read_write = "只读" if prop_def.get('readOnly', False) else "读写"
            signal = "变更广播" if prop_def.get('options', {}).get('emitChangedSignal', True) else "无"
            description = prop_def.get('description', '').replace('\n', ' ')

            table.append(
                f" | `{prop_name}` | `{prop_type}` |{read_write} | {signal} | {description} |"
            )
        return '\n'.join(table)

    # 生成单个方法文档
    def _generate_method_section(self, method_def: Dict[str, Any]) -> str:
        sections = ["\n"]
        if 'description' in method_def:
            sections.append(f'{method_def["description"]}\n')

        # 处理输入参数
        if 'req' in method_def and method_def['req']:
            input_table = [
                "**参数**",
            ]
            for param_name, param_def in method_def['req'].items():
                param_type = self._resolve_type(param_def)
                description = param_def.get('description', '').replace('\n', ' ').replace('{', '[').replace('}', ']')
                l = f"- `{param_name}`: {param_type} {('\\- ' + description) if description else ''}"
                input_table.append(l)
            sections.append('\n'.join(input_table))

        # 处理输出参数
        if 'rsp' in method_def and method_def['rsp']:
            output_table = [
                "\n**返回值**",
            ]
            for param_name, param_def in method_def['rsp'].items():
                param_type = self._resolve_type(param_def)
                description = param_def.get('description', '').replace('\n', ' ').replace('{', '[').replace('}', ']')
                l = f"- `{param_name}`: {param_type} {('\\- ' + description) if description else ''}"
                output_table.append(l)
            sections.append('\n'.join(output_table))
        sections.append('\n---\n')
        return '\n'.join(sections)

    # 生成方法文档
    def _generate_methods_section(self, methods: Dict[str, Any]) -> str:
        if not methods:
            return ''

        sections = ["**==方法==**\n\n---\n"]
        for method_name, method_def in methods.items():
            sections.append(f"`{method_name}`{self._generate_method_section(method_def)}")
        return '\n'.join(sections)

    #生成自定义类型文档
    def _generate_defs_section(self, defs: Dict[str, Any]) -> str:
        if not defs:
            return ''

        sections = ["**==自定义类型==**"]
        for type_name, type_def in defs.items():
            # 判断是否为枚举类型（即所有字段皆为整数）
            is_enum = all(isinstance(value, int) for value in type_def.values())

            t = []
            if is_enum:
                t.append(f"---\n`{type_name}`: 枚举类型")
                for field_name, field_value in type_def.items():
                    t.append(f"- {field_value}: `{field_name}`")
            else:
                t.append(f"---\n`{type_name}`: 结构体类型")
                for field_name, field_value in type_def.items():
                    if isinstance(field_value, dict):
                        field_type = self._resolve_type(field_value)
                        description = field_value.get('description', '').replace('\n', ' ')
                        t.append(f"- `{field_name}`: {field_type} {('\\- ' + description) if description else ''}")
            sections.append('\n'.join(t))
        
        return '\n\n'.join(sections)


def main():
    parser = argparse.ArgumentParser(
        prog='mdb-docgen',
        description='MDB 结构文档生成工具'
    )
    parser.add_argument('-t', '--type',
                        required=True,
                        choices=['dev', 'kepler'],
                        help='接口类型：dev-设备接口，kepler-资源接口')
    parser.add_argument('-p', '--path',
                        default=DEFAULT_TEMP_PATH,
                        help=F'MDB仓库路径（默认：{DEFAULT_TEMP_PATH})')
    parser.add_argument('-o', '--output',
                        default='./docs',
                        help='输出目录（默认，/docs）')

    args = parser.parse_args()

    generator = MDBMarkdownGenerator(
        mdb_root=args.path,
        interface_type=args.type,
    )

    try:
        generator.generate(output_dir=args.output)
    except Exception as e:
        logging.fatal(f"生成文档时发生错误：{str(e)}")
        exit(1)


if __name__ == '__main__':
    main()