from flask import (abort, current_app, flash, make_response, redirect, request,
                   render_template, url_for, send_from_directory)
from flask_login import current_user, login_required
from . import bp
from . import tasks
from .forms import (AddQueryResultForm, DisplayOptionsForm,
                    InspectDisplayOptionsForm)
from .. import db
from ..models import QueryResult
import json
import os


@bp.route('/result/add', methods=['GET', 'POST'])
@login_required
def add_query_result():
    '''
    View to import a result as a json file.
    '''
    abort(503)
    form = AddQueryResultForm(prefix='add-query-result-form')
    if form.is_submitted():
        if not form.validate():
            return make_response(form.errors, 400)
        query_result = QueryResult(user=current_user,
                                   description=form.description.data,
                                   filename=form.file.data.filename,
                                   title=form.title.data)
        db.session.add(query_result)
        db.session.flush()
        db.session.refresh(query_result)
        try:
            os.makedirs(os.path.dirname(query_result.path))
        except OSError:
            current_app.logger.error(
                f'Make dir {query_result.path} led to an OSError!')
            db.session.rollback()
            flash('Internal Server Error', 'error')
            return make_response(
                {'redirect_url': url_for('.add_query_result')}, 500)
        # save the uploaded file
        form.file.data.save(query_result.path)
        # parse json from file
        with open(query_result.path, 'r') as file:
            query_result_file_content = json.load(file)
        # parse json schema
        # with open('app/static/json_schema/nopaque_cqi_py_results_schema.json', 'r') as file:  # noqa
        #     schema = json.load(file)
        # try:
        #     # validate imported json file
        #     validate(instance=query_result_file_content, schema=schema)
        # except Exception:
        #     tasks.delete_query_result(query_result.id)
        #     flash('Uploaded file is invalid', 'result')
        #     return make_response(
        #         {'redirect_url': url_for('.add_query_result')}, 201)
        query_result_file_content.pop('matches')
        query_result_file_content.pop('cpos_lookup')
        query_result.query_metadata = query_result_file_content
        db.session.commit()
        flash('Query result added', 'result')
        return make_response({'redirect_url': url_for('.query_result', query_result_id=query_result.id)}, 201)  # noqa
    return render_template('corpora/query_results/add_query_result.html.j2',
                           form=form, title='Add query result')


@bp.route('/result/<hashid:query_result_id>')
@login_required
def query_result(query_result_id):
    abort(503)
    query_result = QueryResult.query.get_or_404(query_result_id)
    if not (query_result.user == current_user
            or current_user.is_administrator()):
        abort(403)
    return render_template('corpora/query_results/query_result.html.j2',
                           query_result=query_result, title='Query result')


@bp.route('/result/<hashid:query_result_id>/inspect')
@login_required
def inspect_query_result(query_result_id):
    '''
    View to inspect imported result file in a corpus analysis like interface
    '''
    abort(503)
    query_result = QueryResult.query.get_or_404(query_result_id)
    query_metadata = query_result.query_metadata
    if not (query_result.user == current_user
            or current_user.is_administrator()):
        abort(403)
    display_options_form = DisplayOptionsForm(
        prefix='display-options-form',
        results_per_page=request.args.get('results_per_page', 30),
        result_context=request.args.get('context', 20)
    )
    inspect_display_options_form = InspectDisplayOptionsForm(
        prefix='inspect-display-options-form'
    )
    with open(query_result.path, 'r') as query_result_file:
        query_result_file_content = json.load(query_result_file)
    return render_template(
        'corpora/query_results/inspect.html.j2',
        query_result=query_result,
        display_options_form=display_options_form,
        inspect_display_options_form=inspect_display_options_form,  # noqa
        query_result_file_content=query_result_file_content,
        query_metadata=query_metadata,
        title='Inspect query result'
   )


@bp.route('/result/<hashid:query_result_id>/delete')
@login_required
def delete_query_result(query_result_id):
    abort(503)
    query_result = QueryResult.query.get_or_404(query_result_id)
    if not (query_result.user == current_user
            or current_user.is_administrator()):
        abort(403)
    flash(f'Query result "{query_result}" marked for deletion', 'result')
    tasks.delete_query_result(query_result_id)
    return redirect(url_for('services.service', service="corpus_analysis"))


@bp.route('/result/<hashid:query_result_id>/download')
@login_required
def download_query_result(query_result_id):
    abort(503)
    query_result = QueryResult.query.get_or_404(query_result_id)
    if not (query_result.user == current_user
            or current_user.is_administrator()):
        abort(403)
    return send_from_directory(as_attachment=True,
                               directory=os.path.dirname(query_result.path),
                               filename=query_result.filename)
