#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
自动将docs目录下的文件添加到mkdocs.yml导航配置中
"""

import os
import sys
import re
import yaml
from pathlib import Path

def load_mkdocs_nav(mkdocs_path='mkdocs.yml'):
    """加载mkdocs.yml中的导航配置"""
    try:
        with open(mkdocs_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # 使用正则表达式提取nav部分
        nav_match = re.search(r'nav:\s*\n(.*?)(?=\n\w+:|$)', content, re.DOTALL)
        if not nav_match:
            print("错误: 找不到nav配置")
            sys.exit(1)
        
        nav_content = nav_match.group(1)
        
        # 解析YAML格式的nav内容
        # 为nav内容添加适当的缩进
        nav_yaml = "nav:\n" + nav_content
        config = yaml.safe_load(nav_yaml)
        return config.get('nav', [])
        
    except FileNotFoundError:
        print(f"错误: 找不到文件 {mkdocs_path}")
        sys.exit(1)
    except Exception as e:
        print(f"错误: 解析文件失败: {e}")
        sys.exit(1)

def save_mkdocs_nav(nav, mkdocs_path='mkdocs.yml'):
    """保存导航配置到mkdocs.yml"""
    try:
        with open(mkdocs_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # 生成新的nav内容
        nav_yaml = yaml.dump({'nav': nav}, allow_unicode=True, default_flow_style=False, sort_keys=False)
        
        # 移除第一行的"nav:"
        nav_lines = nav_yaml.split('\n')
        new_nav_content = '\n'.join(nav_lines[1:])  # 跳过第一行
        
        # 替换原有的nav部分，使用re.escape避免特殊字符问题
        nav_pattern = r'(nav:\s*\n)(.*?)(?=\n\w+:|$)'
        # 对new_nav_content进行转义处理
        escaped_content = re.escape(new_nav_content)
        # 但我们需要保留实际的换行符等，所以使用更简单的方法
        new_content = re.sub(nav_pattern, r'\1' + new_nav_content, content, flags=re.DOTALL)
        
        with open(mkdocs_path, 'w', encoding='utf-8') as f:
            f.write(new_content)
        
        print(f"✓ 已更新 {mkdocs_path}")
        
    except Exception as e:
        print(f"错误: 保存文件失败: {e}")
        sys.exit(1)

def get_all_md_files(docs_dir='docs'):
    """获取docs目录下的所有.md文件"""
    md_files = []
    for root, dirs, files in os.walk(docs_dir):
        for file in files:
            if file.endswith('.md'):
                rel_path = os.path.relpath(os.path.join(root, file), docs_dir)
                # 将Windows路径分隔符转换为Unix风格（/）
                rel_path = rel_path.replace('\\', '/')
                md_files.append(rel_path)
    return sorted(md_files)

def get_nav_files(nav):
    """从导航配置中提取所有文件路径"""
    nav_files = []
    
    def extract_files(item):
        if isinstance(item, dict):
            for key, value in item.items():
                if isinstance(value, list):
                    for subitem in value:
                        extract_files(subitem)
                elif isinstance(value, str):
                    nav_files.append(value)
        elif isinstance(item, str):
            nav_files.append(item)
    
    for item in nav:
        extract_files(item)
    
    return nav_files

def categorize_file(file_path):
    """根据文件路径分类文件"""
    path_parts = file_path.split('/')
    
    # 如果文件在根目录
    if len(path_parts) == 1:
        return "其他"
    
    # 根据目录名分类
    category_map = {
        '技术文档': '技术文档',
        '开发指南': '开发指南',
        '学习笔记': '学习笔记',
        'DevOps平台': 'DevOps平台',
        'cursor': 'Cursor工具',
        'Obsidian': 'Obsidian笔记'
    }
    
    first_dir = path_parts[0]
    # 如果目录名在映射中，使用映射的名称，否则使用目录名
    return category_map.get(first_dir, first_dir)

def remove_deleted_files_from_nav(nav, existing_files=None, docs_dir='docs'):
    """从导航配置中删除已不存在的文件"""
    deleted_files = []
    
    def clean_item(item):
        """递归清理导航项，删除不存在的文件"""
        if isinstance(item, dict):
            # 处理字典类型（分类）
            cleaned_dict = {}
            for key, value in item.items():
                if isinstance(value, list):
                    # 递归处理列表
                    cleaned_list = []
                    for subitem in value:
                        cleaned = clean_item(subitem)
                        if cleaned is not None:
                            cleaned_list.append(cleaned)
                    
                    # 如果列表不为空，保留分类
                    if cleaned_list:
                        cleaned_dict[key] = cleaned_list
                elif isinstance(value, str):
                    # 检查文件是否存在
                    file_path = os.path.join(docs_dir, value.replace('/', os.sep))
                    if os.path.exists(file_path) or value == 'index.md':
                        cleaned_dict[key] = value
                    else:
                        deleted_files.append(value)
                else:
                    # 其他类型，保留
                    cleaned_dict[key] = value
            
            # 如果字典为空，返回None表示删除
            return cleaned_dict if cleaned_dict else None
        elif isinstance(item, str):
            # 检查文件是否存在
            file_path = os.path.join(docs_dir, item.replace('/', os.sep))
            if os.path.exists(file_path) or item == 'index.md':
                return item
            else:
                deleted_files.append(item)
                return None
        else:
            # 其他类型，保留
            return item
    
    # 处理导航列表
    new_nav = []
    for item in nav:
        cleaned = clean_item(item)
        if cleaned is not None:
            new_nav.append(cleaned)
    
    return new_nav, deleted_files

def add_files_to_nav(nav, missing_files):
    """将缺失的文件添加到导航配置中"""
    # 创建分类字典
    categories = {}
    for file_path in missing_files:
        category = categorize_file(file_path)
        if category not in categories:
            categories[category] = []
        categories[category].append(file_path)
    
    # 将文件添加到现有分类或创建新分类
    for category, files in categories.items():
        category_found = False
        
        # 查找是否已存在该分类
        for i, item in enumerate(nav):
            if isinstance(item, dict) and category in item:
                # 添加到现有分类
                existing_files = set(item[category])
                for file_path in files:
                    if file_path not in existing_files:
                        item[category].append(file_path)
                category_found = True
                print(f"✓ 已将 {len(files)} 个文件添加到 '{category}' 分类")
                break
        
        # 如果分类不存在，创建新分类
        if not category_found:
            nav.append({category: sorted(files)})
            print(f"✓ 已创建新分类 '{category}' 并添加 {len(files)} 个文件")
    
    return nav

def main():
    print("开始自动同步docs目录和mkdocs.yml导航配置...")
    print("=" * 60)
    
    # 1. 加载当前导航配置
    print("1. 加载mkdocs.yml导航配置...")
    nav = load_mkdocs_nav()
    
    # 2. 获取所有.md文件
    print("2. 扫描docs目录下的所有.md文件...")
    all_md_files = get_all_md_files()
    print(f"   找到 {len(all_md_files)} 个.md文件")
    
    # 3. 获取导航中的文件
    print("3. 分析当前导航配置...")
    nav_files = get_nav_files(nav)
    print(f"   导航中已有 {len(nav_files)} 个文件")
    
    # 4. 检查并删除已删除的文件
    print("4. 检查已删除的文件...")
    updated_nav, deleted_files = remove_deleted_files_from_nav(nav, all_md_files)
    
    if deleted_files:
        print(f"   发现 {len(deleted_files)} 个文件已删除:")
        for i, file_path in enumerate(deleted_files, 1):
            print(f"   {i:2d}. {file_path}")
        nav = updated_nav
        # 重新获取导航文件列表（已更新）
        nav_files = get_nav_files(nav)
    else:
        print("   ✓ 没有发现已删除的文件")
    
    # 5. 找出缺失的文件（需要添加到导航的）
    missing_files = []
    for md_file in all_md_files:
        # 将路径统一为Unix风格进行比较
        if md_file not in nav_files and md_file != 'index.md':
            missing_files.append(md_file)
    
    # 6. 汇总变更
    has_changes = len(deleted_files) > 0 or len(missing_files) > 0
    
    if not has_changes:
        print("\n✓ 导航配置已是最新，无需更新")
        return
    
    # 显示变更摘要
    print("\n5. 变更摘要:")
    if deleted_files:
        print(f"   将删除 {len(deleted_files)} 个已不存在的文件")
    if missing_files:
        print(f"   将添加 {len(missing_files)} 个新文件:")
        for i, file_path in enumerate(missing_files, 1):
            print(f"   {i:2d}. {file_path}")
    
    # 7. 确认是否继续
    print("\n6. 是否继续更新mkdocs.yml？")
    response = input("   输入 'y' 继续，其他键取消: ")
    
    if response.lower() != 'y':
        print("操作已取消")
        return
    
    # 8. 添加文件到导航
    print("\n7. 正在更新mkdocs.yml...")
    if missing_files:
        updated_nav = add_files_to_nav(updated_nav, missing_files)
    
    # 9. 保存配置
    save_mkdocs_nav(updated_nav)
    
    print("\n" + "=" * 60)
    print("完成！mkdocs.yml已更新")
    if deleted_files:
        print(f"删除了 {len(deleted_files)} 个已不存在的文件")
    if missing_files:
        print(f"添加了 {len(missing_files)} 个新文件到导航中")

if __name__ == '__main__':
    main()
