import logging
import yaml

from flask import request, jsonify, Blueprint, current_app
from flask_swagger import swagger
from werkzeug.exceptions import BadRequest

from yandextank.config_converter.converter import ConversionError, convert_ini
from .validate import get_validation_result, response


bp = Blueprint('validate', __name__, url_prefix='/')


@bp.route('/ping')
def ping():
    """
    Returns pong to test service availability
    ---
    responses:
        200:
          description: OK
    """
    return 'pong'


@bp.route('/swagger.json')
def spec():

    swag = swagger(current_app)
    swag['info']['version'] = "0.4.0"
    swag['info']['title'] = "Validator"
    swag['basePath'] = '/'
    swag['schemes'] = ['https']

    return jsonify(swag), 200, {
        'Access-Control-Allow-Credentials': True,
        'Access-Control-Allow-Headers': 'Content-Type',
        'Access-Control-Allow-Methods': 'GET, POST',
        'Access-Control-Allow-Origin': 'https://swagger-ui.yandex-team.ru'
    }


@bp.route('/config/validate', methods=['POST'])
def validate_config():
    """
    Returns list of validation errors, and config with enabled defaults
    ---
    consumes:
      - multipart/form-data
    parameters:
      - name: config
        in: formData
        type: file
        required: true
      - name: fmt
        in: query
        required: true
        type: string
        enum:
          - ini
          - yaml
    responses:
      '200':
        description: validation info
        schema:
          type: object
          properties:
            config:
              type: object
              description: resulting config (accounting local tank configuration)
            errors:
              type: array
              items:
                type: object
    """
    try:
        fmt = request.args.get('fmt')
        config = request.files.get('config')
    except Exception as e:
        logging.error('Exception in request data', exc_info=True)
        raise BadRequest('{}'.format(e))

    if fmt == 'ini':
        try:
            validated_config = get_validation_result(convert_ini(config))
            return jsonify(validated_config)
        except ConversionError as e:
            return response({}, [e.message])
        except Exception as e:
            logging.error('Exception during reading Tank config', exc_info=True)
            raise BadRequest('{}'.format(e))
    else:
        try:
            validated_config = get_validation_result(yaml.safe_load(config))
            return jsonify(validated_config)
        except Exception as e:
            logging.error('Exception during reading Tank config', exc_info=True)
            raise BadRequest('{}'.format(e))


@bp.route('/config/validate.json', methods=['POST'])
def validate_config_json():
    """
    Returns list of validation errors, and config with enabled defaults
    ---
    parameters:
      - name: config
        in: body
        required: true
        schema:
          type: object
    consumes:
      - application/json
    responses:
      '200':
        description: validation info
        schema:
          type: object
          properties:
            config:
              type: object
              description: resulting config (accounting local tank configuration)
            errors:
              type: array
              items:
                type: object
    """

    try:
        config = request.get_json()
        validated_config = get_validation_result(config)
        return jsonify(validated_config)
    except Exception as e:
        logging.error('Exception during reading Tank config', exc_info=True)
        raise BadRequest('{}'.format(e))
