import traceback
from urllib.parse import urljoin
import sys
import json

import wordpress_util
import fylr_lib_plugin_python3.util as fylr_util


def oauth1(info_json: dict):
    api_callback_token = fylr_util.get_json_value(info_json, 'api_user_access_token')
    if api_callback_token is None:
        raise Exception('callback token not set')
    response = wordpress_util.oauth1(
        query_params=fylr_util.get_json_value(info_json, 'request.query', True),
        plugin_url=urljoin(
            fylr_util.get_json_value(info_json, 'external_url', True),
            fylr_util.get_json_value(info_json, 'request.url.Path', True),
        ),
        api_callback_token=api_callback_token
    )

    wordpress_util.__tmp(['oauth1 response: {0}'.format(fylr_util.dumpjs(response))])
    return response


def transport_wp(info_json: dict):
    response = fylr_util.get_json_value(info_json, 'export')
    if response is None:
        wordpress_util.raise_error('export not set')

    # read api information
    api_callback_url = fylr_util.get_json_value(info_json, 'api_callback.url')
    if api_callback_url is None:
        raise Exception('callback url not set')
    api_callback_token = fylr_util.get_json_value(info_json, 'api_callback.token')
    if api_callback_token is None:
        raise Exception('callback token not set')

    # read from export definition
    export_def = fylr_util.get_json_value(response, 'export')
    if export_def is None:
        wordpress_util.raise_error('export definition not set')
    export_id = fylr_util.get_json_value(export_def, '_id')
    if export_id is None:
        raise Exception('export: id not set')

    # read from transport definition
    transport_def = fylr_util.get_json_value(info_json, 'transport')
    if transport_def is None:
        raise Exception('transport not set')

    transport_opts = fylr_util.get_json_value(transport_def, 'options', True)
    wp_inst_uuid = fylr_util.get_json_value(transport_opts, 'wp_inst_uuid', True)

    wp_conf = fylr_util.get_json_value(info_json, 'info.config.plugin.easydb-wordpress-plugin.config.wordpress', True)
    if wp_conf is None:
        wordpress_util.raise_error('wordpress config not found')

    wp_inst = None
    for _wp_inst in wp_conf['wp_instances']:
        auth = json.loads(_wp_inst['auth'])
        if auth['uuid'] == wp_inst_uuid:
            wp_inst = _wp_inst
            break

    if wp_inst is None:
        wordpress_util.raise_error('wordpress instance not found')

    wordpress_util.__tmp([
        '=== WP INST:',
        fylr_util.dumpjs(wp_inst),
        '=== WP INST AUTH:',
        fylr_util.dumpjs(auth),
    ])

    wp_inst_url = fylr_util.get_json_value(wp_inst, 'url', True)
    wp_media_url = wordpress_util.build_wp_media_url(wp_inst_url)
    wordpress_util.__tmp('=== WP URL: {0}'.format(wp_media_url))

    _, protocol = wordpress_util.transport_files(
        wp_media_url=wp_media_url,
        fpath='.',
        files=fylr_util.get_json_value(response, '_files', True),
        auth=auth,
        user_generated_displayname=fylr_util.get_json_value(transport_opts, 'user_generated_displayname', True),
        source_name='fylr',
        export_id=export_id,
        api_callback_url=api_callback_url,
        api_callback_token=api_callback_token,
    )
    protocol = ['Wordpress: {0}'.format(wp_inst_url)] + protocol

    response['_state'] = 'done'
    response['_transport_log'] = protocol

    return {
        'headers': {
            'Content-Type': 'application/json'
        },
        'body': response
    }


if __name__ == '__main__':
    _registered_callbacks = {
        'oauth1': oauth1,
        'transport_wp': transport_wp,
    }

    try:
        wordpress_util.__tmp(['start wordpress plugin'], newfile=True)
        if len(sys.argv) < 3:
            raise Exception('expect 2 args: [callback name] [info.json]')

        callback_name = sys.argv[1].strip()
        if not callback_name in _registered_callbacks:
            raise Exception('unknown callback name {0}. expect [{1}]'.format(
                callback_name,
                ",".join(_registered_callbacks.keys()),
            ))

        info_json = json.loads(sys.argv[2])

        wordpress_util.__tmp([
            'callback:', callback_name,
        ])

        response = _registered_callbacks[callback_name](info_json)

        body = fylr_util.get_json_value(response, 'body')
        if body is None:
            fylr_util.stdout(str(response))
            exit(0)

        content_type = fylr_util.get_json_value(response, 'headers.Content-Type')
        if content_type == 'application/json':
            # body will be dumped as json
            fylr_util.return_response(body)
        else:
            # for text/html: return body as it is
            fylr_util.stdout(str(body))
            exit(0)

    except Exception as e:
        wordpress_util.__tmp(str(e))
        wordpress_util.__tmp(traceback.format_list(traceback.extract_stack(e)))
        fylr_util.return_error_response(
            error=str(e)
        )
