"""
转换相关的辅助函数

提供配置合并、转换执行等功能，简化工作区脚本。
"""

from collections.abc import Callable
from pathlib import Path

from mark2pdf.core import ConversionOptions, convert_directory, convert_file
from mark2pdf.core.utils import merge_frontmatter, open_with_system
from mark2pdf.helper_markdown import extract_frontmatter

from .config import ConfigManager, load_frontmatter_yaml, resolve_template


def run_conversion(
    filename: str,
    workspace_dir: Path,
    postprocess: Callable[[str], str] | None = None,
    *,
    verbose: bool = False,
    overwrite: bool = False,
    template: str | None = None,
    tc: bool = False,
    open_file: bool = False,
    force_filename: bool = False,
) -> bool:
    """
    执行 Markdown 到 PDF 的转换

    这是工作区脚本使用的主入口函数，封装了全部转换逻辑。

    Args:
        filename: 输入文件名
        workspace_dir: 工作区目录
        postprocess: 后处理函数（可选）
        verbose: 显示详细信息
        overwrite: 覆盖输出文件
        template: 指定模板（CLI 优先级最高）
        tc: 转换为繁体中文
        open_file: 转换完成后打开文件

    Returns:
        转换是否成功
    """
    # 加载配置
    config = ConfigManager.load(start_dir=workspace_dir)

    # 合并 overwrite：CLI > config
    final_overwrite = overwrite or config.options.overwrite

    # 加载默认 frontmatter
    default_fm = load_frontmatter_yaml(workspace_dir)
    if config.frontmatter:
        default_fm = merge_frontmatter(config.frontmatter, default_fm)

    # 读取文件 frontmatter（用于 template）
    input_path = config.input_dir / filename
    file_fm = extract_frontmatter(input_path) if input_path.exists() else {}

    merged_fm = merge_frontmatter(default_fm, file_fm)

    # 构建 options
    options = ConversionOptions(
        verbose=verbose,
        overwrite=final_overwrite,
        tc=tc,
        force_filename=force_filename,
    )

    options.template = resolve_template(
        cli_template=template,
        frontmatter_template=merged_fm.get("theme", {}).get("template"),
        config_template=config.options.default_template,
    )

    # 执行转换
    result = convert_file(
        input_file=filename,
        options=options,
        indir=config.paths.input,
        outdir=config.paths.output,
        default_frontmatter=default_fm if default_fm else None,
        postprocess=postprocess,
        config=config,
    )

    if result and open_file:
        open_with_system(result, verbose=verbose)

    return result is not None


def run_directory_conversion(
    directory: str,
    workspace_dir: Path,
    postprocess: Callable[[str], str] | None = None,
    *,
    verbose: bool = False,
    overwrite: bool = False,
    template: str | None = None,
    tc: bool = False,
    open_file: bool = False,
    force_filename: bool = False,
) -> bool:
    """
    执行目录到 PDF 的转换（合并目录中所有 Markdown 文件）

    Args:
        directory: 目录名（相对于 input 路径）
        workspace_dir: 工作区目录
        postprocess: 后处理函数（可选）
        verbose: 显示详细信息
        overwrite: 覆盖输出文件
        template: 指定模板（CLI 优先级最高）
        tc: 转换为繁体中文
        open_file: 转换完成后打开文件

    Returns:
        转换是否成功
    """
    # 加载配置
    config = ConfigManager.load(start_dir=workspace_dir)

    # 合并 overwrite：CLI > config
    final_overwrite = overwrite or config.options.overwrite

    # 加载默认 frontmatter（与 run_conversion 一致）
    default_fm = load_frontmatter_yaml(workspace_dir)
    if config.frontmatter:
        default_fm = merge_frontmatter(config.frontmatter, default_fm)

    # 读取目录中 index.mdx/index.md 的 frontmatter（用于 template）
    dir_path = config.input_dir / directory
    index_path = dir_path / "index.mdx"
    if not index_path.exists():
        index_path = dir_path / "index.md"
    file_fm = extract_frontmatter(index_path) if index_path.exists() else {}

    merged_fm = merge_frontmatter(default_fm, file_fm)

    # 构建 options
    options = ConversionOptions(
        verbose=verbose,
        overwrite=final_overwrite,
        tc=tc,
        force_filename=force_filename,
    )

    options.template = resolve_template(
        cli_template=template,
        frontmatter_template=merged_fm.get("theme", {}).get("template"),
        config_template=config.options.default_template,
    )

    # 执行目录转换
    result = convert_directory(
        directory=directory,
        options=options,
        indir=config.paths.input,
        outdir=config.paths.output,
        default_frontmatter=default_fm if default_fm else None,
        config=config,
        postprocess=postprocess,
    )

    if result and open_file:
        open_with_system(result, verbose=verbose)

    return result is not None


