#!/usr/bin/env python3
"""
SFTP client for file operations.
Handles connection, file discovery, and download operations.
"""

import paramiko
import os
from pathlib import Path
from logging_config import get_logger
from config import get_config

logger = get_logger(__name__)


class SFTPClient:
    """SFTP operations for NEFT file processing."""

    def __init__(self):
        """Initialize SFTP client."""
        self.config = get_config()
        self.sftp = None
        self.ssh = None

    def connect(self) -> bool:
        """
        Establish SFTP connection.

        Returns:
            True if successful, False otherwise
        """
        try:
            # Create SSH client
            self.ssh = paramiko.SSHClient()
            self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

            # Connect
            self.ssh.connect(
                self.config.sftp_host,
                port=self.config.sftp_port,
                username=self.config.sftp_username,
                password=self.config.sftp_password,
                timeout=10
            )

            # Get SFTP channel
            self.sftp = self.ssh.open_sftp()
            logger.info(f"Connected to SFTP server: {self.config.sftp_host}:{self.config.sftp_port}")
            return True

        except Exception as e:
            logger.error(f"Failed to connect to SFTP server: {e}", exc_info=True)
            return False

    def disconnect(self):
        """Close SFTP connection."""
        try:
            if self.sftp:
                self.sftp.close()
            if self.ssh:
                self.ssh.close()
            logger.info("SFTP connection closed")
        except Exception as e:
            logger.error(f"Error closing SFTP connection: {e}")

    def list_files(self, remote_path: str, pattern: str) -> list:
        """
        List files matching pattern in remote directory.

        Args:
            remote_path: Path on SFTP server
            

        Returns:
            List of matching filenames
        """
        if not self.sftp:
            logger.error("SFTP not connected")
            return []

        try:
            files = []
            try:
                items = self.sftp.listdir_attr(remote_path)
            except FileNotFoundError:
                logger.warning(f"Directory not found: {remote_path}")
                return []

            import fnmatch
            for item in items:
                if fnmatch.fnmatch(item.filename, pattern):
                    files.append(item.filename)

            logger.debug(f"Found {len(files)} files matching {pattern} in {remote_path}")
            return sorted(files)

        except Exception as e:
            logger.error(f"Error listing files in {remote_path}: {e}", exc_info=True)
            return []

    def download_file(self, remote_path: str, local_path: str) -> bool:
        """
        Download file from SFTP server.

        Args:
            remote_path: Full path on SFTP server
            local_path: Local destination path

        Returns:
            True if successful, False otherwise
        """
        if not self.sftp:
            logger.error("SFTP not connected")
            return False

        try:
            # Create local directory if needed
            Path(local_path).parent.mkdir(parents=True, exist_ok=True)

            # Download file
            self.sftp.get(remote_path, local_path)
            logger.info(f"Downloaded file: {remote_path} -> {local_path}")
            return True

        except Exception as e:
            logger.error(f"Error downloading file {remote_path}: {e}", exc_info=True)
            return False

    def get_file_size(self, remote_path: str) -> int:
        """
        Get size of remote file.

        Args:
            remote_path: Full path on SFTP server

        Returns:
            File size in bytes, or -1 if error
        """
        if not self.sftp:
            logger.error("SFTP not connected")
            return -1

        try:
            stat = self.sftp.stat(remote_path)
            return stat.st_size
        except Exception as e:
            logger.error(f"Error getting file size {remote_path}: {e}")
            return -1

    def __enter__(self):
        """Context manager entry."""
        self.connect()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Context manager exit."""
        self.disconnect()
