import re

from django.conf import settings
from django.core.exceptions import SuspiciousOperation
from django.http import HttpResponse
from django.shortcuts import redirect


def hosts_pattern():
    hosts = []
    for host in settings.ALLOWED_HOSTS:
        if host == "*":
            return ".*"

        if host.startswith("."):
            host = host.removeprefix(".")
            hosts.append(f"(?:.+\.)?{re.escape(host)}")

        hosts.append(re.escape(host))

    if hosts == []:
        hosts = ["(?:.+\.)?localhost(?::\d+)?", "127.0.0.1(?::\d+)?", "[::1](?::\d+)?"]

    return "|".join(hosts)


match_next_url = re.compile(f"^http(s?)://(?:{hosts_pattern()})(?:/|$)", re.IGNORECASE)


def remote_ip(request):
    if "x-forwarded-for" in request.headers:
        remote_addr = request.headers["x-forwarded-for"].split(",")[0]
    else:
        remote_addr = request.META["REMOTE_ADDR"]

    q = request.GET.copy()
    q.appendlist("addr", remote_addr)

    if "next" in q:
        next = q.pop("next")
        if len(next) > 1:
            q.setlist("next", next[1:])
        next = next[0]

        if (m := match_next_url.match(next)) is None or m[1] != {False: "", True: "s"}[
            request.is_secure()
        ]:
            raise SuspiciousOperation(f"invalid redirect url {next}")

        return redirect(next + f"?{q.urlencode()}")

    return HttpResponse(",".join(q.getlist("addr")), "text/plain")
