import responses
import json

from brian_dashboard_manager.grafana.provision import provision_folder, \
    provision

TEST_INTERFACES = [
    {
        "router": "srx2.ch.office.geant.net",
        "name": "ge-0/0/8",
        "bundle": [],
        "bundle-parents": [],
        "description": "PHY CUSTOMER GEANT CORPORATE SRF000001 | GEANT Corporate to MX1.LON - Via Vodafone",  # noqa: E501
        "circuits": [
            {
                "id": 679232,
                "name": "GEANT CORPORATE TO MX1.LON - VIA VODAFONE",
                "type": "GEANT IP",
                "status": "non-monitored"
            }
        ],
        "snmp-index": 523,
        "dashboards": [
            "NREN",
            "RE_CUST"
        ],
        "dashboard_info": {
            "name": "GEANT",
            "interface_type": "PHYSICAL"
        },
        "ipv4": [],
        "ipv6": []
    },
    {
        "router": "srx2.ch.office.geant.net",
        "name": "ge-0/0/8.10",
        "bundle": [],
        "bundle-parents": [],
        "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE-ViaVodafone | GEANT Corporate to mx1.lon - Via Vodafone ",  # noqa: E501
        "circuits": [
            {
                "id": 679360,
                "name": "GEANT_CORPORATE-VIAVODAFONE",
                "type": "GEANT IP",
                "status": "non-monitored"
            }
        ],
        "snmp-index": 543,
        "dashboards": [
            "NREN",
            "RE_CUST"
        ],
        "dashboard_info": {
            "name": "GEANT",
            "interface_type": "LOGICAL"
        },
        "ipv4": [
            "62.40.127.131/31"
        ],
        "ipv6": [
            "2001:798:99:1::ca/126"
        ]
    },
    {
        "router": "srx2.ch.office.geant.net",
        "name": "ge-0/0/8.11",
        "bundle": [],
        "bundle-parents": [],
        "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE_ViaVodafone-VRF | GEANT Corporate to mx1.lon - Via Vodafone - for VRF",  # noqa: E501
        "circuits": [
            {
                "id": 712144,
                "name": "GEANT_CORPORATE_VIAVODAFONE-VRF",
                "type": "GEANT IP",
                "status": "non-monitored"
            }
        ],
        "snmp-index": 545,
        "dashboards": [
            "NREN",
            "RE_CUST"
        ],
        "dashboard_info": {
            "name": "GEANT",
            "interface_type": "LOGICAL"
        },
        "ipv4": [
            "10.101.0.6/30"
        ],
        "ipv6": []
    },
    {
        "router": "srx2.ch.office.geant.net",
        "name": "ge-0/0/8.12",
        "bundle": [],
        "bundle-parents": [],
        "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE_ViaVodafone-VRF-TEST | GEANT Corporate to mx1.lon - Via Vodafone - DASHBOARD BGP TEST VLAN",  # noqa: E501
        "circuits": [
            {
                "id": 678920,
                "name": "GEANT_CORPORATE_VIAVODAFONE-VRF-TEST (DO NOT OPEN A TICKET)",  # noqa: E501
                "type": "GEANT IP",
                "status": "non-monitored"
            }
        ],
        "snmp-index": 522,
        "dashboards": [
            "NREN",
            "RE_CUST"
        ],
        "dashboard_info": {
            "name": "GEANT",
            "interface_type": "LOGICAL"
        },
        "ipv4": [
            "62.40.127.141/31"
        ],
        "ipv6": []
    },
    {
        "router": "srx2.ch.office.geant.net",
        "name": "ge-0/0/8.996",
        "bundle": [],
        "bundle-parents": [],
        "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_OPERATIONS_LabConnectivity | GEANT MX1.LON Infinera VRF to Operations Lab",  # noqa: E501
        "circuits": [
            {
                "id": 678999,
                "name": "GEANT_OPERATIONS_LABCONNECTIVITY",
                "type": "GEANT IP",
                "status": "non-monitored"
            }
        ],
        "snmp-index": 554,
        "dashboards": [
            "NREN",
            "RE_CUST"
        ],
        "dashboard_info": {
            "name": "GEANT",
            "interface_type": "LOGICAL"
        },
        "ipv4": [
            "10.1.1.1/30"
        ],
        "ipv6": []
    },
    {
        "router": "mx1.ams.nl.geant.net",
        "name": "xe-0/0/0",
        "bundle": [
            "ae16"
        ],
        "bundle-parents": [],
        "description": "PHY CUSTOMER KIAE P_AE16 SRF9915671 |",
        "circuits": [],
        "snmp-index": 588,
        "dashboards": [
            "NREN",
            "RE_CUST"
        ],
        "dashboard_info": {
            "name": "KIAE",
            "interface_type": "PHYSICAL"
        },
        "ipv4": [],
        "ipv6": []
    },
    {
        "router": "mx1.ams.nl.geant.net",
        "name": "xe-0/0/1",
        "bundle": [
            "ae14"
        ],
        "bundle-parents": [],
        "description": "PHY CUSTOMER SWITCH P_AE14 SRF18008 |",
        "circuits": [],
        "snmp-index": 589,
        "dashboards": [
            "NREN",
            "RE_CUST"
        ],
        "dashboard_info": {
            "name": "SWITCH",
            "interface_type": "PHYSICAL"
        },
        "ipv4": [],
        "ipv6": []
    },
    {
        "router": "mx1.ams.nl.geant.net",
        "name": "ge-0/2/1.0",
        "bundle": [],
        "bundle-parents": [],
        "description": "SRV_L2CIRCUIT INFRASTRUCTURE GEANT GEANT #AMS-ZAG OPENFLOW |",  # noqa: E501
        "circuits": [],
        "snmp-index": 687,
        "dashboards": [
            "L2_CIRCUIT"
        ],
        "dashboard_info": {
            "name": "GEANT",
            "interface_type": "LOGICAL"
        },
        "ipv4": [],
        "ipv6": []
    },
    {
        "router": "mx1.ams.nl.geant.net",
        "name": "ge-0/2/2.0",
        "bundle": [],
        "bundle-parents": [],
        "description": "SRV_L2CIRCUIT INFRASTRUCTURE GEANT GEANT #AMS-VIE OPENFLOW |",  # noqa: E501
        "circuits": [],
        "snmp-index": 711,
        "dashboards": [
            "L2_CIRCUIT"
        ],
        "dashboard_info": {
            "name": "GEANT",
            "interface_type": "LOGICAL"
        },
        "ipv4": [],
        "ipv6": []
    },
    {
        "router": "mx1.ams.nl.geant.net",
        "name": "ge-0/2/4.0",
        "bundle": [],
        "bundle-parents": [],
        "description": "SRV_L2CIRCUIT INFRASTRUCTURE GEANT GEANT #AMS-FRA OPENFLOW |",  # noqa: E501
        "circuits": [],
        "snmp-index": 718,
        "dashboards": [
            "L2_CIRCUIT"
        ],
        "dashboard_info": {
            "name": "GEANT",
            "interface_type": "LOGICAL"
        },
        "ipv4": [],
        "ipv6": []
    }
]

