import hashlib
from copy import deepcopy
from pathlib import Path
from typing import Union

import rapidjson


def get_strategy_run_id(strategy) -> str:
    """
    Generate unique identification hash for a backtest run. Identical config and strategy file will
    always return an identical hash.
    :param strategy: strategy object.
    :return: hex string id.
    """
    digest = hashlib.sha1()
    config = deepcopy(strategy.config)

    # Options that have no impact on results of individual backtest.
    not_important_keys = ('strategy_list', 'original_config', 'telegram', 'api_server')
    for k in not_important_keys:
        if k in config:
            del config[k]

    # Explicitly allow NaN values (e.g. max_open_trades).
    # as it does not matter for getting the hash.
    digest.update(rapidjson.dumps(config, default=str,
                                  number_mode=rapidjson.NM_NAN).encode('utf-8'))
    # Include _ft_params_from_file - so changing parameter files cause cache eviction
    digest.update(rapidjson.dumps(
        strategy._ft_params_from_file, default=str, number_mode=rapidjson.NM_NAN).encode('utf-8'))
    with open(strategy.__file__, 'rb') as fp:
        digest.update(fp.read())
    return digest.hexdigest().lower()


def get_backtest_metadata_filename(filename: Union[Path, str]) -> Path:
    """Return metadata filename for specified backtest results file."""
    filename = Path(filename)
    return filename.parent / Path(f'{filename.stem}.meta{filename.suffix}')
