from datetime import datetime as Datetime

import pytest

from delta_barth.api import common
from delta_barth.constants import HTTP_CURRENT_CONNECTION
from delta_barth.errors import (
    ApiConnectionError,
    UnknownApiErrorCode,
    UnspecifiedRequestType,
)
from delta_barth.types import HttpRequestTypes

"http://test.com/ "


@pytest.mark.parametrize(
    ["case", "expect"],
    [
        ("http://test.com/ ", "http://test.com"),
        ("http://test.com/", "http://test.com"),
        ("http://test.com ", "http://test.com"),
        ("http://test.com// ", "http://test.com"),
        ("http://test.com", "http://test.com"),
        (" /http://test.com", "http://test.com"),
        ("  //http://test.com", "http://test.com"),
        ("//http://test.com", "http://test.com"),
    ],
)
def test_strip_url_components(case, expect):
    res = common._strip_url_components(case)
    assert res == expect


@pytest.mark.parametrize(
    ["base", "route", "expect"],
    [
        ("http://test.com/ ", "ping", "http://test.com/ping"),
        ("http://test.com/", "ping  ", "http://test.com/ping"),
        ("http://test.com ", "ping/", "http://test.com/ping"),
        ("http://test.com// ", "ping", "http://test.com/ping"),
        ("http://test.com", "/ping  ", "http://test.com/ping"),
        (" /http://test.com", "/ ping/ ", "http://test.com/ping"),
        ("  //http://test.com", "ping", "http://test.com/ping"),
        ("//http://test.com", "//    ping// ", "http://test.com/ping"),
    ],
)
def test_combine_route(base, route, expect):
    res = common.combine_route(base, route)
    assert res == expect


def test_assert_login():
    with pytest.raises(ApiConnectionError):
        common._assert_login_status()


@pytest.mark.api_con_required
def test_ping(api_base_url):
    resp = common.ping(api_base_url, HttpRequestTypes.GET)
    assert resp.status_code == 204
    resp = common.ping(api_base_url, HttpRequestTypes.PUT)
    assert resp.status_code == 204
    resp = common.ping(api_base_url, HttpRequestTypes.DELETE)
    assert resp.status_code == 204

    with pytest.raises(UnspecifiedRequestType):
        resp = common.ping(api_base_url, HttpRequestTypes.POST)


@pytest.mark.api_con_required
def test_raise_unknown_error(api_base_url):
    resp = common.ping(api_base_url, HttpRequestTypes.GET)
    with pytest.raises(UnknownApiErrorCode):
        common._raise_for_unknown_error(resp)


@pytest.mark.api_con_required
def test_login_logout(credentials, api_base_url):
    assert HTTP_CURRENT_CONNECTION.session_token is None
    resp = common.login(
        base_url=api_base_url,
        user_name=credentials["user"],
        password=credentials["pwd"],
        database=credentials["db"],
        mandant=credentials["mandant"],
    )
    assert resp.error is None
    assert HTTP_CURRENT_CONNECTION.session_token is not None
    resp = common.logout(
        base_url=api_base_url,
    )
    assert resp.error is None
    assert HTTP_CURRENT_CONNECTION.session_token is None
    assert "DelecoToken" not in HTTP_CURRENT_CONNECTION.headers
    resp = common.login(
        base_url=api_base_url,
        user_name=credentials["user"],
        password="WRONG_PASSWORD",
        database=credentials["db"],
        mandant=credentials["mandant"],
    )
    assert resp.error is not None
    assert resp.error.status_code == 409
    assert resp.error.message == "Nutzer oder Passwort falsch."


# @pytest.mark.api_con_required
@pytest.mark.new
def test_get_sales_prognosis_data(credentials, api_base_url):
    resp = common.login(
        base_url=api_base_url,
        user_name=credentials["user"],
        password=credentials["pwd"],
        database=credentials["db"],
        mandant=credentials["mandant"],
    )
    # test without company ID
    assert resp.error is None
    date = Datetime(2022, 6, 1)
    resp = common.get_sales_prognosis_data(api_base_url, None, date)
    assert resp.error is None
    assert len(resp.daten) > 0
    date = Datetime(2030, 1, 1)
    resp = common.get_sales_prognosis_data(api_base_url, None, date)
    assert resp.error is None
    assert len(resp.daten) == 0
    # test with company ID
    assert resp.error is None
    date = Datetime(2022, 6, 1)
    company_id = 1024
    resp = common.get_sales_prognosis_data(api_base_url, company_id, date)
    assert resp.error is None
    assert len(resp.daten) > 0
    date = Datetime(2030, 1, 1)
    resp = common.get_sales_prognosis_data(api_base_url, company_id, date)
    assert resp.error is None
    assert len(resp.daten) == 0
    # test with non-existent company ID
    assert resp.error is None
    date = Datetime(2022, 6, 1)
    company_id = 1000024
    resp = common.get_sales_prognosis_data(api_base_url, company_id, date)
    assert resp.error is None
    assert len(resp.daten) == 0
    # close connection
    resp = common.logout(
        base_url=api_base_url,
    )
    assert resp.error is None
