import datetime
import json
import os
import django
import sys
from django.utils import timezone

from confluent_kafka import Consumer
from django.db.models import Prefetch
# if want access django, must put this 2
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "backend.settings")
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
django.setup()

from api.models import KafkaLog, TtActivity, TtSetting, TtActivityStaff, TtStaffResourceMap, TtStaff, TtLocation, \
    TtActivityLocation, TtLocationResourceMap
from django.conf import settings
from api.utils import log_critical_error, get_exception_detail, bitwise_calculator_from_string, bulk_sync_to_redis, \
    push_websocket_notification
from backend.redis_client import redis_client
from api.translation import __

host = settings.KAFKA_CONFIG["HOST"]
port = str(settings.KAFKA_CONFIG["PORT"])
conf = {
    'bootstrap.servers': host + ":" + port,
    'group.id': 'ttapi-worker-1', # 1 group id only can poll 1 time of same msg data, so if this group_id already poll request A 1 time, next time restart if using earliest also wont get again request A
    'auto.offset.reset': 'earliest' #'earliest': consume from beginning, 'latest': consume only new messages, 'none': error if no offset, mostly in manual poll scenario will used
}

websocket_host = settings.WEBSOCKET_CONFIG["HOST"]
websocket_port = str(settings.WEBSOCKET_CONFIG["PORT"])
websocket_endpoint = str(settings.WEBSOCKET_CONFIG["PRESCHEDULE_RESPONSE_ENDPOINT"])
websocket_url = websocket_host + ":" + websocket_port + "/" + websocket_endpoint

consumer = Consumer(conf)
topic = settings.KAFKA_CONFIG["PRESCHEDULE_RESPONSE_TOPIC"]
timeout = settings.KAFKA_CONFIG["TIMEOUT"]
# topic = "test-topic"
consumer.subscribe([topic])

setting_params = {
    "minute_per_slot",
    "slot_per_week",
    "slot_per_day"
}
settings = TtSetting.get_multiple_setting(setting_params)
slot_per_week = int(settings["slot_per_week"])
slot_per_day = int(settings["slot_per_day"])
minute_per_slot = int(settings["minute_per_slot"])

while True:
    # poll(1.0) means 1 second timeout, so everytime call poll within 1 second no data, will have another poll call again
    # if put poll() without timeout, will keep wait until got response only call another poll. (NOT RECOMMEND NO TIMEOUT, WILL CAUSE BUSY LOOP)
    try:
        msg = consumer.poll(1.0)
        # print(msg)
        if msg is None:
            continue
        if msg.error():
            # print("Error:", msg.error())
            continue
        # convert to string first only convert become list
        msg_str = msg.value().decode()
        # print("Received:", msg.value().decode())
        try:
            # print(datetime.datetime.now())
            response_data = json.loads(msg_str)
            kafka_log = KafkaLog.update_response(topic, response_data)
            if timezone.now() > kafka_log.request_at + datetime.timedelta(seconds=timeout):
                continue
            """
            2026-01-13 exact response
            {
                "session_id": "dev",
                "request_id": "ef4b11ff-9941-493e-8945-d12ed4d6b40a",
                "status": "success", 
                "schedule": "[
                    {
                        \"activity\":\"19\",
                        \"preference\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,9,9,9,0,0,0,0,0,0,0,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0]
                    }
                ]"
            }
            """
            # got kafka_log only do action, else need double check why no request but receive response
            if response_data['status'] == "success" and kafka_log:
                # 2025-12-12 the exact response for the "schedule" is json_encode 1 more time, so need decode again for the "schedule"
                schedule = json.loads(response_data['schedule'])
                activity_ids = [int(item["activity"]) for item in schedule]

                # activities = (
                #     TtActivity.objects.filter(id__in=activity_ids)
                #     .select_related("activity_template", "department", "academic_term", "module", "week_pattern",
                #                     "activity_type", "zone", "availability", "start_preference", "usage_preference")
                #     .prefetch_related("staff","location")
                # )
                # format the data need put to FE

                # push websocket for FE
                if kafka_log.socket_id:
                    push_websocket_notification(websocket_url, schedule,kafka_log.socket_id)

        except json.JSONDecodeError:
            # if cant load back to array, then end of the function, wait next msg
            continue
    except Exception as e:
        e_details = get_exception_detail(e)
        log_critical_error(user_id=None, descr=e_details['descr'], url=e_details['url'], trace=e_details['trace'])
        continue

    # print(datetime.datetime.now())

