import shutil
import sys
from pathlib import Path

from splitnodes import markdown_to_html_node


def main():
    if len(sys.argv) < 3:
        raise RuntimeError("Please provide destination and basepath: <destination> <base_path>")

    destination_dir = sys.argv[1]
    basepath = sys.argv[2]

    copy_static(destination_dir)
    generate_pages("content", "template.html", destination_dir, basepath)


def copy_static(destination: str) -> None:
    source_path = Path("static")
    destination_path = Path(destination)

    if not source_path.exists():
        raise FileNotFoundError(f"Source directory '{source_path}' does not exist.")

    if destination_path.exists():
        print(f"Cleaning contents of '{destination_path}'...")

        for item in destination_path.iterdir():
            if item.is_dir():
                shutil.rmtree(item)
            else:
                item.unlink()
    else:
        destination_path.mkdir(parents=True, exist_ok=True)

    print(f"Copying files from '{source_path}' to '{destination_path}'...")

    for item in source_path.rglob("*"):
        relative_path = item.relative_to(source_path)
        target_path = destination_path / relative_path

        if item.is_dir():
            target_path.mkdir(parents=True, exist_ok=True)
        else:
            target_path.parent.mkdir(parents=True, exist_ok=True)
            shutil.copy2(item, target_path)

    print(f"Finished copying files from '{source_path}' to '{destination_path}'")


def generate_pages(
    dir_path_content: str, template_path: str, dest_dir_path: str, basepath: str
) -> None:
    content_dir = Path(dir_path_content)
    template = Path(template_path)
    dest_dir = Path(dest_dir_path)

    print(f"Crawling '{content_dir}' to generate HTML pages in '{dest_dir}'...")

    for item in content_dir.rglob("*"):
        if item.is_file() and item.suffix.lower() == ".md":
            relative_path = item.relative_to(content_dir)
            target_path = dest_dir / relative_path.with_suffix(".html")

            generate_page(item, template, target_path, basepath)

    print("Page generation complete")


def generate_page(
        from_path: str | Path, template_path: str | Path, dest_path: str | Path, basepath: str
) -> None:
    src = Path(from_path)
    template = Path(template_path)
    dest = Path(dest_path)

    if not src.exists():
        raise RuntimeError(f"Source file '{src}' does not exist")

    if not src.is_file():
        raise RuntimeError(f"Source file '{src}' is not a file")

    if not template.exists():
        raise RuntimeError(f"Template file '{template}' does not exist")

    if not template.is_file():
        raise RuntimeError(f"Template file '{template}' is not a file")

    print(f"Generating page from '{src}' to '{dest}' using '{template}'")

    markdown_content = src.read_text(encoding="utf-8")
    template_content = template.read_text(encoding="utf-8")

    html_node = markdown_to_html_node(markdown_content)

    title = extract_title(markdown_content)
    html = html_node.to_html()

    rendered_html = template_content.replace("{{ Title }}", title)
    rendered_html = rendered_html.replace("{{ Content }}", html)
    rendered_html = rendered_html.replace('href="/', f'href="{basepath}')
    rendered_html = rendered_html.replace('src="/', f'src="{basepath}')

    dest.parent.mkdir(parents=True, exist_ok=True)

    dest.write_text(rendered_html, encoding="utf-8")
    print(f"Page successfuly generated: 'dest'")


def extract_title(markdown: str) -> str:
    heading_identifier = "# "
    lines = markdown.splitlines()

    for line in lines:
        if line.startswith(heading_identifier):
            return line.lstrip(heading_identifier)

    raise RuntimeError("No heading found that can be used as title")


if __name__ == "__main__":
    main()
