# # SPDX-FileCopyrightText: 2025 Maxime Letellier <maxime.eliot.letellier@gmail.com>
#
# # SPDX-License-Identifier: GPL-3.0-or-later

from typing import Optional
from pathlib import Path
from logging import getLogger

from tomlkit import TOMLDocument, comment, nl
from tomlkit.toml_file import TOMLFile

from ..toml_utils import get_comments

logger = getLogger(__file__)

BLENDER_MANIFEST_FILENAME = "blender_manifest.toml"


_HEADLINE_CREATED = "This file was autogenerated by peeler"
_HEADLINE_UPDATED = "This file was updated by peeler"


def _add_headlines(document: TOMLDocument, is_update: bool) -> None:
    comments = get_comments(document)

    if any(_HEADLINE_CREATED in comment_ for comment_ in comments) or any(
        _HEADLINE_UPDATED in comment_ for comment_ in comments
    ):
        return
    if is_update:
        comment_ = _HEADLINE_UPDATED
    else:
        comment_ = _HEADLINE_CREATED

    document.body.insert(0, (None, comment(comment_)))
    document.body.insert(1, (None, nl()))


def _write(document: TOMLDocument, path: Path, /, overwrite: bool = True) -> None:
    if not path.exists():
        _add_headlines(document, is_update=False)
        TOMLFile(path).write(document)
        return

    existing_file = TOMLFile(path)

    if overwrite:
        existing_document = existing_file.read()
        existing_document.update(document)
        document = existing_document
    else:
        document.update(existing_file.read())

    _add_headlines(document, is_update=True)

    existing_file.write(document)


def _retrieve_valid_path(path: Path | None, /, allow_non_default_name: bool) -> Path:
    """Return a complete path of the blender_manifest.toml to be created.

    :param path: the original path given by the user
    :param allow_non_default_name: whether to allow to export to a file named other than `blender_manifest.toml`, defaults to False
    :raises ValueError: if allow_non_default_name is False and the given path is not named `blender_manifest.toml`
    :return: The valid path

    >>> _retrieve_valid_path(None, allow_non_default_name=False)
    Path("/path/to/cwd/blender_manifest.toml")
    >>> _retrieve_valid_path(Path("/path/to/dir/"), allow_non_default_name=False)
    Path("/path/to/dir/blender_manifest.toml")
    >>> _retrieve_valid_path(
    ...     Path("/path/to/manifest/blender_manifest.toml"),
    ...     allow_non_default_name=False,
    ... )
    Path("/path/to/manifest/blender_manifest.toml")
    >>> _retrieve_valid_path(
    ...     Path("/path/to/manifest/maya_manifest.toml"), allow_non_default_name=True
    ... )
    Path("/path/to/manifest/maya_manifest.toml")
    >>> _retrieve_valid_path(
    ...     Path("/path/to/manifest/maya_manifest.toml"), allow_non_default_name=False
    ... )
    ValueError: the blender manifest should be named : `blender_manifest.toml` not `maya_manifest.toml`
    """

    if path is None:
        path = Path.cwd()

    if not path.exists():
        if path.suffix:
            path.parent.mkdir(parents=True, exist_ok=True)
        else:
            path.mkdir(exist_ok=True, parents=True)

    if path.is_dir():
        path = path / BLENDER_MANIFEST_FILENAME
    elif not path.name == BLENDER_MANIFEST_FILENAME:
        msg = f"the blender manifest should be named : `{BLENDER_MANIFEST_FILENAME}` not `{path.name}`"
        if allow_non_default_name:
            logger.warning(msg)
        else:
            raise ValueError(msg)

    return path


def export_to_blender_manifest(
    document: TOMLDocument,
    path: Optional[Path] = None,
    /,
    overwrite: bool = True,
    allow_non_default_name: bool = False,
) -> Path:
    """Export the given document to the given path.

    :param document: the toml document representing a blender_manifest.toml
    :param path: the path, file or directory, defaults to current working directory
    :param overwrite: whether to overwrite values already existing in a file at the given path, defaults to True
    :param allow_non_default_name: whether to allow to export to a file named other than `blender_manifest.toml`, defaults to False
    :return: The path of file updated or created
    """

    path = _retrieve_valid_path(path, allow_non_default_name=allow_non_default_name)

    _write(document, path, overwrite=overwrite)

    return path
