#!/usr/bin/env python
# markdown_to_project.py
# Recreate a project's directory structure and files from a single markdown file.
# This script is the reverse of the 'project-to-markdown' tool.

from __future__ import annotations

import argparse
import re
from pathlib import Path


def _normalize_parsed_path(path_str: str) -> str:
    """Remove wrapping and segment-trailing backticks from parsed paths."""
    normalized = path_str.strip().strip("`")
    normalized = re.sub(r"(?:(?<=^)|(?<=[\\/]))`+", "", normalized)
    return re.sub(r"`+(?=(?:[\\/]|$))", "", normalized)


def parse_markdown_to_files(markdown_content: str) -> dict[str, str]:
    """
    Parses markdown content to extract file paths and their code blocks.

    This version uses a strict regex to ensure that a file header is
    immediately followed by a code block, correctly parsing each file
    without mixing sections.
    """
    # This stricter regex ensures the captured file path is on a single line
    # by matching any character except a newline ([^\n\r]+).
    pattern = re.compile(
        r"^##\s*([^\n\r]+)\s*\n```(?:[a-zA-Z]*)?\n(.*?)\n```",
        re.DOTALL | re.MULTILINE
    )

    files: dict[str, str] = {}
    for match in pattern.finditer(markdown_content):
        # Group 1: The file path (e.g., ".gitignore")
        path_str = _normalize_parsed_path(match.group(1))

        # Group 2: The file content
        content = match.group(2)

        # Reverse the backtick escaping
        content = content.replace("``\u200b`", "```")

        files[path_str] = content

    return files

def create_project_from_files(
        output_dir: Path,
        files: dict[str, str],
        overwrite: bool = False
) -> None:
    """
    Creates the directory structure and files in the specified output directory.

    Args:
        output_dir: The root directory where the project will be created.
        files: A dictionary mapping relative file paths to their content.
        overwrite: If True, allows writing into a non-empty directory.

    Raises:
        SystemExit: If the output directory is not empty and overwrite is False.
    """
    if output_dir.exists() and any(output_dir.iterdir()) and not overwrite:
        raise SystemExit(
            f"[error] Output directory '{output_dir}' is not empty. "
            "Use --overwrite to force."
        )

    output_dir.mkdir(parents=True, exist_ok=True)
    print(f"Creating project in: {output_dir.resolve()}")

    if not files:
        print("[warning] No files were found in the markdown input.")
        return

    for rel_path_str, content in files.items():
        file_path = output_dir / rel_path_str
        print(f"  - Creating: {rel_path_str}")

        # Ensure the parent directory for the file exists.
        file_path.parent.mkdir(parents=True, exist_ok=True)

        # Write the content to the file, using UTF-8 encoding.
        try:
            file_path.write_text(content, encoding="utf-8")
        except IOError as e:
            print(f"[error] Could not write to file {file_path}: {e}")


def main() -> None:
    """Main entry point and CLI handler."""
    parser = argparse.ArgumentParser(
        description="Recreate a project from a markdown file generated by 'project-to-markdown'."
    )
    parser.add_argument(
        "-i", "--input",
        type=Path,
        required=True,
        help="Input markdown file containing the project source.",
    )
    parser.add_argument(
        "-o", "--output",
        type=Path,
        default=Path("recreated_project"),
        help="Output directory to recreate the project in (default: 'recreated_project').",
    )
    parser.add_argument(
        "--overwrite",
        action="store_true",
        help="Allow writing into an existing, non-empty output directory.",
    )
    args = parser.parse_args()

    # --- Input Validation ---
    if not args.input.is_file():
        raise SystemExit(f"[error] Input file not found: {args.input}")

    # --- Core Logic ---
    try:
        print(f"Reading from '{args.input}'...")
        markdown_content = args.input.read_text(encoding="utf-8")

        file_data = parse_markdown_to_files(markdown_content)

        create_project_from_files(args.output, file_data, args.overwrite)

        print(f"\n[ok] Project successfully recreated with {len(file_data)} files.")
    except Exception as e:
        # Catch any other unexpected errors during processing.
        raise SystemExit(f"[error] An unexpected error occurred: {e}")


if __name__ == "__main__":
    main()