#
# # 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>
#
"""Utility functions for plugin handling."""

from __future__ import annotations

from pathlib import Path
from typing import Any

from peak.press.wrappers.deploy.utils.s3_utils import upload_plugin_to_s3
from peak.tools.logging import LogLevel, PeakLogger, get_logger

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


def get_full_plugin_file_path(plugin_path: str) -> str:
    """Resolve the full file path for a plugin.

    Args:
        plugin_path: Relative path to the plugin, possibly prefixed with "local://"

    Returns:
        Absolute path to the plugin file

    Raises:
        FileNotFoundError: If plugin file cannot be found
    """
    # First try relative to the main script directory
    full_path = Path(__file__).parent.parent / plugin_path.replace("local://", "")
    if full_path.exists():
        return str(full_path)
    # Try relative to the current working directory
    full_path_from_cwd = Path.cwd() / plugin_path.replace("local://", "")
    if full_path_from_cwd.exists():
        return str(full_path_from_cwd)
    error_msg = f"Plugin file not found at {full_path} or {full_path_from_cwd}"
    logger.error(error_msg)
    raise FileNotFoundError(error_msg)


def process_plugins(
    plugins: list[dict[str, str]],
    app_name: str,
) -> list[dict[str, str]]:
    """Upload plugins to S3 and return updated paths.

    Args:
        plugins: List of plugin dicts with "PLUGIN_PATH" keys
        app_name: Application name for S3 path construction

    Returns:
        Plugin dicts with "PLUGIN_PATH" updated to S3 URIs
    """
    processed_plugins = []
    for plugin in plugins:
        plugin_path = plugin["PLUGIN_PATH"]
        # Resolve local path and upload to S3
        local_path = get_full_plugin_file_path(plugin_path)
        s3_path = upload_plugin_to_s3(local_path, app_name)
        processed_plugins.append({"PLUGIN_PATH": s3_path})

    return processed_plugins


def process_plugin_paths(deployment_config: dict[str, Any], final_body: dict[str, Any]) -> None:  # noqa: C901
    """Process and update plugin paths in the deployment configuration.

    Args:
        deployment_config: The deployment configuration dictionary
        final_body: Deployment body to update with processed plugin paths (modified in place)
    """
    # Process app-level PYTHON_PLUGINS (only if appParameters exists)
    app_params = deployment_config.get("appParameters", {})
    if "PYTHON_PLUGINS" in app_params.get("run", {}):
        # Ensure appParameters exists in final_body for app deployments
        if "appParameters" not in final_body:
            final_body["appParameters"] = {"run": {}}
        elif "run" not in final_body["appParameters"]:
            final_body["appParameters"]["run"] = {}

        final_body["appParameters"]["run"]["PYTHON_PLUGINS"] = process_plugins(
            app_params["run"]["PYTHON_PLUGINS"],
            deployment_config["metadata"]["name"],
        )

    # Process block-level PYTHON_PLUGINS
    for block_name, block_params in final_body["parameters"].items():
        run_params = block_params.get("run", {})
        if "PYTHON_PLUGINS" in run_params:
            run_params["PYTHON_PLUGINS"] = process_plugins(
                run_params["PYTHON_PLUGINS"],
                deployment_config["metadata"]["name"],
            )
            final_body["parameters"][block_name]["run"] = run_params

    # Process app-level DBT_PLUGINS (only if appParameters exists)
    if "DBT_PLUGINS" in app_params.get("run", {}):
        # Ensure appParameters exists in final_body for app deployments
        if "appParameters" not in final_body:
            final_body["appParameters"] = {"run": {}}
        elif "run" not in final_body["appParameters"]:
            final_body["appParameters"]["run"] = {}

        final_body["appParameters"]["run"]["DBT_PLUGINS"] = process_plugins(
            app_params["run"]["DBT_PLUGINS"],
            deployment_config["metadata"]["name"],
        )

    # Process block-level DBT_PLUGINS
    for block_name, block_params in final_body["parameters"].items():
        run_params = block_params.get("run", {})
        if "DBT_PLUGINS" in run_params:
            run_params["DBT_PLUGINS"] = process_plugins(
                run_params["DBT_PLUGINS"],
                deployment_config["metadata"]["name"],
            )
            final_body["parameters"][block_name]["run"] = run_params
