#
# # 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 parameter handling and processing."""

from __future__ import annotations

from typing import Any


def extract_defaults(parameter_specs: list[dict[str, Any]]) -> dict[str, Any]:
    """Extract default values from parameter specifications.

    Args:
        parameter_specs: List of parameter spec dicts with 'name', 'required' keys

    Returns:
        Dictionary mapping parameter names to their default values
    """
    defaults = {}
    for param in parameter_specs:
        if param["required"]:
            if "defaultValue" in param:
                defaults[param["name"]] = param["defaultValue"]
            elif "properties" in param:
                nested_defaults = extract_defaults(param["properties"])
                defaults[param["name"]] = nested_defaults
    return defaults


def parse_build_and_run_parameters(parameter_specs: dict[str, list[dict[str, Any]]]) -> dict[str, dict[str, Any]]:
    """Extract default parameters for build and run configurations.

    Args:
        parameter_specs: Parameter specs with 'build' and/or 'run' keys

    Returns:
        Dictionary with build/run parameter defaults
    """
    parameters = {}
    if "build" in parameter_specs:
        parameters["build"] = extract_defaults(parameter_specs["build"])
    if "run" in parameter_specs:
        parameters["run"] = extract_defaults(parameter_specs["run"])
    return parameters


def remove_app_params_from_blocks(
    app_parameters: dict[str, dict[str, Any]],
    block_parameters: dict[str, dict[str, Any]],
) -> dict[str, dict[str, Any]]:
    """Remove block parameters that are already defined at app level.

    App-level parameters take precedence. Blocks with no remaining
    parameters after deduplication are removed from the result.

    Args:
        app_parameters: App-level build and run parameters
        block_parameters: Block parameters indexed by block name

    Returns:
        Filtered block parameters with app-level duplicates removed
    """
    result: dict[str, dict[str, Any]] = {}

    # For each block in the block parameters
    for block_name, block_param in block_parameters.items():
        result[block_name] = {}

        # Process build parameters if they exist
        if "build" in block_param:
            if "build" in app_parameters:
                # Filter out any parameters that are in app_parameters["build"]
                filtered_build_params = {
                    k: v for k, v in block_param["build"].items() if k not in app_parameters["build"]
                }

                # Only add build parameters if there are any left after filtering
                if filtered_build_params:
                    result[block_name]["build"] = filtered_build_params
            else:
                # If app has no build parameters, keep all block build parameters
                result[block_name]["build"] = block_param["build"]

        # Process run parameters if they exist
        if "run" in block_param:
            if "run" in app_parameters:
                # Filter out any parameters that are in app_parameters["run"]
                filtered_run_params = {k: v for k, v in block_param["run"].items() if k not in app_parameters["run"]}

                # Only add run parameters if there are any left after filtering
                if filtered_run_params:
                    result[block_name]["run"] = filtered_run_params
            else:
                # If app has no run parameters, keep all block run parameters
                result[block_name]["run"] = block_param["run"]

        # If the block has no parameters after filtering, remove it from result
        if not result[block_name]:
            del result[block_name]

    return result
