import logging

import pytest
from beartype.typing import Dict, List, Union
from fast_bitrix24.logger import logger
from fast_bitrix24.server_response import (
    ErrorInServerResponseException,
    ServerResponseParser,
)
from fast_bitrix24.srh import ServerRequestHandler

logger.addHandler(logging.StreamHandler())


class MockSRH(ServerRequestHandler):
    def __init__(self, response: Union[Dict, List[Dict]]):
        self.response = response if isinstance(response, list) else [response]
        self.element_no = -1

        super().__init__("https://google.com/path", False, None)

    async def single_request(self, *args, **kwargs):
        self.element_no += 1
        return self.response[self.element_no]


def test_single_success():
    from tests.real_responses.crm_lead_fields_success import response

    results = ServerResponseParser(response).extract_results()
    assert isinstance(results, dict)

    from tests.real_responses.crm_lead_list_one_page_success import response

    results = ServerResponseParser(response).extract_results()
    assert isinstance(results, list)


def test_batch_success(bx_dummy, recwarn):
    from tests.real_responses.crm_lead_list_several_pages_success import response

    bx_dummy.srh = MockSRH(response)
    results = bx_dummy.get_all("crm.lead.list")
    assert isinstance(results, list)
    print(w.message for w in recwarn.list)
    with pytest.raises(Exception):
        recwarn.pop(RuntimeWarning)


def test_batch_single_page_error(bx_dummy):
    from tests.real_responses.crm_get_batch_mix_success_and_errors import response

    bx_dummy.srh = MockSRH(response)
    with pytest.raises(ErrorInServerResponseException):
        bx_dummy.get_by_ID("crm.lead.get", [0, 1, 35943])


def test_call_single_success(bx_dummy):
    from tests.real_responses.call_single_success import response

    bx_dummy.srh = MockSRH(response)
    results = bx_dummy.call("crm.lead.get", {"ID": 35943})
    assert isinstance(results, dict)


def test_call_several_success(bx_dummy):
    from tests.real_responses.call_several_success import response

    bx_dummy.srh = MockSRH(response)
    results = bx_dummy.call("crm.lead.get", [{"ID": 35943}, {"ID": 161}, {"ID": 171}])
    assert isinstance(results, tuple)
    assert len(results) == 3
    assert isinstance(results[0], dict)


def test_call_list_empty(bx_dummy):
    from tests.real_responses.batch_list_empty import response

    bx_dummy.srh = MockSRH(response)
    results = bx_dummy.call(
        "crm.lead.list", ({"filter": {"PHONE": "+0000877578564"}, "select": ["ID"]},)
    )
    assert isinstance(results, list)
    assert len(results) == 0


def test_get_all_non_list_method(bx_dummy, recwarn):
    from tests.real_responses.user_fields import response

    bx_dummy.srh = MockSRH(response)
    results = bx_dummy.get_all("user.fields")
    assert isinstance(results, dict)
    print(w.message for w in recwarn.list)
    with pytest.raises(Exception):
        recwarn.pop(RuntimeWarning)


def test_batch_and_call_raw(bx_dummy):
    from tests.real_responses.call_batch import response

    bx_dummy.srh = MockSRH(response)
    results = bx_dummy.call_batch(
        {
            "halt": 0,
            "cmd": {
                "statuses": "crm.status.entity.items?entityId=STATUS",
                "sources": "crm.status.entity.items?entityId=SOURCE",
            },
        }
    )
    assert isinstance(results, dict)
    assert results.keys() == {"statuses", "sources"}

    bx_dummy.srh = MockSRH(response)
    results = bx_dummy.call(
        "batch",
        {
            "halt": 0,
            "cmd": {
                "statuses": "crm.status.entity.items?entityId=STATUS",
                "sources": "crm.status.entity.items?entityId=SOURCE",
            },
        },
        raw=True,
    )
    assert isinstance(results, dict)
    assert results.keys() == {"result", "time"}


def test_stagehistory(bx_dummy, recwarn):
    from tests.real_responses.stagehistory import response

    bx_dummy.srh = MockSRH(response)
    results = bx_dummy.get_all(
        "crm.stagehistory.list",
        {
            "entityTypeId": 2,
            "filter": {"STAGE_ID": "UC_KW9988"},
        },
    )

    assert isinstance(results, list)
    print(w.message for w in recwarn.list)
    with pytest.raises(Exception):
        recwarn.pop(RuntimeWarning)


def test_single_add(bx_dummy):
    from tests.real_responses.single_add import response

    bx_dummy.srh = MockSRH(response)
    results = bx_dummy.call(
        "tasks.task.add",
        {
            "fields": {
                "TITLE": "АГ",
                "DESCRIPTION": "Сложно сказать, почему потускнели светлые лики икон",
                "RESPONSIBLE_ID": 1,
                "TAGS": "скпэ22-4",
                "DEADLINE": "2022/07/30",
            }
        },
    )
    assert isinstance(results, dict)


def test_get_all_tasks(bx_dummy):
    from tests.real_responses.get_all_tasks import response

    bx_dummy.srh = MockSRH(response)
    results = bx_dummy.get_all(
        "tasks.task.list",
        {"filter": {"status": -1}, "select": ["ID", "STATUS", "STATUS_COMPLETE"]},
    )
    assert isinstance(results, list)
    assert len(results) == 1570
