import csv
from io import StringIO
import os
from django.http import HttpResponse
from django.shortcuts import render
from django.http import JsonResponse
from django.views.decorators.csrf import ensure_csrf_cookie, csrf_protect
import json
from utils.influx import InfluxDBHelper
from dotenv import load_dotenv
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth import authenticate, login, logout
from .forms import CreateUserForm

"""old functions not used by django ninja"""


@ensure_csrf_cookie
@require_http_methods(["GET"])
def set_csrf_token(request):
    """
    We set the CSRF cookie on the frontend.
    """
    return JsonResponse({"message": "CSRF cookie set"})


@require_http_methods(["POST"])
def login_view(request):
    try:
        data = json.loads(request.body.decode("utf-8"))
        email = data["email"]
        password = data["password"]
    except json.JSONDecodeError:
        return JsonResponse({"success": False, "message": "Invalid JSON"}, status=400)

    user = authenticate(request, username=email, password=password)

    if user:
        login(request, user)  # also creates a session in the browser
        return JsonResponse({"success": True})
    return JsonResponse({"success": False, "message": "Invalid credentials"}, status=401)


def logout_view(request):
    logout(request)
    return JsonResponse({"message": "Logged out"})


@require_http_methods(["GET"])
def user(request):
    if request.user.is_authenticated:
        return JsonResponse({"username": request.user.username, "email": request.user.email})
    return JsonResponse({"message": "Not logged in"}, status=401)


@require_http_methods(["POST"])
def register(request):
    data = json.loads(request.body.decode("utf-8"))
    form = CreateUserForm(data)
    if form.is_valid():
        form.save()
        return JsonResponse({"success": "User registered successfully"}, status=201)
    else:
        errors = form.errors.as_json()
        return JsonResponse({"error": errors}, status=400)


@require_http_methods(["GET"])
def room_data_range(request):
    try:
        room = request.GET.get("room")
        start = request.GET.get("start", "-30d")
        stop = request.GET.get("stop", "now()")

        if not room:
            return JsonResponse({"error": "Missing 'room' parameter"}, status=400)

        load_dotenv()
        client = InfluxDBHelper(
            url=os.getenv("INFLUXDB_URL"),
            token=os.getenv("INFLUXDB_TOKEN"),
            org=os.getenv("INFLUXDB_ORG"),
            bucket=os.getenv("INFLUXDB_BUCKET"),
        )

        tables = client.get_room_data_in_range(room, start, stop)

        data_by_time = {}

        for table in tables:
            for record in table.records:
                timestamp = str(record.get_time())
                field = record.get_field()
                value = record.get_value()

                if timestamp not in data_by_time:
                    data_by_time[timestamp] = {}
                data_by_time[timestamp][field] = value

        return JsonResponse({"room": room, "data": data_by_time}, status=200)
    except json.JSONDecodeError:
        return JsonResponse({"success": False, "message": "Invalid JSON"}, status=400)


@require_http_methods(["GET"])
def get_rooms(request):
    client = InfluxDBHelper(
        url=os.getenv("INFLUXDB_URL"),
        token=os.getenv("INFLUXDB_TOKEN"),
        org=os.getenv("INFLUXDB_ORG"),
        bucket=os.getenv("INFLUXDB_BUCKET"),
    )

    tables = client.list_rooms()
    rooms = set()
    for table in tables:
        for record in table.records:
            rooms.add(record.get_value())

    return JsonResponse({"rooms": sorted(rooms)})


@require_http_methods(["GET"])
def get_rooms_from_building(request):
    building = request.GET.get("building")

    if not building:
        return JsonResponse({"error": "Missing 'building' parameter"}, status=400)

    client = InfluxDBHelper(
        url=os.getenv("INFLUXDB_URL"),
        token=os.getenv("INFLUXDB_TOKEN"),
        org=os.getenv("INFLUXDB_ORG"),
        bucket=os.getenv("INFLUXDB_BUCKET"),
    )

    tables = client.list_rooms()
    rooms = set()

    for table in tables:
        for record in table.records:
            room = record.get_value()
            if isinstance(room, str) and room.startswith(f"{building}/"):
                rooms.add(room)

    return JsonResponse({"building": building, "rooms": sorted(rooms)})


@require_http_methods(["GET"])
def get_bau(request):
    client = InfluxDBHelper(
        url=os.getenv("INFLUXDB_URL"),
        token=os.getenv("INFLUXDB_TOKEN"),
        org=os.getenv("INFLUXDB_ORG"),
        bucket=os.getenv("INFLUXDB_BUCKET"),
    )

    tables = client.list_rooms()
    baus = set()

    for table in tables:
        for record in table.records:
            room = record.get_value()
            if isinstance(room, str) and "/" in room:
                bau = room.split("/")[0]
                baus.add(bau)

    return JsonResponse({"baus": sorted(baus)})


