# pylint: disable=missing-docstring
import logging
import os
from ssl import PROTOCOL_TLSv1_1, PROTOCOL_TLSv1_2

import pytest
from requests import exceptions

from ibm_cloud_sdk_core.base_service import BaseService
from ibm_cloud_sdk_core.authenticators import NoAuthAuthenticator
from .utils.logger_utils import setup_test_logger
from .utils.http_utils import local_server


setup_test_logger(logging.ERROR)


# The certificate files that are used in this tests are generated by this command:
# pylint: disable=line-too-long,pointless-string-statement
"""
openssl req -x509 -out test_ssl.crt -keyout test_ssl.key \
  -newkey rsa:2048 -nodes -sha256 -days 36500 \
  -subj '/CN=localhost' -extensions EXT -config <( \
   printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
"""


# Load the certificate and the key files.
cert = os.path.join(os.path.dirname(__file__), '../resources/test_ssl.crt')
key = os.path.join(os.path.dirname(__file__), '../resources/test_ssl.key')


@local_server(3333, PROTOCOL_TLSv1_1, cert, key)
def test_tls_v1_1():
    service = BaseService(service_url='https://localhost:3333', authenticator=NoAuthAuthenticator())
    prepped = service.prepare_request('GET', url='/')
    # The following request should fail, because the server will try
    # to use TLS v1.1 but that's not allowed in our client.
    with pytest.raises(Exception) as exception:
        service.send(prepped, verify=cert)
    # Errors can be differ based on the Python version.
    assert exception.type is exceptions.SSLError or exception.type is exceptions.ConnectionError


@local_server(3334, PROTOCOL_TLSv1_2, cert, key)
def test_tls_v1_2():
    service = BaseService(service_url='https://localhost:3334', authenticator=NoAuthAuthenticator())

    # First call the server with the default configuration.
    # It should fail due to the self-signed SSL cert.
    assert service.disable_ssl_verification is False
    prepped = service.prepare_request('GET', url='/')
    with pytest.raises(exceptions.SSLError, match='certificate verify failed: self-signed certificate'):
        res = service.send(prepped)

    # Next configure it to validate by using our local certificate. Should raise no exception.
    res = service.send(prepped, verify=cert)
    assert res is not None

    # Now disable the SSL verification. The request shouldn't raise any issue.
    service.set_disable_ssl_verification(True)
    assert service.disable_ssl_verification is True
    prepped = service.prepare_request('GET', url='/')
    res = service.send(prepped)
    assert res is not None

    # Lastly, try with an external URL.
    # This test case is mainly here to reproduce the regression
    # in the `requests` package that was introduced in `2.32.3`.
    # More details on the issue can be found here: https://github.com/psf/requests/issues/6730
    service = BaseService(service_url='https://cloud.ibm.com', authenticator=NoAuthAuthenticator())
    assert service.disable_ssl_verification is False

    ssl_context = service.http_adapter.poolmanager.connection_pool_kw.get("ssl_context")
    assert ssl_context is not None
    assert len(ssl_context.get_ca_certs()) > 0

    prepped = service.prepare_request('GET', url='/status')
    res = service.send(prepped)
    assert res is not None
