"""Web-ready API for Flask, FastAPI, Django, etc."""

from typing import Dict, Any, Optional, List
import base64
import io
import numpy as np
import cv2
from dataclasses import dataclass, asdict
import json


@dataclass
class WebDetection:
    """Web-friendly detection format (JSON serializable)."""
    bbox: List[float]  # [x1, y1, x2, y2]
    confidence: float
    class_id: int
    class_name: str
    tracker_id: Optional[int] = None
    mask: Optional[str] = None  # Base64 encoded


@dataclass
class WebResponse:
    """Standard web API response."""
    success: bool
    detections: List[WebDetection]
    frame_id: int
    processing_time_ms: float
    metadata: Dict[str, Any]
    error: Optional[str] = None


class WebAPI:
    """Web-ready interface for Eye library.
    
    Features:
    - JSON serializable responses
    - Base64 image encoding/decoding
    - CORS-ready
    - Stateless operation
    - Fast processing
    
    Perfect for: Flask, FastAPI, Django, Node.js bridges, etc.
    """
    
    def __init__(
        self,
        model: Any,
        tracker: Optional[Any] = None,
        class_names: Optional[Dict[int, str]] = None
    ):
        """
        Args:
            model: Detection model (YOLO, etc.)
            tracker: Optional tracker
            class_names: Dict mapping class IDs to names
        """
        self.model = model
        self.tracker = tracker
        self.class_names = class_names or {}
    
    def process_base64(
        self,
        image_b64: str,
        conf_threshold: float = 0.5,
        frame_id: int = 0
    ) -> Dict[str, Any]:
        """Process base64-encoded image.
        
        Args:
            image_b64: Base64 encoded image
            conf_threshold: Confidence threshold
            frame_id: Frame identifier
        
        Returns:
            JSON-serializable dict
        """
        import time
        start = time.time()
        
        try:
            # Decode image
            image = self.decode_base64_image(image_b64)
            
            # Process
            response = self.process_image(image, conf_threshold, frame_id)
            response.processing_time_ms = (time.time() - start) * 1000
            
            return asdict(response)
        
        except Exception as e:
            return asdict(WebResponse(
                success=False,
                detections=[],
                frame_id=frame_id,
                processing_time_ms=(time.time() - start) * 1000,
                metadata={},
                error=str(e)
            ))
    
    def process_image(
        self,
        image: np.ndarray,
        conf_threshold: float = 0.5,
        frame_id: int = 0
    ) -> WebResponse:
        """Process numpy image.
        
        Args:
            image: Input image (numpy array)
            conf_threshold: Confidence threshold
            frame_id: Frame identifier
        
        Returns:
            WebResponse
        """
        from eye.detection.auto_convert import auto_convert
        
        # Detect
        results = self.model(image, conf=conf_threshold, verbose=False)
        detections = auto_convert(results)
        
        # Track
        if self.tracker:
            detections = self.tracker.update(detections)
        
        # Convert to web format
        web_dets = []
        for i in range(len(detections)):
            web_det = WebDetection(
                bbox=detections.xyxy[i].tolist(),
                confidence=float(detections.confidence[i]) if detections.confidence is not None else 1.0,
                class_id=int(detections.class_id[i]) if detections.class_id is not None else 0,
                class_name=self.class_names.get(
                    int(detections.class_id[i]) if detections.class_id is not None else 0,
                    'unknown'
                ),
                tracker_id=int(detections.tracker_id[i]) if detections.tracker_id is not None else None
            )
            web_dets.append(web_det)
        
        return WebResponse(
            success=True,
            detections=web_dets,
            frame_id=frame_id,
            processing_time_ms=0.0,  # Will be set by caller
            metadata={
                'image_shape': list(image.shape),
                'num_detections': len(web_dets)
            }
        )
    
    @staticmethod
    def decode_base64_image(image_b64: str) -> np.ndarray:
        """Decode base64 image to numpy array."""
        # Remove data URL prefix if present
        if ',' in image_b64:
            image_b64 = image_b64.split(',')[1]
        
        # Decode
        img_bytes = base64.b64decode(image_b64)
        img_array = np.frombuffer(img_bytes, dtype=np.uint8)
        image = cv2.imdecode(img_array, cv2.IMREAD_COLOR)
        
        return image
    
    @staticmethod
    def encode_image_base64(image: np.ndarray, format: str = 'jpg') -> str:
        """Encode numpy image to base64."""
        _, buffer = cv2.imencode(f'.{format}', image)
        img_b64 = base64.b64encode(buffer).decode('utf-8')
        return f"data:image/{format};base64,{img_b64}"


# Flask example
def create_flask_app(model, tracker=None, class_names=None):
    """Create Flask app with Eye detection endpoint.
    
    Example:
        >>> from flask import Flask
        >>> from ultralytics import YOLO
        >>> import eye
        >>> 
        >>> model = YOLO("yolo11n.pt")
        >>> app = eye.web.create_flask_app(model, class_names=model.names)
        >>> app.run(host='0.0.0.0', port=5000)
    """
    try:
        from flask import Flask, request, jsonify
    except ImportError:
        raise ImportError("Flask not installed. Run: pip install flask")
    
    try:
        from flask_cors import CORS
        _has_cors = True
    except ImportError:
        _has_cors = False
    
    app = Flask(__name__)
    if _has_cors:
        CORS(app)
    
    api = WebAPI(model, tracker, class_names)
    
    @app.route('/detect', methods=['POST'])
    def detect():
        """Detection endpoint."""
        data = request.json
        image_b64 = data.get('image')
        conf_threshold = data.get('confidence', 0.5)
        frame_id = data.get('frame_id', 0)
        
        result = api.process_base64(image_b64, conf_threshold, frame_id)
        return jsonify(result)
    
    @app.route('/health', methods=['GET'])
    def health():
        """Health check endpoint."""
        return jsonify({'status': 'healthy'})
    
    return app


# FastAPI example
def create_fastapi_app(model, tracker=None, class_names=None):
    """Create FastAPI app with Eye detection endpoint.
    
    Example:
        >>> from fastapi import FastAPI
        >>> from ultralytics import YOLO
        >>> import eye
        >>> 
        >>> model = YOLO("yolo11n.pt")
        >>> app = eye.web.create_fastapi_app(model, class_names=model.names)
        >>> # Run with: uvicorn main:app --host 0.0.0.0 --port 8000
    """
    try:
        from fastapi import FastAPI
        from fastapi.middleware.cors import CORSMiddleware
        from pydantic import BaseModel
    except ImportError:
        raise ImportError("FastAPI not installed. Run: pip install fastapi uvicorn")
    
    app = FastAPI(title="Eye Detection API")
    
    # Enable CORS
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )
    
    api = WebAPI(model, tracker, class_names)
    
    class DetectionRequest(BaseModel):
        image: str
        confidence: float = 0.5
        frame_id: int = 0
    
    @app.post("/detect")
    async def detect(request: DetectionRequest):
        """Detection endpoint."""
        result = api.process_base64(request.image, request.confidence, request.frame_id)
        return result
    
    @app.get("/health")
    async def health():
        """Health check endpoint."""
        return {"status": "healthy"}
    
    return app
