import json
import ntpath
import os

import parallels.core
from parallels.core import get_logger, safe_format, is_run_on_windows
from parallels.core.reports.model.issue import Issue
from parallels.core.utils.clean_logging import clean_dict_args_for_log
from parallels.core.utils.file_utils import get_relative_path
from parallels.core.utils.migrator_utils import get_package_extras_file_path
from parallels.core.utils.safe_structures import safe_get_list
from parallels.plesk.source.web import messages
from parallels.plesk.source.web.utils.site_migration_exception import SiteMigrationError

logger = get_logger(__name__)


def create_config(global_context, folder):
    """Create configuration file for web streaming downloader script to transfer specified folder, return as string.

    :type global_context: parallels.plesk.source.web.global_context.WebGlobalMigrationContext
    :type folder: parallels.plesk.source.web.migrated_folder.MigratedFolder
    :rtype: str | unicode
    """
    source = global_context.conn.get_source()

    excludes = [
        get_relative_path(
            exclude, folder.source_path,
            is_windows=False, sub_path_is_windows=False, base_path_is_windows=False
        )
        for exclude in folder.path_excludes
    ]

    config = dict(
        password=source.web_rpc_agent.password,
        stream_url=source.web_rpc_agent.url + '?task=download_dir',
        local_path=folder.target_path,
        remote_path=folder.source_absolute_path,
        exclude=excludes,
        insecure=not source.web_rpc_agent.verify_certificates,
        cacert=_get_ca_cert_bundle_path(global_context)
    )
    config_json = json.dumps(config, indent=4)

    config_json_for_log = json.dumps(clean_dict_args_for_log(config), indent=4)
    logger.fdebug(messages.WEB_STREAMING_CONFIG, config=config_json_for_log)

    return config_json


def parse_output(stdout, stderr):
    """
    :type stdout: str | unicode
    :type stderr: str | unicode
    :raises: parallels.plesk.source.web.utils.site_migration_exception.SiteMigrationError
    :rtype: list[parallels.core.reports.model.issue.Issue] | None
    """
    issues = []

    try:
        web_stream_downloader_stdout = json.loads(stdout)
    except Exception as e:
        logger.exception()
        raise SiteMigrationError(
            messages.WEB_STREAM_DOWNLOADER_INVALID_OUTPUT,
            details=safe_format(
                messages.WEB_STREAM_DOWNLOADER_INVALID_OUTPUT_DETAILS,
                exception=e, stdout=stdout, stderr=stderr
            )
        )

    for web_stream_downloader_issue in safe_get_list(web_stream_downloader_stdout, 'issues'):
        issues.append(Issue(
            'web-stream-downloader-issues', Issue.SEVERITY_ERROR,
            problem_text=web_stream_downloader_issue.get('problem_text'),
            details_text=web_stream_downloader_issue.get('details_text')
        ))

    return issues


def _get_ca_cert_bundle_path(global_context):
    """
    :type global_context: parallels.plesk.source.web.global_context.WebGlobalMigrationContext
    :rtype: str | unicode
    """
    if is_run_on_windows():
        return ntpath.join(
            global_context.conn.target.plesk_server.plesk_dir,
            'Additional', 'modules', 'panel-migrator', 'cacert', 'cacert.pem'
        )
    else:
        return get_package_extras_file_path(parallels.core, os.path.join("cacert", "cacert.pem"))
