from datetime import datetime, timedelta
from bson import json_util, ObjectId
import json
from aiokafka import AIOKafkaConsumer
from app.db import database
from app.utils.connections import connected_clients

async def consume_tracking_data():
    consumer = AIOKafkaConsumer(
        "vehicle_tracking",
        bootstrap_servers="localhost:9092",
        group_id="tracking-group"
    )
    await consumer.start()

    mongo_gen = database.get_mongo_db()
    mongo = next(mongo_gen)

    tracking_logs = mongo["tracking_logs"]
    alert_logs = mongo["alert_logs"]
    geofences = mongo["geofences"]
    geofence_rules = mongo["geofence_rules"]
    geofence_mappings = mongo["geofence_rule_mapping"]

    try:
        async for msg in consumer:
            data = json.loads(msg.value.decode("utf-8"))
            data["received_at"] = datetime.utcnow()
            device_id = data.get("device_id")
            coordinates = data.get("location", {}).get("coordinates", [])

            # ✅ Insert tracking log
            tracking_logs.insert_one(data)

            alerts = []

            # 1. 🔔 Check for inactivity (no update in >30 mins)
            last_entry = tracking_logs.find_one(
                {"device_id": device_id},
                sort=[("received_at", -1)]
            )

            if last_entry:
                print("🟡 Last entry found:")
                print(last_entry)

                last_time = last_entry["received_at"]
                current_time = datetime.utcnow()
                gap = current_time - last_time

                # Check if it was inactive for >30 minutes
                if gap > timedelta(minutes=30):
                    # 1. Log inactivity alert
                    alert = {
                        "device_id": device_id,
                        "type": "inactivity",
                        "message": f"Device {device_id} inactive for over 30 minutes.",
                        "triggered_at": current_time
                    }
                    alert_logs.insert_one(alert)
                    alerts.append(alert)

                    # 2. Also log "back online" alert
                    online_alert = {
                        "device_id": device_id,
                        "type": "recovery",
                        "message": f"Device {device_id} is back online after {gap.seconds // 60} minutes of inactivity.",
                        "triggered_at": current_time
                    }
                    alert_logs.insert_one(online_alert)
                    alerts.append(online_alert)

            # 2. 🧠 Check for geofence + rules
            mappings = list(geofence_mappings.find({"assigned_entity_id": device_id}))

            for mapping in mappings:
                geo_id = mapping.get("geofence_id")
                rule_id = mapping.get("geofence_rule_id")

                geofence = geofences.find_one({"_id": ObjectId(geo_id)})
                if not geofence or not coordinates:
                    continue

                # Check if the point is inside the geofence polygon
                from shapely.geometry import Point, Polygon
                point = Point(coordinates)
                polygon = Polygon(geofence["loc"]["coordinates"][0])
                inside = polygon.contains(point)

                # Trigger event check
                if mapping.get("trigger_events") == "exit" and not inside:
                    rule = None
                    if rule_id:
                        rule = geofence_rules.find_one({"_id": ObjectId(rule_id)})

                    alert_msg = rule.get("alert_message") if rule else f"Device {device_id} exited geofence."
                    alert = {
                        "device_id": device_id,
                        "type": "geofence-exit",
                        "geofence": geofence["name"],
                        "message": alert_msg,
                        "triggered_at": data["received_at"]
                    }
                    alert_logs.insert_one(alert)
                    alerts.append(alert)

            print("connected_clientsconnected_clientsconnected_clients")
            alerts = {
                        "device_id": "dev123",
                        "type": "geofence-exit",
                        "geofence": "Test Zone",
                        "message": "Test Zone message",
                        "triggered_at": "2025-06-02 18:50"
                    }

            # ✅ Send Kafka message to clients
            for ws in connected_clients.copy():
                print(f"✅ Broadcasting to {len(connected_clients)} connected client(s)")
                try:
                    # Send the main tracking data
                    await ws.send_text(json.dumps(data, default=json_util.default))

                    # Send any alerts
                    print("alert")
                    print(alerts)
                    for alert in alerts:
                        print("127127")
                        print(alert)
                        await ws.send_text(json.dumps({
                            "type": "alert",
                            "message": alert.get("message", ""),
                            "device_id": alert.get("device_id"),
                            "alert_type": alert.get("type"),
                            "geofence": alert.get("geofence"),
                            "triggered_at": alert.get("triggered_at")
                        }, default=json_util.default))

                except Exception as e:
                    connected_clients.remove(ws)
                    print("❌ WebSocket error:", e)


    finally:
        await consumer.stop()
        try:
            next(mongo_gen)
        except StopIteration:
            pass
