########################################################################################################################
# IMPORTS

import logging
from pathlib import Path
from typing import Any, Dict, List, Optional

import requests

########################################################################################################################
# CLASSES

logger = logging.getLogger(__name__)


class SACSAPInterface:
    """
    Interface for uploading and downloading files between SAC and SAP
    using REST/OData-style APIs.
    """

    def __init__(self, config: str):
        self.config = config

        self.profiles: List[Dict[str, Any]] = []
        self.config = config
        for section in getattr(self.config, "sections", lambda: [])():
            if section.startswith("ftp:"):
                profile_name = section.split(":", 1)[1]
                upload_endpoint = self.config[section]["endpoint"]
                auth_type = self.config[section]["auth_type"]
                self.profiles.append(
                    {
                        "profile": profile_name,
                        "upload_endpoint": upload_endpoint,
                        "auth_type": auth_type,
                    }
                )

        if not self.profiles:
            logger.warning("no ftp section in config")

        self.current_profile: Optional[Dict[str, Any]] = self.profiles[0] if self.profiles else None

    def switch_profile(self, profile_name: str) -> None:
        for profile in self.profiles:
            if profile["profile"] == profile_name:
                self.current_profile = profile
                self.ftp = profile["session"]
                return
        logger.warning(f"Profile {profile_name} not found")

    def _authenticate(self):
        auth_type = self.current_profile["auth_type"]
        if auth_type == "oauth2":
            self._oauth2_login()
        elif auth_type == "basic":
            self._basic_auth()
        elif auth_type == "bearer":
            self._bearer_auth()
        else:
            raise ValueError(f"Unsupported auth_type: {auth_type}")

    def upload_file(
        self,
        local_path: str,
        remote_path: Optional[str] = None,
        overwrite: bool = False,
    ) -> dict:
        """
        Upload a file to SAP.
        """
        self._authenticate()

        file_path = Path(local_path)
        if not file_path.exists():
            raise FileNotFoundError(local_path)

        files = {"file": (file_path.name, open(file_path, "rb"))}

        payload = {"remotePath": remote_path or file_path.name, "overwrite": overwrite}

        url = f"{self.base_url}{self.upload_endpoint}"

        response = self.session.post(url, files=files, data=payload, timeout=self.timeout, verify=self.verify_ssl)

        response.raise_for_status()
        return response.json()

    def download_file(
        self,
        remote_path: str,
        local_path: str,
        chunk_size: int = 8192,
    ):
        """
        Download a file from SAP.
        """

        url = f"{self.base_url}{self.download_endpoint}"

        params = {"path": remote_path}

        response = self.session.get(url, params=params, stream=True, timeout=self.timeout, verify=self.verify_ssl)

        response.raise_for_status()

        local_path = Path(local_path)
        local_path.parent.mkdir(parents=True, exist_ok=True)

        with open(local_path, "wb") as f:
            for chunk in response.iter_content(chunk_size=chunk_size):
                if chunk:
                    f.write(chunk)

