# type: ignore
# TODO: Remove this file and function
import sys
import click
from docker.errors import ImageNotFound  # type: ignore

from biolib import utils, cli_utils
from biolib.app.utils import run_job
from biolib.biolib_binary_format import ModuleInput
from biolib.biolib_docker_client import BiolibDockerClient
from biolib.biolib_logging import logger, logger_no_user_data
from biolib.biolib_api_client import CreatedJobDict
from biolib.cli_utils import BiolibValidationError
from biolib.typing_utils import Tuple
from biolib.validators.validate_zip_file import validate_zip_file  # type: ignore


@click.command(
    context_settings=dict(ignore_unknown_options=True, allow_interspersed_args=False),
    help='Run an application from a local directory',
    hidden=True,
)
@click.argument('path', required=True)
@click.argument('args', nargs=-1, type=click.UNPROCESSED)
def run_dev(path: str, args: Tuple[str]) -> None:
    app_path = cli_utils.validate_and_get_app_path(path)
    logger.info(f'Running BioLib application in local directory {app_path}...')
    tmp_directory, source_files_zip_path = cli_utils.create_temporary_directory_with_source_files_zip(app_path)

    try:
        validate_zip_file(source_files_zip_path, app_path)
        yaml_data = cli_utils.get_yaml_data(app_path)
        cli_utils.validate_yaml_config(yaml_data, source_files_zip_path)
        app_version_mocked = cli_utils.get_mocked_app_version_from_yaml(yaml_data, source_files_zip_path)

        for module in app_version_mocked['modules']:
            try:
                BiolibDockerClient.get_docker_client().images.get(module['image_uri'])
            except ImageNotFound:
                raise Exception(
                    f"Could not find local docker image {module['image_uri']} specified in .biolib/config.yml"
                ) from None

        args = cli_utils.validate_and_get_args(list(args))
        files_dict, args = cli_utils.get_files_dict_and_file_args(files=None, args=args)

        def _get_stdin():
            stdin = None
            if not sys.stdin.isatty() and not utils.IS_DEV:
                stdin = sys.stdin.read()
            return stdin

        module_input_serialized = ModuleInput().serialize(
            stdin=_get_stdin() or b'',
            files=files_dict,
            arguments=args,
        )

        module_output = run_job(
            module_input_serialized=module_input_serialized,
            job=CreatedJobDict(
                app_version=app_version_mocked,
                arguments_override_command=False,
                auth_token='',
                caller_job=None,
                created_at='',
                federated_job_uuid=None,
                public_id=utils.RUN_DEV_JOB_ID,
                remote_hosts_with_warning=[],
                state='in_progress',
                user_id=None,
            ),
            force_local=True,
        )

        cli_utils.write_output_files(module_output['files'])  # type: ignore

        print(cli_utils.get_pretty_print_module_output_string(
            exitcode=module_output['exit_code'],  # type: ignore
            stderr=module_output['stderr'],  # type: ignore
            stdout=module_output['stdout'],  # type: ignore
        ))

    except Exception as exception:
        # Exit on BiolibValidationError as we have already printed the validation errors
        if isinstance(exception, BiolibValidationError):
            logger_no_user_data.error('Validation check failed for config file at .biolib/config.yml')
            exit(1)
        raise exception

    finally:
        try:
            tmp_directory.cleanup()
        except IOError:
            logger_no_user_data.error('Failed to clean up temporary source files zip directory')
