"""
Agnostic Bridge for Multi-Language Integration

Provides a REST-like HTTP interface for non-Python subsystems (C++, ROS, Go)
to interact with the ALTRUS kernel.
"""

import json
import threading
from http.server import HTTPServer, BaseHTTPRequestHandler
from typing import Any, Dict
from altrus.core.intent.intent import Intent
from altrus.core.registry.module import Module

class AgnosticBridgeHandler(BaseHTTPRequestHandler):
    kernel = None

    def _set_headers(self, status=200):
        self.send_response(status)
        self.send_header('Content-type', 'application/json')
        self.end_headers()

    def do_GET(self):
        """Handle status queries"""
        if self.path == "/status":
            status = {
                "kernel_state": self.kernel.get_system_state().value,
                "modules": [m.to_dict() for m in self.kernel.registry.list_modules()],
                "active_intent": self.kernel.intent_engine.current_intent.to_dict() if self.kernel.intent_engine.current_intent else None
            }
            self._set_headers()
            self.wfile.write(json.dumps(status).encode())
        else:
            self._set_headers(404)
            self.wfile.write(json.dumps({"error": "Not Found"}).encode())

    def do_POST(self):
        """Handle intent submission and registration"""
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length)

        try:
            data = json.loads(post_data.decode('utf-8'))
        except json.JSONDecodeError:
            self._set_headers(400)
            self.wfile.write(json.dumps({"error": "Invalid JSON"}).encode())
            return

        if self.path == "/intent":
            self._handle_intent(data)
        elif self.path == "/register":
            self._handle_registration(data)
        elif self.path == "/heartbeat":
            self._handle_heartbeat(data)
        elif self.path == "/intent_result":
            self._handle_intent_result(data)
        elif self.path == "/sensor_data":
            self._handle_sensor_data(data)
        elif self.path == "/sensor_error":
            self._handle_sensor_error(data)
        else:
            self._set_headers(404)
            self.wfile.write(json.dumps({"error": "Endpoint not found"}).encode())

    def _handle_intent(self, data: Dict[str, Any]):
        try:
            intent = Intent.from_dict(data)
            self.kernel.intent_engine.submit_intent(intent)
            self._set_headers(201)
            self.wfile.write(json.dumps({"status": "Intent submitted", "intent_id": intent.intent_id}).encode())
        except Exception as e:
            self._set_headers(400)
            self.wfile.write(json.dumps({"error": str(e)}).encode())

    def _handle_registration(self, data: Dict[str, Any]):
        try:
            module = Module.from_dict(data)
            self.kernel.registry.register(module)
            self.kernel.registry.activate(module.module_id)
            self._set_headers(201)
            self.wfile.write(json.dumps({"status": "Module registered and activated"}).encode())
        except Exception as e:
            self._set_headers(400)
            self.wfile.write(json.dumps({"error": str(e)}).encode())

    def _handle_heartbeat(self, data: Dict[str, Any]):
        try:
            module_id = data.get("module_id")
            if not module_id:
                raise ValueError("module_id is required")

            self.kernel.registry.heartbeat(module_id)
            self._set_headers(200)
            self.wfile.write(json.dumps({"status": "Heartbeat received"}).encode())
        except Exception as e:
            self._set_headers(400)
            self.wfile.write(json.dumps({"error": str(e)}).encode())

    def _handle_intent_result(self, data: Dict[str, Any]):
        try:
            intent_id = data.get("intent_id")
            result = data.get("result")
            details = data.get("details", "")

            if not intent_id or not result:
                raise ValueError("intent_id and result are required")

            if result == "SUCCESS":
                self.kernel.intent_engine.mark_intent_completed(intent_id)
            elif result == "FAILURE":
                self.kernel.intent_engine.mark_intent_failed(intent_id, reason=details)
            else:
                raise ValueError(f"Invalid result: {result}")

            self._set_headers(200)
            self.wfile.write(json.dumps({"status": "Result recorded"}).encode())
        except Exception as e:
            self._set_headers(400)
            self.wfile.write(json.dumps({"error": str(e)}).encode())

    def _handle_sensor_data(self, data: Dict[str, Any]):
        try:
            sensor_id = data.get("sensor_id", "unknown_sensor")
            self.kernel.ledger.log_event(
                event_type="SENSOR_DATA_RECEIVED",
                actor_type="SENSOR",
                actor_id=sensor_id,
                data=data
            )
            self._set_headers(200)
            self.wfile.write(json.dumps({"status": "Sensor data recorded"}).encode())
        except Exception as e:
            self._set_headers(400)
            self.wfile.write(json.dumps({"error": str(e)}).encode())

    def _handle_sensor_error(self, data: Dict[str, Any]):
        try:
            sensor_id = data.get("sensor_id", "unknown_sensor")
            self.kernel.ledger.log_event(
                event_type="SENSOR_FAULT",
                actor_type="SENSOR",
                actor_id=sensor_id,
                data=data
            )
            self._set_headers(200)
            self.wfile.write(json.dumps({"status": "Sensor error recorded"}).encode())
        except Exception as e:
            self._set_headers(400)
            self.wfile.write(json.dumps({"error": str(e)}).encode())

class ReusableHTTPServer(HTTPServer):
    allow_reuse_address = True

class AgnosticBridge:
    """
    HTTP Bridge for ALTRUS kernel.
    Allows external processes to submit intents and register modules via JSON/HTTP.
    """
    def __init__(self, kernel, port: int = 5000):
        self.kernel = kernel
        self.port = port
        self.server: Optional[HTTPServer] = None
        self._thread: Optional[threading.Thread] = None

    def start(self):
        AgnosticBridgeHandler.kernel = self.kernel

        def serve():
            try:
                self.server = ReusableHTTPServer(('0.0.0.0', self.port), AgnosticBridgeHandler)
            except OSError:
                # If port is in use, bind to any free port
                self.server = ReusableHTTPServer(('0.0.0.0', 0), AgnosticBridgeHandler)
                self.port = self.server.server_address[1]

            print(f"🌐 Agnostic Bridge started on port {self.port}")
            self.server.serve_forever()

        self._thread = threading.Thread(target=serve, daemon=True)
        self._thread.start()


    def stop(self):
        if self.server:
            self.server.shutdown()
            self.server.server_close()
            print("🌐 Agnostic Bridge stopped")
