import os

from unittest import mock
import pytest
from django.urls import reverse
from rest_framework import status

from devices.enums import ArmaIndustrialFirewallStatus
from devices.models.firewall import ArmaIndustrialFirewall
from devices.services.firewall import ConnectionException
from devices.services.firewall import FirewallService

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEST_FILES = os.path.join(BASE_DIR, "tests", "test_files")

LIVE_FIREWALL_DATA = {
    "name": "LIVE IF TEST",
    "ip": os.getenv('LIVE_TEST_FIREWALL_IP', ''),
    "key": os.getenv('LIVE_TEST_FIREWALL_KEY', ''),
    "secret": os.getenv('LIVE_TEST_FIREWALL_SECRET', ''),
    "port": 5500,
    "type": 'firewall'
}

TEST_FW_GET = [
    'firewall-download-config',
    'firewall-download-rulesets'
]

TEST_FW_SET = [
    ('live_if_rulesets.tar', 'firewall-upload-ids-rulesets', 'rulesets'),
    ('live_if_config.xml', 'firewall-upload-config', 'conffile'),
]


@pytest.mark.django_db
class TestFirewallAPI:

    @pytest.fixture(autouse=True)
    def setup_tests(self, api_client, django_user_model, add_user_with_permissions):
        self.user = add_user_with_permissions(username='test_admin', password='test_admin_pass', is_superuser=True)
        api_client.force_authenticate(self.user)
        pytest.firewall = ArmaIndustrialFirewall.objects.create(**LIVE_FIREWALL_DATA)
        info = FirewallService(pytest.firewall).get_info()
        fw_status = info.get('status', ArmaIndustrialFirewallStatus.error)
        if fw_status != ArmaIndustrialFirewallStatus.online:
            assert False

    @pytest.mark.live_firewall
    def test_live_get_firewall_status_online(self, api_client):
        assert True

    @pytest.mark.parametrize('url_name', TEST_FW_GET)
    @pytest.mark.live_firewall
    def test_live_get_firewall_config(self, api_client, url_name: str):
        try:
            url = reverse(url_name, args=[pytest.firewall.id])
            response = api_client.get(url)
            assert response.reason_phrase == 'OK'
            assert response.status_code == status.HTTP_200_OK
            assert response.content is not None
        except ConnectionException:
            assert False

    @mock.patch('devices.constants.FIREWALL_TIMEOUT', 30)
    @pytest.mark.parametrize('file_name, url_name, data_name', TEST_FW_SET)
    @pytest.mark.live_firewall
    def test_live_set_firewall_suricata(self, api_client, file_name: str, url_name: str, data_name: str):
        try:
            file_path = os.path.join(TEST_FILES, file_name)
            file = open(file_path, 'r')
            url = reverse(url_name, args=[pytest.firewall.id])
            data = {data_name: file}
            response = api_client.post(url, data)
            assert response.json()['status'] == 'ok'
            assert response.status_code == status.HTTP_200_OK
        except ConnectionException:
            assert False