def run_batch_conversion(
    directory: str,
    workspace_dir: Path,
    postprocess: Callable[[str], str] | None = None,
    *,
    verbose: bool = False,
    overwrite: bool = False,
    template: str | None = None,
    tc: bool = False,
    open_file: bool = False,
    force_filename: bool = False,
) -> bool:
    """
    执行批量转换（逐一转换目录中每个 Markdown 文件）

    与 run_directory_conversion 不同，不会合并文件，而是逐一生成 PDF。

    Args:
        directory: 目录名（相对于 input 路径），使用 "." 表示当前目录
        workspace_dir: 工作区目录
        postprocess: 后处理函数（可选）
        verbose: 显示详细信息
        overwrite: 覆盖输出文件
        template: 指定模板（CLI 优先级最高）
        tc: 转换为繁体中文
        open_file: 转换完成后打开文件（批量模式不支持）

    Returns:
        全部转换成功返回 True，任一失败返回 False
    """
    # 加载配置
    config = ConfigManager.load(start_dir=workspace_dir)

    # 合并 overwrite：CLI > config
    final_overwrite = overwrite or config.options.overwrite

    # 确定输入目录
    if directory == ".":
        input_dir = config.input_dir
        output_subdir = config.output_dir
    else:
        input_dir = config.input_dir / directory
        output_subdir = config.output_dir / directory

    if not input_dir.exists():
        print(f"错误：目录不存在：{input_dir}")
        return False

    # 加载工作区默认 frontmatter
    workspace_fm = load_frontmatter_yaml(workspace_dir)
    if config.frontmatter:
        workspace_fm = merge_frontmatter(config.frontmatter, workspace_fm)

    # 读取目录中 index.md 的 frontmatter（作为目录级默认值）
    index_path = input_dir / "index.md"
    index_fm = extract_frontmatter(index_path) if index_path.exists() else {}

    # 合并目录级 frontmatter（index.md 覆盖工作区默认值）
    # 注意：排除 title 和 exportFilename，这些应该是每个文件特有的
    default_fm = workspace_fm
    if index_fm:
        index_fm_for_default = {
            k: v for k, v in index_fm.items()
            if k not in ("title", "exportFilename")
        }
        default_fm = merge_frontmatter(workspace_fm, index_fm_for_default)

    options_base_fm = merge_frontmatter(workspace_fm, index_fm)

    # 获取文件列表（排除 index.md）
    md_files = [
        f for f in input_dir.glob("*.md")
        if f.name != "index.md"
    ]

    if not md_files:
        print(f"警告：目录中没有 Markdown 文件（除 index.md 外）：{input_dir}")
        return True

    # 逐一转换
    success_count = 0
    fail_count = 0

    print(f"批量转换：{len(md_files)} 个文件")
    print(f"输入目录：{input_dir}")
    print(f"输出目录：{output_subdir}")
    print("-" * 40)

    for md_file in sorted(md_files):
        # 确定每个文件的输入/输出目录
        if directory == ".":
            file_indir = config.paths.input
            file_outdir = config.paths.output
        else:
            file_indir = f"{config.paths.input}/{directory}"
            file_outdir = f"{config.paths.output}/{directory}"

        print(f"处理：{md_file.name}")

        file_fm = extract_frontmatter(md_file) if md_file.exists() else {}
        merged_fm = merge_frontmatter(options_base_fm, file_fm)

        options = ConversionOptions(
            verbose=verbose,
            overwrite=final_overwrite,
            tc=tc,
            force_filename=force_filename,
        )

        options.template = resolve_template(
            cli_template=template,
            frontmatter_template=merged_fm.get("theme", {}).get("template"),
            config_template=config.options.default_template,
        )

        result = convert_file(
            input_file=md_file.name,  # 纯文件名
            options=options,
            indir=file_indir,         # 包含子目录的输入路径
            outdir=file_outdir,       # 包含子目录的输出路径
            default_frontmatter=default_fm if default_fm else None,
            config=config,
        )


        if result:
            success_count += 1
        else:
            fail_count += 1

    # 汇报结果
    print("-" * 40)
    print(f"完成：成功 {success_count}，失败 {fail_count}")

    return fail_count == 0
