#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Server Client
Handles server communication for automation scripts
"""

import os
import time
import logging
import io
from typing import Optional, Dict, Any

try:
    import requests
except ImportError:
    requests = None


class ServerClient:
    """Handles all server communication for the automation script"""
    
    def __init__(self, api_base_url: str, user_id: str, job_id: str, logger=None):
        """Initialize server client.
        
        Args:
            api_base_url: Base URL of the API
            user_id: User ID
            job_id: Job ID
            logger: Optional logger instance
        """
        self.api_base_url = api_base_url.rstrip('/')
        self.user_id = user_id
        self.job_id = job_id
        self.logger = logger or logging.getLogger("ServerClient")
        
        if requests is None:
            self.logger.warning("⚠️ 'requests' library not available. Server communication disabled.")
            self.enabled = False
        else:
            self.enabled = True
    
    def upload_log_file(self, log_file_path: str, job_data: Dict[str, Any]) -> Optional[str]:
        """Upload log file to server.
        
        Args:
            log_file_path: Path to log file
            job_data: Job data dictionary
            
        Returns:
            Uploaded file path or None
        """
        if not self.enabled:
            self.logger.warning("⚠️ Server communication disabled. Skipping log file upload.")
            return None
        
        if not os.path.exists(log_file_path):
            self.logger.warning(f"⚠️ Log file not found: {log_file_path}")
            return None
        
        try:
            # Get file metadata
            file_size_bytes = os.path.getsize(log_file_path)
            file_size_kb = file_size_bytes / 1024
            file_name = os.path.basename(log_file_path)
            
            self.logger.info("📤 Starting log file upload...")
            self.logger.info(f"📊 File metadata:")
            self.logger.info(f"   - File path: {log_file_path}")
            self.logger.info(f"   - File name: {file_name}")
            self.logger.info(f"   - File size: {file_size_bytes} bytes ({file_size_kb:.2f} KB)")
            
            url = f"{self.api_base_url}/api/local-exe/jobs/{self.job_id}/upload-log"
            self.logger.info(f"🌐 Upload URL: {url}")
            
            # Log job data being sent
            self.logger.info("📊 Job data being sent:")
            self.logger.info(f"   - User ID: {job_data.get('userId', self.user_id)}")
            self.logger.info(f"   - Service ID: {job_data.get('serviceId', 'automation')}")
            self.logger.info(f"   - Service Name: {job_data.get('serviceName', 'Automation')}")
            self.logger.info(f"   - Input File Name: {job_data.get('inputFileName', 'input.csv')}")
            self.logger.info(f"   - Credits Used: {job_data.get('creditsUsed', 0)}")
            
            self.logger.info("⚡ Opening file for reading...")
            with open(log_file_path, 'rb') as f:
                files = {'logFile': (file_name, f, 'text/plain')}
                data = {
                    'userId': job_data.get('userId', self.user_id),
                    'serviceId': job_data.get('serviceId', 'automation'),
                    'serviceName': job_data.get('serviceName', 'Automation'),
                    'inputFileName': job_data.get('inputFileName', 'input.csv'),
                    'inputFilePath': job_data.get('inputFilePath', ''),
                    'creditsUsed': str(job_data.get('creditsUsed', 0))
                }
                
                self.logger.info("⚡ Sending POST request to server...")
                request_start_time = time.time()
                response = requests.post(url, files=files, data=data, timeout=30)
                request_duration = time.time() - request_start_time
                
                self.logger.info(f"⏱️ Request completed in {request_duration:.2f} seconds")
                self.logger.info(f"📊 HTTP Status Code: {response.status_code}")
                
                response.raise_for_status()
                result = response.json()
                
                self.logger.info("📊 Response received:")
                self.logger.info(f"   - Success: {result.get('success', False)}")
                if result.get('logFilePath'):
                    self.logger.info(f"   - Server file path: {result.get('logFilePath')}")
                if result.get('error'):
                    self.logger.warning(f"   - Error: {result.get('error')}")
                
                if result.get('success') and result.get('logFilePath'):
                    self.logger.info(f"✅ Log file uploaded successfully: {result['logFilePath']}")
                    self.logger.info(f"⏱️ Total upload time: {request_duration:.2f} seconds")
                    
                    # Optional: Also upload to PHP API for redundancy (non-critical)
                    self._upload_to_php_api(log_file_path, file_name, job_data, 'log')
                    
                    return result['logFilePath']
                else:
                    self.logger.warning(f"⚠️ Log upload failed: {result.get('error', 'Unknown error')}")
                    return None
        except requests.exceptions.RequestException as e:
            self.logger.error(f"❌ Failed to upload log file: {e}")
            self.logger.error(f"   Error type: {type(e).__name__}")
            return None
        except Exception as e:
            self.logger.error(f"❌ Unexpected error uploading log file: {e}")
            self.logger.error(f"   Error type: {type(e).__name__}")
            import traceback
            self.logger.debug(traceback.format_exc())
            return None
    
    def upload_results_csv(self, csv_file_path: str, job_data: Dict[str, Any]) -> Optional[str]:
        """Upload results CSV file to server.
        
        Args:
            csv_file_path: Path to CSV file
            job_data: Job data dictionary
            
        Returns:
            Uploaded file path or None
        """
        if not self.enabled:
            self.logger.warning("⚠️ Server communication disabled. Skipping CSV upload.")
            return None
        
        if not os.path.exists(csv_file_path):
            self.logger.warning(f"⚠️ CSV file not found: {csv_file_path}")
            return None
        
        try:
            # Get file metadata
            file_size_bytes = os.path.getsize(csv_file_path)
            file_size_kb = file_size_bytes / 1024
            file_name = os.path.basename(csv_file_path)
            
            self.logger.info("📤 Starting CSV file upload...")
            self.logger.info(f"📊 File metadata:")
            self.logger.info(f"   - File path: {csv_file_path}")
            self.logger.info(f"   - File name: {file_name}")
            self.logger.info(f"   - File size: {file_size_bytes} bytes ({file_size_kb:.2f} KB)")
            
            url = f"{self.api_base_url}/api/local-exe/jobs/{self.job_id}/upload-log"
            self.logger.info(f"🌐 Upload URL: {url}")
            
            # Log job data being sent
            self.logger.info("📊 Job data being sent:")
            self.logger.info(f"   - User ID: {job_data.get('userId', self.user_id)}")
            self.logger.info(f"   - Service ID: {job_data.get('serviceId', 'automation')}")
            self.logger.info(f"   - Service Name: {job_data.get('serviceName', 'Automation')}")
            self.logger.info(f"   - Input File Name: {job_data.get('inputFileName', 'input.csv')}")
            self.logger.info(f"   - Credits Used: {job_data.get('creditsUsed', 0)}")
            
            self.logger.info("⚡ Opening file for reading...")
            with open(csv_file_path, 'rb') as f:
                files = {'logFile': (file_name, f, 'text/csv')}
                data = {
                    'userId': job_data.get('userId', self.user_id),
                    'serviceId': job_data.get('serviceId', 'automation'),
                    'serviceName': job_data.get('serviceName', 'Automation'),
                    'inputFileName': job_data.get('inputFileName', 'input.csv'),
                    'inputFilePath': job_data.get('inputFilePath', ''),
                    'creditsUsed': str(job_data.get('creditsUsed', 0))
                }
                
                self.logger.info("⚡ Sending POST request to server...")
                request_start_time = time.time()
                response = requests.post(url, files=files, data=data, timeout=30)
                request_duration = time.time() - request_start_time
                
                self.logger.info(f"⏱️ Request completed in {request_duration:.2f} seconds")
                self.logger.info(f"📊 HTTP Status Code: {response.status_code}")
                
                response.raise_for_status()
                result = response.json()
                
                self.logger.info("📊 Response received:")
                self.logger.info(f"   - Success: {result.get('success', False)}")
                if result.get('logFilePath'):
                    self.logger.info(f"   - Server file path: {result.get('logFilePath')}")
                if result.get('error'):
                    self.logger.warning(f"   - Error: {result.get('error')}")
                
                if result.get('success') and result.get('logFilePath'):
                    self.logger.info(f"✅ Results CSV uploaded successfully: {result['logFilePath']}")
                    self.logger.info(f"⏱️ Total upload time: {request_duration:.2f} seconds")
                    
                    # Optional: Also upload to PHP API for redundancy (non-critical)
                    self._upload_to_php_api(csv_file_path, file_name, job_data, 'csv')
                    
                    return result['logFilePath']
                else:
                    self.logger.warning(f"⚠️ CSV upload failed: {result.get('error', 'Unknown error')}")
                    return None
        except requests.exceptions.RequestException as e:
            self.logger.error(f"❌ Failed to upload CSV file: {e}")
            self.logger.error(f"   Error type: {type(e).__name__}")
            return None
        except Exception as e:
            self.logger.error(f"❌ Unexpected error uploading CSV file: {e}")
            self.logger.error(f"   Error type: {type(e).__name__}")
            import traceback
            self.logger.debug(traceback.format_exc())
            return None
        
    def upload_log_buffer(self, log_text: str, file_name: str, job_data: Dict[str, Any]) -> Optional[str]:
        if not self.enabled:
            self.logger.warning("⚠️ Server communication disabled. Skipping log buffer upload.")
            return None
        try:
            url = f"{self.api_base_url}/api/local-exe/jobs/{self.job_id}/upload-log"
            files = { 'logFile': (file_name, io.BytesIO(log_text.encode('utf-8')), 'text/plain') }
            data = {
                'userId': job_data.get('userId', self.user_id),
                'serviceId': job_data.get('serviceId', 'automation'),
                'serviceName': job_data.get('serviceName', 'Automation'),
                'inputFileName': job_data.get('inputFileName', 'input.csv'),
                'inputFilePath': job_data.get('inputFilePath', ''),
                'creditsUsed': str(job_data.get('creditsUsed', 0))
            }
            response = requests.post(url, files=files, data=data, timeout=30)
            response.raise_for_status()
            result = response.json()
            return result.get('logFilePath') if result.get('success') else None
        except Exception as e:
            self.logger.error(f"❌ Failed to upload log buffer: {e}")
            return None
        
    def upload_results_buffer(self, csv_bytes: bytes, file_name: str, job_data: Dict[str, Any]) -> Optional[str]:
        if not self.enabled:
            self.logger.warning("⚠️ Server communication disabled. Skipping results buffer upload.")
            return None
        try:
            url = f"{self.api_base_url}/api/local-exe/jobs/{self.job_id}/upload-log"
            files = { 'logFile': (file_name, io.BytesIO(csv_bytes), 'text/csv') }
            data = {
                'userId': job_data.get('userId', self.user_id),
                'serviceId': job_data.get('serviceId', 'automation'),
                'serviceName': job_data.get('serviceName', 'Automation'),
                'inputFileName': job_data.get('inputFileName', 'input.csv'),
                'inputFilePath': job_data.get('inputFilePath', ''),
                'creditsUsed': str(job_data.get('creditsUsed', 0))
            }
            response = requests.post(url, files=files, data=data, timeout=30)
            response.raise_for_status()
            result = response.json()
            return result.get('logFilePath') if result.get('success') else None
        except Exception as e:
            self.logger.error(f"❌ Failed to upload results buffer: {e}")
            return None
        
    def report_job_result(self, result_files: list, output_directory: str, successful_count: Optional[int] = None) -> bool:
        """Report job completion to server.
        
        Args:
            result_files: List of result file paths
            output_directory: Output directory path
            successful_count: Optional count of successful operations
            
        Returns:
            True if successful, False otherwise
        """
        if not self.enabled:
            self.logger.warning("⚠️ Server communication disabled. Skipping job result reporting.")
            return False
        
        try:
            self.logger.info("📤 Starting job result reporting...")
            url = f"{self.api_base_url}/api/local-exe/jobs/{self.job_id}/complete"
            self.logger.info(f"🌐 Report URL: {url}")
            
            payload = {
                'success': True,
                'resultFiles': result_files,
                'outputFiles': [],
                'outputDirectory': output_directory
            }
            if successful_count is not None:
                payload['successfulCount'] = successful_count
            
            self.logger.info("📊 Payload being sent:")
            self.logger.info(f"   - Success: {payload.get('success')}")
            self.logger.info(f"   - Result files: {len(payload.get('resultFiles', []))} file(s)")
            for i, file_path in enumerate(payload.get('resultFiles', []), 1):
                self.logger.info(f"      {i}. {file_path}")
            self.logger.info(f"   - Output directory: {payload.get('outputDirectory')}")
            if successful_count is not None:
                self.logger.info(f"   - Successful count: {payload.get('successfulCount')}")
            
            self.logger.info("⚡ Sending POST request to server...")
            self.logger.info(f"   📤 Payload summary: success={payload.get('success')}, resultFiles={len(payload.get('resultFiles', []))}, successfulCount={payload.get('successfulCount', 'N/A')}")
            request_start_time = time.time()
            response = requests.post(url, json=payload, timeout=30)
            request_duration = time.time() - request_start_time
            
            self.logger.info(f"⏱️ Request completed in {request_duration:.2f} seconds")
            self.logger.info(f"📊 HTTP Status Code: {response.status_code}")
            
            # Log response details even if there's an error
            try:
                result = response.json()
                self.logger.info("📊 Response received:")
                self.logger.info(f"   - Success: {result.get('success', False)}")
                if result.get('error'):
                    self.logger.warning(f"   - Error: {result.get('error')}")
                if result.get('message'):
                    self.logger.info(f"   - Message: {result.get('message')}")
            except Exception as parse_error:
                self.logger.error(f"   ❌ Failed to parse response JSON: {parse_error}")
                self.logger.error(f"   Response text: {response.text[:500]}")
                raise
            
            response.raise_for_status()
            
            if result.get('success'):
                self.logger.info("✅ Job result reported successfully to server")
                self.logger.info(f"⏱️ Total reporting time: {request_duration:.2f} seconds")
                self.logger.info("   💡 Note: Work history should now be visible in the dashboard")
                return True
            else:
                self.logger.warning(f"⚠️ Job result reporting failed: {result.get('error', 'Unknown error')}")
                self.logger.warning("   ⚠️ Work history may not have been saved - check server logs")
                return False
        except requests.exceptions.RequestException as e:
            self.logger.error(f"❌ Failed to report job result: {e}")
            self.logger.error(f"   Error type: {type(e).__name__}")
            return False
        except Exception as e:
            self.logger.error(f"❌ Unexpected error reporting job result: {e}")
            self.logger.error(f"   Error type: {type(e).__name__}")
            import traceback
            self.logger.debug(traceback.format_exc())
            return False
    
    def _upload_to_php_api(self, file_path: str, file_name: str, job_data: Dict[str, Any], file_type: str) -> None:
        """Optional upload to PHP API for redundancy (non-critical).
        
        Args:
            file_path: Path to file to upload
            file_name: Name of the file
            job_data: Job data dictionary
            file_type: Type of file ('log' or 'csv')
        """
        try:
            self.logger.info(f"📤 Attempting backup upload to PHP API ({file_type})...")
            
            # Determine  PHP API upload endpoint
            # Replace port 3001 with default port for PHP API
            php_api_base = self.api_base_url.replace(':3001', '')
            php_upload_url = f"{php_api_base}/api/php/upload-job-file"
            
            with open(file_path, 'rb') as f:
                files = {'file': (file_name, f, 'application/octet-stream')}
                data = {
                    'userId': job_data.get('userId', self.user_id),
                    'jobId': self.job_id,
                    'serviceId': job_data.get('serviceId', 'automation'),
                    'fileType': file_type
                }
                
                response = requests.post(php_upload_url, files=files, data=data, timeout=15)
                
                if response.ok:
                    result = response.json()
                    if result.get('success'):
                        self.logger.info(f"✅ PHP API backup upload successful ({file_type})")
                    else:
                        self.logger.debug(f"⚠️ PHP API upload returned non-success: {result.get('message')}")
                else:
                    self.logger.debug(f"⚠️ PHP API upload returned status {response.status_code}")
                    
        except Exception as e:
            # This is intentionally non-critical - log at debug level only
            self.logger.debug(f"⚠️ PHP API backup upload failed (non-critical): {e}")

