import requests import io from PIL import Image from typing import Dict, Any import logging logger = logging.getLogger(__name__) class DermaScanAPIClient: """Client for external DermaScan AI API""" def __init__(self, base_url: str = "https://omarelrayes-api.hf.space"): self.base_url = base_url.rstrip('/') self.timeout = 60 def health_check(self) -> bool: """Check if external API is healthy""" try: response = requests.get(f"{self.base_url}/health", timeout=5) return response.status_code == 200 except Exception as e: logger.error(f"Health check failed: {e}") return False def upload_and_analyze_image(self, image: Image.Image, thread_id: str) -> Dict[str, Any]: """ Upload image and get full analysis (classification + segmentation) Returns dict with: label, confidence_pct, infection_pct, images """ try: # Convert PIL Image to bytes img_byte_arr = io.BytesIO() image.save(img_byte_arr, format='PNG') img_byte_arr.seek(0) # Upload and analyze files = {'file': ('image.png', img_byte_arr, 'image/png')} data = {'thread_id': thread_id} response = requests.post( f"{self.base_url}/analyze-image", files=files, data=data, timeout=self.timeout ) response.raise_for_status() result = response.json() if not result.get('ok'): return {'error': result.get('error', 'Analysis failed')} return { 'label': result.get('label', 'Unknown'), 'confidence_pct': result.get('confidence_pct', 0), 'infection_pct': result.get('infection_pct', 0), 'images': result.get('images', {}), 'patient': result.get('patient', {}), } except requests.exceptions.Timeout: return {'error': 'API request timed out'} except requests.exceptions.RequestException as e: return {'error': f'API request failed: {str(e)}'} except Exception as e: logger.error(f"Unexpected error in upload_and_analyze_image: {e}", exc_info=True) return {'error': f'Unexpected error: {str(e)}'} def book_appointment(self, thread_id: str, city: str = "") -> Dict[str, Any]: """Book appointment via external API""" try: response = requests.post( f"{self.base_url}/book-appointment", json={'thread_id': thread_id, 'city': city}, timeout=30 ) response.raise_for_status() return response.json() except Exception as e: return {'ok': False, 'error': str(e)} def get_patient_image(self, thread_id: str) -> Dict[str, Any]: """Get patient's uploaded image""" try: response = requests.get( f"{self.base_url}/patient-image", params={'thread_id': thread_id}, timeout=30 ) response.raise_for_status() return response.json() except Exception as e: return {'ok': False, 'error': str(e)} def segment_patient_image(self, thread_id: str) -> Dict[str, Any]: """Segment patient's image""" try: response = requests.post( f"{self.base_url}/segment-patient-image", json={'thread_id': thread_id}, timeout=60 ) response.raise_for_status() return response.json() except Exception as e: return {'ok': False, 'error': str(e)} def reanalyze_patient_image(self, thread_id: str) -> Dict[str, Any]: """Reanalyze patient's image""" try: response = requests.post( f"{self.base_url}/reanalyze-patient-image", json={'thread_id': thread_id}, timeout=60 ) response.raise_for_status() return response.json() except Exception as e: return {'ok': False, 'error': str(e)}