from django.http import (
    HttpResponse,
    HttpResponseServerError,
    HttpResponseNotFound,
)
from django.test import RequestFactory
from django.test.utils import override_settings

from csp.middleware import CSPMiddleware


HEADER = 'Content-Security-Policy'
mw = CSPMiddleware()
rf = RequestFactory()


def test_add_header():
    request = rf.get('/')
    response = HttpResponse()
    mw.process_response(request, response)
    assert HEADER in response


def test_exempt():
    request = rf.get('/')
    response = HttpResponse()
    response._csp_exempt = True
    mw.process_response(request, response)
    assert HEADER not in response


@override_settings(CSP_EXCLUDE_URL_PREFIXES=('/inlines-r-us'))
def text_exclude():
    request = rf.get('/inlines-r-us/foo')
    response = HttpResponse()
    mw.process_response(request, response)
    assert HEADER not in response


@override_settings(CSP_REPORT_ONLY=True)
def test_report_only():
    request = rf.get('/')
    response = HttpResponse()
    mw.process_response(request, response)
    assert HEADER not in response
    assert HEADER + '-Report-Only' in response


def test_dont_replace():
    request = rf.get('/')
    response = HttpResponse()
    response[HEADER] = 'default-src example.com'
    mw.process_response(request, response)
    assert response[HEADER] == 'default-src example.com'


def test_use_config():
    request = rf.get('/')
    response = HttpResponse()
    response._csp_config = {'default-src': ['example.com']}
    mw.process_response(request, response)
    assert response[HEADER] == 'default-src example.com'


def test_use_update():
    request = rf.get('/')
    response = HttpResponse()
    response._csp_update = {'default-src': ['example.com']}
    mw.process_response(request, response)
    assert response[HEADER] == "default-src 'self' example.com"


@override_settings(CSP_IMG_SRC=['foo.com'])
def test_use_replace():
    request = rf.get('/')
    response = HttpResponse()
    response._csp_replace = {'img-src': ['bar.com']}
    mw.process_response(request, response)
    policy_list = sorted(response[HEADER].split('; '))
    assert policy_list == ["default-src 'self'", "img-src bar.com"]


@override_settings(DEBUG=True)
def test_debug_errors_exempt():
    request = rf.get('/')
    response = HttpResponseServerError()
    mw.process_response(request, response)
    assert HEADER not in response


@override_settings(DEBUG=True)
def test_debug_notfound_exempt():
    request = rf.get('/')
    response = HttpResponseNotFound()
    mw.process_response(request, response)
    assert HEADER not in response


def test_nonce_created_when_accessed():
    request = rf.get('/')
    mw.process_request(request)
    nonce = str(request.csp_nonce)
    response = HttpResponse()
    mw.process_response(request, response)
    assert nonce in response[HEADER]


def test_no_nonce_when_not_accessed():
    request = rf.get('/')
    mw.process_request(request)
    response = HttpResponse()
    mw.process_response(request, response)
    assert 'nonce-' not in response[HEADER]


def test_nonce_regenerated_on_new_request():
    request1 = rf.get('/')
    request2 = rf.get('/')
    mw.process_request(request1)
    mw.process_request(request2)
    nonce1 = str(request1.csp_nonce)
    nonce2 = str(request2.csp_nonce)
    assert request1.csp_nonce != request2.csp_nonce

    response1 = HttpResponse()
    response2 = HttpResponse()
    mw.process_response(request1, response1)
    mw.process_response(request2, response2)
    assert nonce1 not in response2[HEADER]
    assert nonce2 not in response1[HEADER]


@override_settings(CSP_INCLUDE_NONCE_IN=[])
def test_no_nonce_when_disabled_by_settings():
    request = rf.get('/')
    mw.process_request(request)
    nonce = str(request.csp_nonce)
    response = HttpResponse()
    mw.process_response(request, response)
    assert nonce not in response[HEADER]