NREN_INTERFACES = [
    {
        "router": "mx1.dub2.ie.geant.net",
        "name": "xe-0/0/0",
        "bundle": [
                "ae10"
        ],
        "bundle-parents": [],
        "description": "PHY CUSTOMER HEANET P_AE10 SRF9948758 | HEANET-AP2-LL3",  # noqa: E501
        "circuits": [],
        "snmp-index": 554,
        "dashboards": [
            "NREN",
            "RE_CUST"
        ],
        "dashboard_info": {
            "name": "HEANET",
            "interface_type": "PHYSICAL"
        },
        "ipv4": [],
        "ipv6": []
    },
    {
        "router": "mx1.dub2.ie.geant.net",
        "name": "xe-1/0/1",
        "bundle": [
                "ae10"
        ],
        "bundle-parents": [],
        "description": "PHY CUSTOMER HEANET P_AE10 SRF0000001 | HEANET-AP2-LL2",  # noqa: E501
        "circuits": [],
        "snmp-index": 527,
        "dashboards": [
            "NREN",
            "RE_CUST"
        ],
        "dashboard_info": {
            "name": "HEANET",
            "interface_type": "PHYSICAL"
        },
        "ipv4": [],
        "ipv6": []
    },
    {
        "router": "mx1.dub2.ie.geant.net",
        "name": "xe-1/1/0",
        "bundle": [
                "ae10"
        ],
        "bundle-parents": [],
        "description": "PHY CUSTOMER HEANET P_AE10 SRF9925903 | HEANET-AP2-LL1",  # noqa: E501
        "circuits": [],
        "snmp-index": 528,
        "dashboards": [
            "NREN",
            "RE_CUST"
        ],
        "dashboard_info": {
            "name": "HEANET",
            "interface_type": "PHYSICAL"
        },
        "ipv4": [],
        "ipv6": []
    },
    {
        "router": "mx1.dub2.ie.geant.net",
        "name": "ae10",
        "bundle": [],
        "bundle-parents": [
                "xe-0/0/0",
                "xe-1/0/1",
                "xe-1/1/0"
        ],
        "description": "LAG CUSTOMER HEANET SRF9925909 | HEANET-AP2-LAG",
        "circuits": [],
        "snmp-index": 596,
        "dashboards": [
            "NREN",
            "RE_CUST"
        ],
        "dashboard_info": {
            "name": "HEANET",
            "interface_type": "AGGREGATE"
        },
        "ipv4": [],
        "ipv6": []
    },
    {
        "router": "mx1.dub2.ie.geant.net",
        "name": "ae10.12",
        "bundle": [],
        "bundle-parents": [
                "xe-0/0/0",
                "xe-1/0/1",
                "xe-1/1/0"
        ],
        "description": "SRV_GLOBAL CUSTOMER HEANET #HEANET-AP2 | ASN1213 | ",
        "circuits": [
            {
                "id": 662976,
                "name": "HEANET-AP2",
                "type": "GEANT IP",
                "status": "operational"
            }
        ],
        "snmp-index": 713,
        "dashboards": [
            "NREN",
            "RE_CUST"
        ],
        "dashboard_info": {
            "name": "HEANET",
            "interface_type": "LOGICAL"
        },
        "ipv4": [
            "62.40.125.13/30"
        ],
        "ipv6": [
            "2001:0798:0018:10aa::15/126"
        ]
    },
    {
        "router": "mx1.dub2.ie.geant.net",
        "name": "ae10.30",
        "bundle": [],
        "bundle-parents": [
                "xe-0/0/0",
                "xe-1/0/1",
                "xe-1/1/0"
        ],
        "description": "SRV_MDVPN CUSTOMER HEANET AP2 #HEANET-BGP-LU-CoC-1 |",  # noqa: E501
        "circuits": [
            {
                "id": 663160,
                "name": "HEANET-BGP-LU-COC-1",
                "type": "MD-VPN (NATIVE)",
                "status": "operational"
            }
        ],
        "snmp-index": 712,
        "dashboards": [
            "MDVPN_CUSTOMERS",
            "NREN"
        ],
        "dashboard_info": {
            "name": "HEANET",
            "interface_type": "LOGICAL"
        },
        "ipv4": [
            "62.40.102.36/31"
        ],
        "ipv6": []
    },
    {
        "router": "mx1.dub2.ie.geant.net",
        "name": "ae10.333",
        "bundle": [],
        "bundle-parents": [
                "xe-0/0/0",
                "xe-1/0/1",
                "xe-1/1/0"
        ],
        "description": "SRV_IAS CUSTOMER HEANET #HEANET-AP2-IAS IASPS | ASN1213 ",  # noqa: E501
        "circuits": [
            {
                "id": 663214,
                "name": "HEANET-AP2-IAS",
                "type": "GEANT PEERING",
                "status": "operational"
            }
        ],
        "snmp-index": 658,
        "dashboards": [
            "IAS_CUSTOMER",
            "NREN"
        ],
        "dashboard_info": {
            "name": "HEANET",
            "interface_type": "LOGICAL"
        },
        "ipv4": [
            "83.97.88.77/30"
        ],
        "ipv6": [
            "2001:798:1::61/126"
        ]
    },
    {
        "router": "mx1.dub2.ie.geant.net",
        "name": "ae10.1214",
        "bundle": [],
        "bundle-parents": [
                "xe-0/0/0",
                "xe-1/0/1",
                "xe-1/1/0"
        ],
        "description": "SRV_L2CIRCUIT CUSTOMER HEANET GEANT #ams-dub2-HEANET-RARE-21061 |",  # noqa: E501
        "circuits": [
            {
                "id": 713335,
                "name": "AMS-DUB2-HEANET-RARE-21061",
                "type": "GEANT PLUS",
                "status": "non-monitored"
            }
        ],
        "snmp-index": 790,
        "dashboards": [
            "L2_CIRCUIT"
        ],
        "dashboard_info": {
            "name": "HEANET",
            "interface_type": "LOGICAL"
        },
        "ipv4": [],
        "ipv6": []
    }
]