@require_http_methods(["GET"])
def room_data_csv_view(request):
    room = request.GET.get("room")
    start = request.GET.get("start", "-30d")
    stop = request.GET.get("stop", "now()")

    if not room:
        return JsonResponse({"error": "Missing 'room' parameter"}, status=400)

    client = InfluxDBHelper(
        url=os.getenv("INFLUXDB_URL"),
        token=os.getenv("INFLUXDB_TOKEN"),
        org=os.getenv("INFLUXDB_ORG"),
        bucket=os.getenv("INFLUXDB_BUCKET"),
    )
    csv_stream = client.get_room_data_csv(room_id=room, start=start, stop=stop)

    decoded = csv_stream.decode("utf-8")
    f = StringIO(decoded)
    reader = csv.DictReader(f)

    results = []
    for row in reader:
        # optional: nur Datenzeilen filtern
        if row.get("_field") and row.get("_value"):
            results.append(
                {
                    "time": row["_time"],
                    "field": row["_field"],
                    "value": row["_value"],
                }
            )

    return JsonResponse({"room": room, "data": results})


@require_http_methods(["GET"])
def room_data_csv_download(request):
    room = request.GET.get("room")
    start = request.GET.get("start", "-30d")
    stop = request.GET.get("stop", "now()")

    if not room:
        return JsonResponse({"error": "Missing 'room' parameter"}, status=400)

    client = InfluxDBHelper(
        url=os.getenv("INFLUXDB_URL"),
        token=os.getenv("INFLUXDB_TOKEN"),
        org=os.getenv("INFLUXDB_ORG"),
        bucket=os.getenv("INFLUXDB_BUCKET"),
    )

    csv_data = client.get_room_data_csv(room, start, stop)

    response = HttpResponse(csv_data, content_type="text/csv")
    response["Content-Disposition"] = f'attachment; filename="{room}_data.csv"'
    return response


@require_http_methods(["GET"])
def room_availability(request):
    room = request.GET.get("room")
    start = request.GET.get("start", "-30d")
    stop = request.GET.get("stop", "now()")

    if not room:
        return JsonResponse({"error": "Missing 'room' parameter"}, status=400)

    client = InfluxDBHelper(
        url=os.getenv("INFLUXDB_URL"),
        token=os.getenv("INFLUXDB_TOKEN"),
        org=os.getenv("INFLUXDB_ORG"),
        bucket=os.getenv("INFLUXDB_BUCKET"),
    )

    availability = client.has_room_sent_data(room, start, stop)

    return JsonResponse({"room": room, "available": availability}, status=200)


@require_http_methods(["GET"])
def sensor_availability(request):
    sensor_mac = request.GET.get("mac")
    start = request.GET.get("start", "-30d")
    stop = request.GET.get("stop", "now()")

    if not sensor_mac:
        return JsonResponse({"error": "Missing 'mac' parameter"}, status=400)

    client = InfluxDBHelper(
        url=os.getenv("INFLUXDB_URL"),
        token=os.getenv("INFLUXDB_TOKEN"),
        org=os.getenv("INFLUXDB_ORG"),
        bucket=os.getenv("INFLUXDB_BUCKET"),
    )

    availability = client.has_sensor_sent_data(sensor_mac, start, stop)

    return JsonResponse({"sensor_mac": sensor_mac, "available": availability}, status=200)


@require_http_methods(["GET"])
def all_rooms_availability(request):
    start = request.GET.get("start", "-30d")
    stop = request.GET.get("stop", "now()")

    client = InfluxDBHelper(
        url=os.getenv("INFLUXDB_URL"),
        token=os.getenv("INFLUXDB_TOKEN"),
        org=os.getenv("INFLUXDB_ORG"),
        bucket=os.getenv("INFLUXDB_BUCKET"),
    )

    rooms_available = client.rooms_with_available_data(start, stop)

    return JsonResponse({"available_rooms": rooms_available}, status=200)


@require_http_methods(["GET"])
def all_sensors_availability(request):
    start = request.GET.get("start", "-30d")
    stop = request.GET.get("stop", "now()")

    client = InfluxDBHelper(
        url=os.getenv("INFLUXDB_URL"),
        token=os.getenv("INFLUXDB_TOKEN"),
        org=os.getenv("INFLUXDB_ORG"),
        bucket=os.getenv("INFLUXDB_BUCKET"),
    )

    sensors_available = client.sensors_with_available_data(start, stop)

    return JsonResponse({"available_sensors": sensors_available}, status=200)
