# SPDX-FileCopyrightText: Red Hat, Inc.
# SPDX-License-Identifier: GPL-2.0-or-later

import os
import pprint
import tempfile

from contextlib import closing
from contextlib import contextmanager

import pytest

from ovirt_imageio._internal import util
from ovirt_imageio._internal import uhttp


@pytest.fixture(scope="session")
def uhttpserver(request):
    tmp = tempfile.NamedTemporaryFile()
    server = uhttp.Server(tmp.name, uhttp.Connection)
    util.start_thread(server.serve_forever, kwargs={"poll_interval": 0.1})
    request.addfinalizer(server.shutdown)
    request.addfinalizer(tmp.close)
    return server


def test_get(uhttpserver):
    uhttpserver.app = get
    with make_connection(uhttpserver) as con:
        con.request("GET", "/")
        resp = con.getresponse()
        log_response(resp)
        assert resp.status == 200
        assert resp.getheader("content-type") == "text/plain"
        assert resp.read() == b"it works"


def test_put(uhttpserver):
    uhttpserver.app = echo
    with make_connection(uhttpserver) as con:
        con.request("PUT", "/", body=b"it works")
        resp = con.getresponse()
        log_response(resp)
        assert resp.status == 200
        assert resp.getheader("content-type") == "text/plain"
        assert resp.read() == b"it works"


def test_file(tmpdir, uhttpserver):
    data = b"x" * 1048576
    tmp = tmpdir.join("data")
    tmp.write(data)
    uhttpserver.app = sendfile
    with make_connection(uhttpserver) as con:
        con.request("GET", str(tmp))
        resp = con.getresponse()
        log_response(resp)
        assert resp.status == 200
        assert resp.getheader("content-type") == "text/plain"
        content_length = int(resp.getheader("content-length"))
        assert content_length == os.path.getsize(str(tmp))
        assert resp.read(content_length) == data


def test_connection_set_tunnel(uhttpserver):
    with make_connection(uhttpserver) as con:
        with pytest.raises(uhttp.UnsupportedError):
            con.set_tunnel("127.0.0.1")


@pytest.mark.skipif(os.geteuid() == 0,
                    reason="Not compatible when running with root")
def test_server_bind_error(tmpdir):
    # Make server_bind fail with EPERM
    tmpdir.chmod(0o600)
    try:
        sock = str(tmpdir.join('sock'))
        with pytest.raises(OSError):
            uhttp.Server(sock, uhttp.Connection)
    finally:
        tmpdir.chmod(0o755)


def get(req, resp):
    body = b"it works"
    resp.headers["content-length"] = len(body)
    resp.headers["content-type"] = "text/plain"
    resp.write(body)


def echo(req, resp):
    body = req.read()
    resp.headers["content-length"] = len(body)
    resp.headers["content-type"] = "text/plain"
    resp.write(body)


def sendfile(req, resp):
    path = req.path
    resp.headers["content-length"] = os.path.getsize(path)
    resp.headers["content-type"] = "text/plain"
    with open(path, "rb") as f:
        resp.write(f.read())


def log_response(resp):
    pprint.pprint((resp.status, resp.reason, resp.getheaders()))


@contextmanager
def make_connection(server):
    con = uhttp.UnixHTTPConnection(server.server_address, timeout=2)
    with closing(con):
        yield con
