import json
import logging

from causalbench.commons.utils import package_module
from causalbench.modules.module import Module
from causalbench.services.requests import save_module, fetch_module


class Run(Module):

    def __init__(self, module_id: int = None):
        super().__init__(module_id, 0, None)

    def validate(self):
        # TODO: To be implemented
        pass

    def fetch(self) -> str:
        return fetch_module(self.type,
                            self.module_id,
                            self.version,
                            'runs',
                            'downloaded_run.zip')

    def save(self, state: dict, public: bool) -> bool:
        if state.context.id is None or state.context.version is None:
            logging.error(f'Cannot publish run as it is generated by an unpublished context')
            return False

        zip_file = package_module(state, self.package_path)
        self.module_id, self.version = save_module(self.type,
                                                   self.module_id,
                                                   self.version,
                                                   public,
                                                   zip_file,
                                                   'runs',
                                                   'run.zip')
        return self.module_id is not None

    def __str__(self):
        string = '=' * 80 + '\n'

        string += f'Task: {self.task}' + '\n'

        for result in self.results:
            string += '-' * 80 + '\n'

            string += f'Dataset: {result.dataset.name}' + '\n'

            string += f'Model: {result.model.name}' + '\n'
            for key, value in result.model.hyperparameters.items():
                string += f'    {key}: {value}' + '\n'

            string += 'Metrics:' + '\n'
            for metric in result.metrics:
                string += f'    {metric.name}: {metric.output["score"]}' + '\n'
                for key, value in metric.hyperparameters.items():
                    string += f'        {key}: {value}' + '\n'

        string += '=' * 80

        return string
