import os
import sys
import json
import asyncio
import sqlite3
from datetime import datetime

# Enforce standard package checking to guide the user on dependency setup
try:
    import websockets
except ImportError:
    print("\n[DEPENDENCY NOTICE] The high-performance 'websockets' library is required for this broker gateway.")
    print(" -> ACTION: Run 'pip3 install websockets' in your terminal to initialize the package networking components.\n")
    sys.exit(1)

class ConsigliereWebSocketServer:
    def __init__(self, host="127.0.0.1", port=8765, db_filepath="/Users/bpa/ForesixaQuant/qzotic_pure_sandbox.db"):
        """Initializes asynchronous event loops, binding the server directly to your local port mappings."""
        self.host = host
        self.port = port
        self.db_filepath = db_filepath
        self.connected_clients = set()

    async def register_client_handshake(self, websocket):
        """Registers incoming mobile or web application connection instances safely in memory cache."""
        self.connected_clients.add(websocket)
        timestamp = datetime.now().strftime("%H:%M:%S")
        print(f"[{timestamp}] [HANDSHAKE SUCCESS] Mobile dashboard client authenticated and linked to stream channel.")
        try:
            # Keep connection open to intercept inbound dashboard button click events in real-time
            async for message in websocket:
                try:
                    payload = json.loads(message)
                    print(f"[{datetime.now().strftime('%H:%M:%S')}] [DASHBOARD INGRESS] Button Command Received: {payload.get('action_intent', 'UNKNOWN_EVENT')}")
                    
                    # Echo confirmation status token back to the specific mobile footprint
                    response_token = {"status": "COMMAND_RECEIVED_PROCESSED_OK", "timestamp": datetime.utcnow().isoformat() + "Z"}
                    await websocket.send(json.dumps(response_token))
                except json.JSONDecodeError:
                    print(f"[{datetime.now().strftime('%H:%M:%S')}] [WARNING] Malformed packet data frame dropped.")
        except websockets.exceptions.ConnectionClosed:
            pass
        finally:
            self.connected_clients.remove(websocket)
            print(f"[{datetime.now().strftime('%H:%M:%S')}] [DISCONNECT] Mobile application connection unlinked cleanly.")

    async def broadcast_enterprise_telemetry_event(self, data_dict: dict):
        """Broadcasts structural JSON asset summaries instantly to all connected mobile devices."""
        if not self.connected_clients:
            return
            
        message_string = json.dumps(data_dict)
        # Push event payload arrays simultaneously to prevent choose latency drops
        await asyncio.gather(*[client.send(message_string) for client in self.connected_clients])

    async def passive_database_change_loop(self, polling_interval_seconds=2):
        """Passively checks the database table for updates and auto-broadcasts changes to your screen."""
        print(f" -> [DAEMON ENROLLED] Active database observer monitoring state tables at: '{self.db_filepath}'")
        
        last_checked_timestamp = datetime.utcnow().isoformat()
        
        while True:
            if os.path.exists(self.db_filepath):
                try:
                    # Establish an isolated read-only network bridge loop to check for row metric variances
                    conn = sqlite3.connect(self.db_filepath)
                    conn.row_factory = sqlite3.Row
                    cursor = conn.cursor()
                    
                    cursor.execute("""
                        SELECT project_name, industry_vertical, lifecycle_state, supervisor_deadline, days_lagging_count 
                        FROM enterprise_portfolio 
                        WHERE logged_at > ?;
                    """, (last_checked_timestamp,))
                    
                    updated_rows = cursor.fetchall()
                    
                    if updated_rows:
                        last_checked_timestamp = datetime.utcnow().isoformat()
                        for row in updated_rows:
                            event_payload = {
                                "event_stream": "CONSIGLIERE_FLEET_UPDATE",
                                "payload_timestamp": datetime.utcnow().isoformat() + "Z",
                                "data": {
                                    "project_name": row["project_name"],
                                    "vertical": row["industry_vertical"],
                                    "state": row["lifecycle_state"],
                                    "deadline": row["supervisor_deadline"],
                                    "days_lagging": int(row["days_lagging_count"])
                                }
                            }
                            print(f"[{datetime.now().strftime('%H:%M:%S')}] [BROADCAST] Pushing state change for [{row['project_name']}] down to app pipeline.")
                            await self.broadcast_enterprise_telemetry_event(event_payload)
                            
                    conn.close()
                except sqlite3.OperationalError:
                    # Safely absorb standard operational database locks if supervisors write updates concurrently
                    pass
                except Exception as e:
                    print(f" -> [OBSERVER ERROR] Database monitoring thread variance: {str(e)}")
            
            await asyncio.sleep(polling_interval_seconds)

    async def start_server_engine_runtime(self):
        print("\n============================================================")
        print("     QZOTIC CONSIGLIERE: REAL-TIME WEBSOCKET ROUTING SERVER ")
        print("============================================================")
        print("[INFO] Initialize Event Broker Core...")
        print(f"[INFO] Binding WebSocket Server Gateway to: ws://{self.host}:{self.port}")
        print("[INFO] Ingress Monitoring Channel Status  : ONLINE_LISTENING_ACTIVE")
        print("------------------------------------------------------------")
        
        # Start the WebSocket server and bind it to your local system loop
        async with websockets.serve(self.register_client_handshake, self.host, self.port):
            # Concurrent execution pass: runs the server alongside the passive database observer loop
            await self.passive_database_change_loop()

if __name__ == "__main__":
    server_broker = ConsigliereWebSocketServer()
    try:
        asyncio.run(server_broker.start_server_engine_runtime())
    except KeyboardInterrupt:
        print("\n[INFO] Event Broker Core safely powered down down. Exiting compliance perimeters.")
