# pylint: disable=no-self-use
from flask import request
from flask_restplus import Namespace, Resource, inputs, abort
from flask_restplus.reqparse import RequestParser
from spectacular import FailedToValidate

from airflow import settings
from shu.interactions import Interactions, InteractionError
from shu.wrappers import DagRunWrapper
from shu.adapters import create_adapters

dags = Namespace("dags")

# Explanation of priorities (#A, #B, #C)
#  #A: Needs to be in prototype
#  #B: Needs to be in when deploying to production
#  #C: Better behaviour, but at this stage non-essential

# IMPR: [#C] Ensure the DAG model also appears in the API documentation,
#            Add something like, marshall_with to DagCollection.get
# DONE: [#B] Better responses on failure
#            Check generic error handler, make handler for PersistenceHandler


class Parser:
    @staticmethod
    def get_dag_collection():
        parser = RequestParser()
        parser.add_argument("prefix", type=str, required=False)
        parser.add_argument("is_active", type=inputs.boolean)
        return parser

    @staticmethod
    def get_dag_run_collection():
        parser = RequestParser()
        parser.add_argument("prefix", type=str, required=False)
        parser.add_argument("state", type=str, required=False)
        return parser


def interactions():
    adapters = create_adapters(settings.Session())
    return Interactions(adapters)


@dags.route("")
class DagCollection(Resource):
    @dags.expect(Parser.get_dag_collection())
    def get(self):
        """List DAGs"""
        try:
            arguments = Parser.get_dag_collection().parse_args()
            return interactions().find_dags(arguments).to_dict()
        except (InteractionError, FailedToValidate) as exc:
            abort(400, error=exc.to_dict())


@dags.route("/<string:dag_id>/runs")
class DagRunCollection(Resource):
    @dags.expect(dags.schema_model("DagRun", DagRunWrapper.schema(ignored=["dag_id"])))
    def post(self, dag_id):
        try:
            return interactions().create_dag_run(dag_id, request.json).to_dict()
        except (InteractionError, FailedToValidate) as exc:
            abort(400, error=exc.to_dict())

    @dags.expect(Parser.get_dag_run_collection())
    def get(self, dag_id):
        """List DAG runs"""
        try:
            return interactions().find_dag_run(dag_id, request.args).to_dict()
        except (InteractionError, FailedToValidate) as exc:
            abort(400, error=exc.to_dict())
