#
# # 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>
#
"""Environment utilities for publish operations."""

from __future__ import annotations

import json
import os
from os import environ
from pathlib import Path
from typing import Any

import yaml

VALID_SCOPES = {"public", "private", "shared"}


def check_env(scope: str) -> None:
    """Validate environment configuration."""
    required_envs = ["GITHUB_TOKEN", "PEAK_AUTH_TOKEN"]
    missing = [env for env in required_envs if env not in environ]
    if missing:
        msg = f"Missing required environment variables: {', '.join(missing)}"
        raise ValueError(msg)

    if scope not in VALID_SCOPES:
        msg = f"Invalid scope: {scope}. Valid options: {', '.join(VALID_SCOPES)}"
        raise ValueError(msg)

    if scope == "shared":
        tenants = [t.strip() for t in environ.get("SHARE_TO_TENANTS", "").split(",") if t.strip()]
        if not tenants:
            msg = "SHARE_TO_TENANTS required for shared scope"
            raise ValueError(msg)


def resolve_env_vars(params: dict[str, Any]) -> dict[str, Any]:
    """Replace env: prefixed values with actual environment variables."""
    return {k: os.getenv(v[4:]) if isinstance(v, str) and v.startswith("env:") else v for k, v in params.items()}


def to_bool(value: Any) -> bool:
    """Convert a value to boolean, handling string representations."""
    if isinstance(value, bool):
        return value
    if isinstance(value, str):
        return value.lower() in ("true", "1", "yes", "on")
    return bool(value)


def get_base_params() -> dict[str, Any]:
    """Build base parameters for spec deployment from environment variables."""
    return resolve_env_vars(
        {
            "SCOPE": environ.get("SCOPE", "private"),
            "RELEASE_NOTES": environ.get("RELEASE_NOTES", ""),
            "SUFFIX": environ.get("SUFFIX"),
            "SPEC_SUFFIX": environ.get("SPEC_SUFFIX"),
            "SHARE_TO_TENANTS": environ.get("SHARE_TO_TENANTS", "").split(","),
            "TARGET_ENV": environ.get("TARGET_ENV", "dev"),
            "TENANT": environ.get("TENANT", ""),
            "TENANT_ID": environ.get("TENANT_ID", ""),
            "STAGE": environ.get("STAGE", ""),
            "PEAK_AUTH_TOKEN": environ.get("PEAK_AUTH_TOKEN", ""),
            "GITHUB_TOKEN": environ.get("GITHUB_TOKEN", ""),
            "SLACK_URL": environ.get("SLACK_URL", ""),
            "TRIGGER_WORKFLOWS": environ.get("TRIGGER_WORKFLOWS", ""),
            "INPUT_SCHEMA": environ.get("INPUT_SCHEMA", ""),
            "TARGET_SCHEMA": environ.get("TARGET_SCHEMA", ""),
        },
    )


def load_external_params(block_name: str) -> dict[str, Any]:
    """Load parameters from environment variables and external files."""
    params: dict[str, Any] = {}

    env_prefix = f"BLOCK_{block_name.upper()}_"
    for key, value in environ.items():
        if key.startswith(env_prefix):
            param_name = key[len(env_prefix) :].lower()
            try:
                params[param_name] = json.loads(value)
            except json.JSONDecodeError:
                params[param_name] = value

    param_file = Path(f"params/{block_name}.yaml")
    if param_file.exists():
        with param_file.open() as f:
            params.update(yaml.safe_load(f))

    return params


def resolve_path(path: str, base_dir: Path | None) -> str:
    """Resolve a path relative to a base directory."""
    return str((base_dir / path).resolve()) if base_dir else path
