"""Read config parameters."""

from __future__ import annotations

import json
import os
from typing import Any

import requests
from _pytest.config import Config
from adaptavist import Adaptavist


class ATMConfiguration:
    """Configuration class to read config parameters (either from env or from "global_config.json")."""

    def __init__(self, pytest_config: Config | None = None):
        self.global_config = {}
        self.pytest_config = pytest_config.inicfg if pytest_config else {}
        config_file_name = os.path.join("config", "global_config.json")
        if os.path.exists(os.path.abspath(config_file_name)):
            with open(config_file_name, "r", encoding="utf-8") as config_file:
                try:
                    self.global_config.update(json.load(config_file))
                except Exception as ex:
                    raise ValueError(f'Failed to load config from file "{config_file}"!', ex) from ex

    def get(self, key: str, default: Any = None) -> Any:
        """
        Get value either from environment or from config file.

        The lookup is the following:

        OS environment[key]
        OS environment[KEY]
        pytest.ini[key]
        pytest.ini[KEY]
        Configuration dictionary[key]
        Configuration dictionary[cfg_key]
        """

        if key.lower().startswith("cfg_"):
            return self.global_config.get(key) or default

        values: tuple[Any, ...] = ()
        for config_storage, lookups in zip(
            [{**self.pytest_config, **os.environ}, self.global_config], [[key, key.upper()], [key, f"cfg_{key}"]]
        ):
            values += tuple(config_storage[lookup] for lookup in lookups if lookup in config_storage)
        return next(iter(values), default)

    def get_bool(self, key: str, default: Any = None) -> bool:
        """
        Get boolean value either from environment or from config file.

        We try to get boolean values from strings like "true", "1" or "yes" (or the equivalent).

        If the function won't find a match, it will raise a ValueError
        """

        result = self.get(key=key, default=default)

        if result is None or isinstance(result, (bool, int)):
            return bool(result)

        if isinstance(result, str):
            if result.lower() in ["true", "1", "yes"]:
                return True
            if result.lower() in ["false", "0", "no"]:
                return False

        raise ValueError(f"Invalid bool result: {result}")


def atm_user_is_valid(user: str) -> bool:
    """Check if user is known to Adaptavist/Jira."""
    cfg = ATMConfiguration()
    adaptavist_instance = Adaptavist(cfg.get("jira_server", ""), cfg.get("jira_username", ""),
                                     cfg.get("jira_password", ""))
    token = os.getenv("JIRA_TOKEN")
    if token:
        adaptavist_instance._session.close()
    adaptavist_instance._session.auth = None
    adaptavist_instance._session = requests.Session()
    adaptavist_instance._session.headers.update({
        'Authorization': f'Bearer {token}',
        'Accept': 'application/json',
        'Content-type': 'application/json',
    })

    return (
            user in adaptavist_instance.get_users()
    )
