#
# # Copyright © 2026 Peak AI Limited. or its affiliates. All Rights Reserved.
# #
# # Licensed under the Apache License, Version 2.0 (the "License"). You
# # may not use this file except in compliance with the License. A copy of
# # the License is located at:
# #
# # https://github.com/PeakBI/peak-sdk/blob/main/LICENSE
# #
# # or in the "license" file accompanying this file. This file is
# # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# # ANY KIND, either express or implied. See the License for the specific
# # language governing permissions and limitations under the License.
# #
# # This file is part of the peak-sdk.
# # see (https://github.com/PeakBI/peak-sdk)
# #
# # You should have received a copy of the APACHE LICENSE, VERSION 2.0
# # along with this program. If not, see <https://apache.org/licenses/LICENSE-2.0>
#
"""Release functionality for publishing and deploying components."""

from __future__ import annotations

from pathlib import Path

from tenacity import (  # type: ignore[import-not-found]
    retry,
    retry_if_exception_type,
    stop_after_attempt,
    wait_exponential,
)

from peak.tools.logging import LogLevel, PeakLogger, get_logger

from .deploy import deploy
from .publish import publish

logger: PeakLogger = get_logger(level=LogLevel.INFO)


@retry(  # type: ignore[misc]
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=2, max=30),
    retry=retry_if_exception_type(Exception),
)
def publish_component(publish_spec_path: str, base_dir: str) -> tuple[str, str]:
    """Safely publish with retry capabilities using tenacity."""
    result = publish(publish_spec_path, base_dir)
    if isinstance(result, tuple):
        return str(result[0]), str(result[1])
    msg = "Expected tuple result from publish for app publishing"
    raise ValueError(msg)


@retry(  # type: ignore[misc]
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=2, max=30),
    retry=retry_if_exception_type(Exception),
)
def deploy_component(config_path: str, spec_id: str, version: str) -> None:
    """Safely deploy with retry capabilities using tenacity."""
    deploy(config_path=config_path, spec_id=spec_id, version=version, deploy_app=True)


def release(publish_spec_path: str, deployment_spec_path: str, base_dir: str) -> bool:
    """Publish and deploy an app or block.

    Args:
        publish_spec_path: Path to publish specification file
        deployment_spec_path: Path to deployment specification file
        base_dir: Base directory for resolving paths

    Returns:
        True if successful, False otherwise
    """
    # Make paths absolute for consistency
    publish_spec_path = str(Path(publish_spec_path).absolute())
    deployment_spec_path = str(Path(deployment_spec_path).absolute())
    base_dir = str(Path(base_dir).absolute())

    try:
        new_id, new_version = publish_component(publish_spec_path, base_dir)
        logger.debug("Component published successfully with id %s and version %s", new_id, new_version)

        # Only proceed with deployment if publish was successful and returned valid IDs
        if not new_id or not new_version:
            logger.error("Publish step did not return valid component id and version")
            return False

        deploy_component(deployment_spec_path, new_id, new_version)
        logger.debug("Component deployed successfully with id %s and version %s", new_id, new_version)

    except (ValueError, OSError, RuntimeError):
        logger.exception("Error during release process")
        return False

    return True