EUMETSAT_MULTICAST = [
    {
        'router': 'mx1.ams.nl.geant.net',
        'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.1.193.17.9.3.255.255.255.255',  # noqa: E501
        'community': '0pBiFbD',
        'subscription': '232.223.222.1',
        'endpoint': '193.17.9.3'
    },
    {
        'router': 'mx1.ams.nl.geant.net',
        'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.2.193.17.9.3.255.255.255.255',  # noqa: E501
        'community': '0pBiFbD',
        'subscription': '232.223.222.2',
        'endpoint': '193.17.9.3'
    },
    {
        'router': 'mx1.lon.uk.geant.net',
        'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.1.193.17.9.3.255.255.255.255',  # noqa: E501
        'community': '0pBiFbD',
        'subscription': '232.223.222.1',
        'endpoint': '193.17.9.3'
    },
    {
        'router': 'mx1.lon.uk.geant.net',
        'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.2.193.17.9.3.255.255.255.255',  # noqa: E501
        'community': '0pBiFbD',
        'subscription': '232.223.222.2',
        'endpoint': '193.17.9.3'
    },
    {
        'router': 'mx1.fra.de.geant.net',
        'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.1.193.17.9.3.255.255.255.255',  # noqa: E501
        'community': '0pBiFbD',
        'subscription': '232.223.222.1',
        'endpoint': '193.17.9.3'
    },
    {
        'router': 'mx1.fra.de.geant.net',
        'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.2.193.17.9.3.255.255.255.255',  # noqa: E501
        'community': '0pBiFbD',
        'subscription': '232.223.222.2',
        'endpoint': '193.17.9.3'
    }
]


