from django.http import HttpResponseBadRequest
from django.template.response import SimpleTemplateResponse
from django.views.decorators.csrf import csrf_exempt

from debug_toolbar.decorators import require_show_toolbar
from debug_toolbar.panels.sql.forms import SQLSelectForm


@csrf_exempt
@require_show_toolbar
def sql_select(request):
    """Returns the output of the SQL SELECT statement"""
    form = SQLSelectForm(request.POST or None)

    if form.is_valid():
        sql = form.cleaned_data["raw_sql"]
        params = form.cleaned_data["params"]
        cursor = form.cursor
        cursor.execute(sql, params)
        headers = [d[0] for d in cursor.description]
        result = cursor.fetchall()
        cursor.close()
        context = {
            "result": result,
            "sql": form.reformat_sql(),
            "duration": form.cleaned_data["duration"],
            "headers": headers,
            "alias": form.cleaned_data["alias"],
        }
        # Using SimpleTemplateResponse avoids running global context processors.
        return SimpleTemplateResponse("debug_toolbar/panels/sql_select.html", context)
    return HttpResponseBadRequest("Form errors")


@csrf_exempt
@require_show_toolbar
def sql_explain(request):
    """Returns the output of the SQL EXPLAIN on the given query"""
    form = SQLSelectForm(request.POST or None)

    if form.is_valid():
        sql = form.cleaned_data["raw_sql"]
        params = form.cleaned_data["params"]
        vendor = form.connection.vendor
        cursor = form.cursor

        if vendor == "sqlite":
            # SQLite's EXPLAIN dumps the low-level opcodes generated for a query;
            # EXPLAIN QUERY PLAN dumps a more human-readable summary
            # See https://www.sqlite.org/lang_explain.html for details
            cursor.execute("EXPLAIN QUERY PLAN {}".format(sql), params)
        elif vendor == "postgresql":
            cursor.execute("EXPLAIN ANALYZE {}".format(sql), params)
        else:
            cursor.execute("EXPLAIN {}".format(sql), params)

        headers = [d[0] for d in cursor.description]
        result = cursor.fetchall()
        cursor.close()
        context = {
            "result": result,
            "sql": form.reformat_sql(),
            "duration": form.cleaned_data["duration"],
            "headers": headers,
            "alias": form.cleaned_data["alias"],
        }
        # Using SimpleTemplateResponse avoids running global context processors.
        return SimpleTemplateResponse("debug_toolbar/panels/sql_explain.html", context)
    return HttpResponseBadRequest("Form errors")


@csrf_exempt
@require_show_toolbar
def sql_profile(request):
    """Returns the output of running the SQL and getting the profiling statistics"""
    form = SQLSelectForm(request.POST or None)

    if form.is_valid():
        sql = form.cleaned_data["raw_sql"]
        params = form.cleaned_data["params"]
        cursor = form.cursor
        result = None
        headers = None
        result_error = None
        try:
            cursor.execute("SET PROFILING=1")  # Enable profiling
            cursor.execute(sql, params)  # Execute SELECT
            cursor.execute("SET PROFILING=0")  # Disable profiling
            # The Query ID should always be 1 here but I'll subselect to get
            # the last one just in case...
            cursor.execute(
                """
  SELECT  *
    FROM  information_schema.profiling
   WHERE  query_id = (
          SELECT  query_id
            FROM  information_schema.profiling
        ORDER BY  query_id DESC
           LIMIT  1
        )
"""
            )
            headers = [d[0] for d in cursor.description]
            result = cursor.fetchall()
        except Exception:
            result_error = (
                "Profiling is either not available or not supported by your database."
            )
        cursor.close()
        context = {
            "result": result,
            "result_error": result_error,
            "sql": form.reformat_sql(),
            "duration": form.cleaned_data["duration"],
            "headers": headers,
            "alias": form.cleaned_data["alias"],
        }
        # Using SimpleTemplateResponse avoids running global context processors.
        return SimpleTemplateResponse("debug_toolbar/panels/sql_profile.html", context)
    return HttpResponseBadRequest("Form errors")
