# Copyright 2022-2025 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
from typing import Optional

import requests
from requests.auth import HTTPBasicAuth

LOGGER = logging.getLogger(__name__)

NCE_FAN_URL = "{:s}://{:s}:{:d}/restconf/v1/data"
TIMEOUT = 30

HTTP_OK_CODES = {
    200,  # OK
    201,  # Created
    202,  # Accepted
    204,  # No Content
}

MAPPING_STATUS = {
    "DEVICEOPERATIONALSTATUS_UNDEFINED": 0,
    "DEVICEOPERATIONALSTATUS_DISABLED": 1,
    "DEVICEOPERATIONALSTATUS_ENABLED": 2,
}

MAPPING_DRIVER = {
    "DEVICEDRIVER_UNDEFINED": 0,
    "DEVICEDRIVER_OPENCONFIG": 1,
    "DEVICEDRIVER_TRANSPORT_API": 2,
    "DEVICEDRIVER_P4": 3,
    "DEVICEDRIVER_IETF_NETWORK_TOPOLOGY": 4,
    "DEVICEDRIVER_ONF_TR_532": 5,
    "DEVICEDRIVER_XR": 6,
    "DEVICEDRIVER_IETF_L2VPN": 7,
    "DEVICEDRIVER_GNMI_OPENCONFIG": 8,
    "DEVICEDRIVER_OPTICAL_TFS": 9,
    "DEVICEDRIVER_IETF_ACTN": 10,
    "DEVICEDRIVER_OC": 11,
}

HEADERS = {'Content-Type': 'application/json'}

class NCEClient:
    def __init__(
        self,
        address: str,
        port: int,
        scheme: str = "http",
        username: Optional[str] = None,
        password: Optional[str] = None,
    ) -> None:
        self._nce_fan_url = NCE_FAN_URL.format(scheme, address, port)
        self._auth = None

    def create_app_flow(self, app_flow_data: dict) -> None:
        try:
            app_data = app_flow_data["huawei-nce-app-flow:app-flows"]["applications"]
            app_url = self._nce_fan_url + "/app-flows/apps"
            LOGGER.info(f'Creating app: {app_data} URL: {app_url}')
            requests.post(app_url, json=app_data, headers=HEADERS)

            app_flow_data = {
                "app-flow": app_flow_data["huawei-nce-app-flow:app-flows"]["app-flow"]
            }
            app_flow_url = self._nce_fan_url + "/app-flows"
            LOGGER.info(f'Creating app flow: {app_flow_data} URL: {app_flow_url}')
            requests.post(app_flow_url, json=app_flow_data, headers=HEADERS)
        except requests.exceptions.ConnectionError:
            raise Exception("faild to send post requests to NCE FAN")

    def delete_app_flow(self, app_flow_name: str) -> None:
        try:
            app_url = self._nce_fan_url + f"/app-flows/apps/application={app_flow_name}"
            LOGGER.info(f'Deleting app: {app_flow_name} URL: {app_url}')
            requests.delete(app_url)

            app_flow_url = self._nce_fan_url + f"/app-flows/app-flow={app_flow_name}"
            LOGGER.info(f'Deleting app flow: {app_flow_name} URL: {app_flow_url}')
            requests.delete(app_flow_url)
        except requests.exceptions.ConnectionError:
            raise Exception("faild to send delete request to NCE FAN")