def generate_folder(data):
    return {
        "id": 555,
        "uid": data['uid'],
        "title": data['title'],
        "url": f"/dashboards/f/{data['uid']}/{data['title'].lower()}",
        "hasAcl": False,
        "canSave": True,
        "canEdit": True,
        "canAdmin": True,
        "createdBy": "Anonymous",
        "created": "2021-02-23T15:33:46Z",
        "updatedBy": "Anonymous",
        "updated": "2021-02-23T15:33:46Z",
        "version": 1
    }


@responses.activate
def test_provision_folder(data_config, mocker):
    dashboards = {
        'NREN': {
            'tag': ['customers'],
            'folder_name': 'NREN Access',
            'interfaces': [
                iface for iface in TEST_INTERFACES
                if 'NREN' in iface['dashboards']]
        },
        'RE_CUST': {
            'tag': 'RE_CUST',
            'folder_name': 'RE Customer',
            'interfaces': [
                iface for iface in TEST_INTERFACES
                if 'RE_CUST' in iface['dashboards']]
        },

    }

    # just return a generated folder
    _mocked_find_folder = mocker.patch(
        'brian_dashboard_manager.grafana.provision.find_folder')
    _mocked_find_folder.return_value = generate_folder(
        {'uid': 'testfolderuid', 'title': 'testfolder'})

    def create_dashboard(request, dashboard, folder_id=None):
        return dashboard

    mocker.patch(
        'brian_dashboard_manager.grafana.provision.create_dashboard',
        create_dashboard)

    excluded_dashboards = []
    nren_result = provision_folder(None, 'testfolder', dashboards['NREN'],
                                   'testdatasource', excluded_dashboards)

    assert len(nren_result) == 3
    assert nren_result[0]['title'] == 'GEANT'
    assert nren_result[1]['title'] == 'KIAE'
    assert nren_result[2]['title'] == 'SWITCH'

    excluded_dashboards = ['SWITCH']
    nren_excluded = provision_folder(None, 'testfolder', dashboards['NREN'],
                                     'testdatasource', excluded_dashboards)

    assert len(nren_excluded) == 2
    assert nren_excluded[0]['title'] == 'GEANT'
    assert nren_excluded[1]['title'] == 'KIAE'

    cust_result = provision_folder(None, 'testfolder', dashboards['RE_CUST'],
                                   'testdatasource', ['GEANT'])
    assert len(cust_result) == 2
    assert cust_result[0]['title'] == 'KIAE'
    assert cust_result[1]['title'] == 'SWITCH'


