# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License 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.
import os
from typing import Any
from unittest import mock

import pytest
from strictyaml import as_document

from pyiceberg.typedef import UTF8, RecursiveDict
from pyiceberg.utils.config import Config, _lowercase_dictionary_keys, merge_config

EXAMPLE_ENV = {"PYICEBERG_CATALOG__PRODUCTION__URI": "https://service.io/api"}


def test_config() -> None:
    """To check if all the file lookups go well without any mocking"""
    assert Config()


@mock.patch.dict(os.environ, EXAMPLE_ENV)
def test_from_environment_variables() -> None:
    assert Config().get_catalog_config("production") == {"uri": "https://service.io/api"}


@mock.patch.dict(os.environ, EXAMPLE_ENV)
def test_from_environment_variables_uppercase() -> None:
    assert Config().get_catalog_config("PRODUCTION") == {"uri": "https://service.io/api"}


@mock.patch.dict(
    os.environ,
    {
        "PYICEBERG_CATALOG__PRODUCTION__S3__REGION": "eu-north-1",
        "PYICEBERG_CATALOG__PRODUCTION__S3__ACCESS_KEY_ID": "username",
    },
)
def test_fix_nested_objects_from_environment_variables() -> None:
    assert Config().get_catalog_config("PRODUCTION") == {
        "s3.region": "eu-north-1",
        "s3.access-key-id": "username",
    }


@mock.patch.dict(os.environ, EXAMPLE_ENV)
@mock.patch.dict(os.environ, {"PYICEBERG_CATALOG__DEVELOPMENT__URI": "https://dev.service.io/api"})
def test_list_all_known_catalogs() -> None:
    catalogs = Config().get_known_catalogs()
    assert "production" in catalogs
    assert "development" in catalogs


def test_from_configuration_files(tmp_path_factory: pytest.TempPathFactory) -> None:
    config_path = str(tmp_path_factory.mktemp("config"))
    with open(f"{config_path}/.pyiceberg.yaml", "w", encoding=UTF8) as file:
        yaml_str = as_document({"catalog": {"production": {"uri": "https://service.io/api"}}}).as_yaml()
        file.write(yaml_str)

    os.environ["PYICEBERG_HOME"] = config_path
    assert Config().get_catalog_config("production") == {"uri": "https://service.io/api"}


def test_lowercase_dictionary_keys() -> None:
    uppercase_keys = {"UPPER": {"NESTED_UPPER": {"YES"}}}
    expected = {"upper": {"nested_upper": {"YES"}}}
    assert _lowercase_dictionary_keys(uppercase_keys) == expected  # type: ignore


def test_merge_config() -> None:
    lhs: RecursiveDict = {"common_key": "abc123"}
    rhs: RecursiveDict = {"common_key": "xyz789"}
    result = merge_config(lhs, rhs)
    assert result["common_key"] == rhs["common_key"]


def test_from_configuration_files_get_typed_value(tmp_path_factory: pytest.TempPathFactory) -> None:
    config_path = str(tmp_path_factory.mktemp("config"))
    with open(f"{config_path}/.pyiceberg.yaml", "w", encoding=UTF8) as file:
        yaml_str = as_document({"max-workers": "4", "legacy-current-snapshot-id": "True"}).as_yaml()
        file.write(yaml_str)

    os.environ["PYICEBERG_HOME"] = config_path
    with pytest.raises(ValueError):
        Config().get_bool("max-workers")

    with pytest.raises(ValueError):
        Config().get_int("legacy-current-snapshot-id")

    assert Config().get_bool("legacy-current-snapshot-id")
    assert Config().get_int("max-workers") == 4


@pytest.mark.parametrize(
    "config_setup, expected_result",
    [
        # PYICEBERG_HOME takes precedence
        (
            {
                "pyiceberg_home_content": "https://service.io/pyiceberg_home",
                "home_content": "https://service.io/user-home",
                "cwd_content": "https://service.io/cwd",
            },
            "https://service.io/pyiceberg_home",
        ),
        # Home directory (~) is checked after PYICEBERG_HOME
        (
            {
                "pyiceberg_home_content": None,
                "home_content": "https://service.io/user-home",
                "cwd_content": "https://service.io/cwd",
            },
            "https://service.io/user-home",
        ),
        # Current working directory (.) is the last fallback
        (
            {
                "pyiceberg_home_content": None,
                "home_content": None,
                "cwd_content": "https://service.io/cwd",
            },
            "https://service.io/cwd",
        ),
        # No configuration files found
        (
            {
                "pyiceberg_home_content": None,
                "home_content": None,
                "cwd_content": None,
            },
            None,
        ),
    ],
)
def test_config_lookup_order(
    monkeypatch: pytest.MonkeyPatch,
    tmp_path_factory: pytest.TempPathFactory,
    config_setup: dict[str, Any],
    expected_result: str | None,
) -> None:
    """
    Test that the configuration lookup prioritizes PYICEBERG_HOME, then home (~), then cwd.
    """

    def create_config_file(path: str, uri: str | None) -> None:
        if uri:
            config_file_path = os.path.join(path, ".pyiceberg.yaml")
            content = {"catalog": {"default": {"uri": uri}}}
            with open(config_file_path, "w", encoding="utf-8") as file:
                yaml_str = as_document(content).as_yaml()
                file.write(yaml_str)

    # Create temporary directories for PYICEBERG_HOME, home (~), and cwd
    pyiceberg_home = str(tmp_path_factory.mktemp("pyiceberg_home"))
    home_dir = str(tmp_path_factory.mktemp("home"))
    cwd_dir = str(tmp_path_factory.mktemp("cwd"))

    # Create configuration files in the respective directories
    create_config_file(pyiceberg_home, config_setup.get("pyiceberg_home_content"))
    create_config_file(home_dir, config_setup.get("home_content"))
    create_config_file(cwd_dir, config_setup.get("cwd_content"))

    # Mock environment and paths
    monkeypatch.setenv("PYICEBERG_HOME", pyiceberg_home)
    monkeypatch.setattr(os.path, "expanduser", lambda _: home_dir)
    monkeypatch.chdir(cwd_dir)

    # Perform the lookup and validate the result
    result = Config()._from_configuration_files()
    assert (
        result["catalog"]["default"]["uri"] if result else None  # type: ignore
    ) == expected_result, f"Unexpected configuration result. Expected: {expected_result}, Actual: {result}"


@pytest.mark.parametrize("content", ["", "\n", "# only a comment\n"])
def test_from_configuration_files_without_a_mapping(
    monkeypatch: pytest.MonkeyPatch, tmp_path_factory: pytest.TempPathFactory, content: str
) -> None:
    """A file that holds no mapping should be treated as absent."""
    pyiceberg_home = str(tmp_path_factory.mktemp("pyiceberg_home"))
    empty_dir = str(tmp_path_factory.mktemp("empty"))
    with open(os.path.join(pyiceberg_home, ".pyiceberg.yaml"), "w", encoding=UTF8) as file:
        file.write(content)

    monkeypatch.setenv("PYICEBERG_HOME", pyiceberg_home)
    monkeypatch.setattr(os.path, "expanduser", lambda _: empty_dir)
    monkeypatch.chdir(empty_dir)

    assert Config()._from_configuration_files() is None
