#!/usr/bin/env python
"""
@Project ：django_base_ai
@File    ：model_to_markdown.py
@Author  ：congxing.wang
@Date    ：2026/02/25
@Desc    ：Django 模型转 Markdown 文档
"""

import logging
import os
import sys
from collections import OrderedDict

import django

logger = logging.getLogger(__name__)
from django.apps import apps
from django.db import connection

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "DjangoBaseAi.settings")
django.setup()

args = sys.argv

models = apps.all_models


def get_app_models(arg: str, all_models: OrderedDict) -> OrderedDict:
    """
    arg is command line first value passed
    """
    return all_models if arg == "all" else all_models[arg]


file_path = args[2] if len(args) == 3 else "fields_detail.md"

if not file_path.endswith(".md"):
    logger.error("输出路径须为 .md 文件，当前: %s", file_path)
    sys.exit(1)

try:
    arg = args[1]
    all_models = get_app_models(arg, models)
    # all_models is an OrderDict
except IndexError:
    all_models = models.values()

markdown_lines = []

table_name = """\n\n## {0}--{1}\n\n"""
table_header = """| 字段名 | 数据类型 | 允许为空 | PK | 字段说明 |
| ---- | ---- | ---- | --- | ---- |
"""
field_desc_str = "| {0} | {1} | {2} | {3} | {4} |"
new_line_str = "\n"


def get_models_fields() -> None:
    """
    get all models and fields,
    format field description into field_desc_str
    and write in file fields_detail.md by default
    if given a specific app name, and file name,
    write fields into a specific file
    :return:
    :rtype:
    """
    for model_odict in all_models:
        for model in model_odict.values():
            markdown_lines.append(table_name.format(model.__name__, model._meta.db_table))
            fields_list = model._meta.get_fields()
            markdown_lines.append(table_header)
            for field in fields_list:
                field_name = field.name
                field_type = field.db_type(connection)
                field_null = field.null
                try:
                    field_limit = field.primary_key
                except AttributeError:
                    field_limit = False
                try:
                    field_verbose = field.verbose_name
                except AttributeError:
                    field_verbose = " "
                _field_str = field_desc_str.format(
                    str(field_name),
                    str(field_type),
                    str(field_null),
                    str(field_limit),
                    str(field_verbose),
                )
                print("_field_str: ", _field_str, end=new_line_str)
                markdown_lines.append(_field_str + new_line_str)
            markdown_lines.append(new_line_str * 2)


def write_to_md(file_path: str) -> None:
    """
    write fields detail into a markdown file,
    file_path could be specific
    :param file_path:
    :type file_path:
    :return:
    :rtype:
    """
    with open(file_path, "w") as fp:
        print("prepare to write markdown file")
        print(len(markdown_lines))
        fp.writelines(markdown_lines)


usage = """
usage:
$ python model_fields.py
---> fields_detail.md
$ python model_fields.py api_home
---> fields_detail.md  # include all models in api_home module
$ python models_fields.py all ~/docs/model_field.md
---> ~/docs/model_field.md  # include all models and output a specific markdown file
$ python model_fields.py company company_models.md
---> company_models.md  # include all models in company models
     and output a specific markdown file
"""


def main(file_path: str) -> None:
    """
    run this function by default,
    will call the get and write method
    :param file_path:
    :type file_path:
    :return:
    :rtype:
    """
    get_models_fields()
    write_to_md(file_path)


if __name__ == "__main__":
    main(file_path)