@responses.activate
def test_provision(data_config, mocker, client):

    responses.add(
        method=responses.GET,
        url=f"{data_config['inventory_provider']}/poller/interfaces",
        json=NREN_INTERFACES)

    responses.add(
        method=responses.GET,
        url=f"{data_config['inventory_provider']}/data/interfaces",
        json=NREN_INTERFACES)

    responses.add(
        method=responses.GET,
        url=f'{data_config["inventory_provider"]}/poller/eumetsat-multicast',
        json=EUMETSAT_MULTICAST)

    responses.add(
        method=responses.DELETE,
        url=f"http://{data_config['hostname']}/api/folders",
        json={"message": "Deleted folder"})

    responses.add(
        method=responses.GET,
        url=f"http://{data_config['hostname']}/api/folders",
        json=[])

    responses.add(
        method='get',
        url=f"http://{data_config['hostname']}/api/folders",
        json=[])

    def folder_post(request):
        data = json.loads(request.body)
        return 200, {}, json.dumps(generate_folder(data))

    responses.add_callback(
        method=responses.POST,
        url=f"http://{data_config['hostname']}/api/folders",
        callback=folder_post)

    def search_responses(request):
        if request.params.get('query', None) == 'Home':
            return 200, {}, json.dumps([])
        if request.params.get('type', None) == 'dash-db':
            return 200, {}, json.dumps([])
        assert False  # no other queries expected

    responses.add_callback(
        method=responses.GET,
        url=f"http://{data_config['hostname']}/api/search",
        callback=search_responses)

    responses.add(
        method=responses.GET,
        url=f"http://{data_config['hostname']}/api/datasources",
        json=[{
            "name": "brian-influx-datasource",
            "type": "influxdb",
            "access": "proxy",
            "url": "http://test-brian-datasource.geant.org:8086",
            "database": "test-db",
            "basicAuth": False,
            "isDefault": True,
            "readOnly": False
        }])

    responses.add(
        method=responses.POST,
        url=f"http://{data_config['hostname']}/api/dashboards/db",
        json={'id': 666})

    responses.add(
        method=responses.PUT,
        url=f"http://{data_config['hostname']}/api/org/preferences",
        json={'message': 'Preferences updated'})

    def homedashboard(request):
        return 404, {}, ''

    responses.add_callback(
        method=responses.GET,
        url=f"http://{data_config['hostname']}/api/dashboards/uid/home",
        callback=homedashboard)

    PROVISIONED_ORGANIZATION = {
        'name': data_config['organizations'][0],
        'id': 0
    }

    EXISTING_ORGS = [{**org, 'id': i + 1}
                     for i, org in enumerate(data_config['organizations'][1:])]

    _mocked_get_organizations = mocker.patch(
        'brian_dashboard_manager.grafana.provision.get_organizations')
    # all organizations are provisioned except the first one.
    _mocked_get_organizations.return_value = EXISTING_ORGS.copy()

    _mocked_create_organization = mocker.patch(
        'brian_dashboard_manager.grafana.provision.create_organization')

    # spoof creating first organization
    _mocked_create_organization.return_value = PROVISIONED_ORGANIZATION

    _mocked_delete_expired_api_tokens = mocker.patch(
        'brian_dashboard_manager.grafana.provision.delete_expired_api_tokens')
    # we dont care about this, , tested separately
    _mocked_delete_expired_api_tokens.return_value = None

    _mocked_create_api_token = mocker.patch(
        'brian_dashboard_manager.grafana.provision.create_api_token')
    _mocked_create_api_token.return_value = {
        'key': 'testtoken', 'id': 0}  # api token

    _mocked_create_datasource = mocker.patch(
        'brian_dashboard_manager.grafana.provision.create_datasource')
    # we dont care about this, just mark it created
    _mocked_create_datasource.return_value = True

    _mocked_get_dashboard_definitions = mocker.patch(
        'brian_dashboard_manager.grafana.provision.get_dashboard_definitions')

    _mocked_gws = mocker.patch(
        'brian_dashboard_manager.grafana.provision.get_gws_direct')
    _mocked_gws.return_value = []

    _mocked_gws_indirect = mocker.patch(
        'brian_dashboard_manager.grafana.provision.get_gws_indirect')
    _mocked_gws_indirect.return_value = []

    UID = 1
    ID = 1
    VERSION = 1
    TITLE = 'testdashboard'
    dashboard = {'id': ID, 'uid': UID, 'title': TITLE, 'version': VERSION}
    _mocked_get_dashboard_definitions.return_value = [
        dashboard  # test dashboard
    ]

    _mocked_create_dashboard = mocker.patch(
        'brian_dashboard_manager.grafana.provision.create_dashboard')
    # we dont care about this, just mark it created
    # we dont care about this, tested separately
    _mocked_create_dashboard.return_value = {'id': 666}

    _mocked_delete_api_token = mocker.patch(
        'brian_dashboard_manager.grafana.provision.delete_api_token')
    # we dont care about this, tested separately
    _mocked_delete_api_token.return_value = None
    provision(data_config)