from datetime import datetime, date, time
from django.core.management.base import BaseCommand
from django.forms import model_to_dict

from api.models import TtStaff, TtLocation, TtStudentSet, TtActivityTemplate, TtActivity, TtModule, TtWeekPattern, \
    TtWeek, TtAcademicTerm, TtWeekPatternWeek
from api.utils import convert_to_redis_week, bulk_sync_to_redis, get_missing_code_from_db
from backend.kafka import send_request
from backend.redis_client import redis_client

class Command(BaseCommand):
    def generate_kafka_data(self, all_data, relation_fields=None,exclude=None):
        if not all_data:
            return {}
        if relation_fields is None:
            relation_fields = []
        if exclude is None:
            exclude = []
        shared_fields = []
        exclude.extend(["resource_map", "created_by", "updated_by"])
        for data in all_data:
            format_data = model_to_dict(data,exclude=exclude)
            for key, value in format_data.items():
                if isinstance(value, (datetime, date, time)):
                    format_data[key] = value.isoformat()
            if relation_fields:
                for field in relation_fields:
                    if field == "tag":
                        format_data[field] = [tag.tag.id for tag in data.tag.all()]
                    else:
                        format_data[field] = [m2m.id for m2m in getattr(data, field).all()]
            shared_fields.append(format_data)

        return shared_fields

    def handle(self, *args, **options):
        if date.today() > date(2026, 7, 6):
            return  # do nothing
        week_1 = "2024-12-30"# first week of 2025
        week_62 = "2026-03-02"
        week_with_start_date = {
            62: "2026-03-02", 63: "2026-03-09", 64: "2026-03-16", 65: "2026-03-23",
            66: "2026-03-30", 67: "2026-04-06", 68: "2026-04-13", 69: "2026-04-20",
            70: "2026-04-27", 71: "2026-05-04", 72: "2026-05-11", 73: "2026-05-18",
            74: "2026-05-25", 75: "2026-06-01", 76: "2026-06-08", 77: "2026-06-15",
            78: "2026-06-22", 79: "2026-06-29", 80: "2026-07-06", 81: "2026-07-13",
            82: "2026-07-20", 83: "2026-07-27", 84: "2026-08-03", 85: "2026-08-10",
            86: "2026-08-17", 87: "2026-08-24", 88: "2026-08-31", 89: "2026-09-07",
            90: "2026-09-14", 91: "2026-09-21", 92: "2026-09-28", 93: "2026-10-05",
            94: "2026-10-12", 95: "2026-10-19", 96: "2026-10-26", 97: "2026-11-02",
            98: "2026-11-09", 99: "2026-11-16", 100: "2026-11-23", 101: "2026-11-30",
            102: "2026-12-07"
        }
        # academic_term_code = "2026-import"
        academic_term_code = "65"
        academic_term = TtAcademicTerm.objects.filter(code=academic_term_code).first()
        if academic_term:
            academic_term_id = academic_term.id
            weeks = TtWeek.objects.all()
            # Ensure keys are formatted exactly the same way dates are returned from the DB (str vs date objects)
            weeks_key_by_start_date = {str(w.start_date): w for w in weeks}

            to_create_string = "63/64/65/66/67/68/69/70/71/72/73/74/75/76/77/78/79/80/81/82/83/84/85/86/87/88/89/90/91/92/93/94/95/96/97/98/99/100/101/102/62,63,64,65,66,67,68,69/63,64,65,66,67,68,69/63,65,66,67,68,69/63,65,66,69/63,65,66,69,71/63,65,69/63,69/65,66/65,66,67/65,66,67,69/65,66,67,69,71/66,67/66,67,68/66,67,68,69/66,67,68,69,70/66,67,68,69,70,71/66,67,68,69,70,71,72,73,75/66,67,68,69,71,72,73,74,75/66,67,68,70/66,67,68,70,71/66,67,68,70,71,72,74/66,67,68,71/66,67,69/66,67,69,70/66,67,69,70,71/66,67,69,71/66,67,70,71,72,74/66,67,72,74/66,68,69,70/66,68,69,71/66,68,69,71,72,73,74,75/66,69/66,69,70,71/66,69,71,72,74,75,76/66,70,71,74/66,71/67,68/67,68,69/67,68,69,70/67,68,69,70,71/67,68,70/67,68,70,72,75/67,68,71,72,74,75/67,69,70/67,69,70,71/67,70/68,69/68,69,70/68,69,70,71/68,69,70,71,72,73/68,69,70,71,72,73,74,75,76,77/68,69,70,71,72,73,75/68,69,70,71,72,73,75,76,77/68,69,70,71,72,73,75,76,77,78,79,80,81,82/68,69,71/68,70/68,71/68,72,74/69,70/69,70,71/69,70,71,72/69,70,71,72,73,74,75,76/69,70,71,72,73,74,75,76,77,78,79,80/69,70,71,72,73,74,75,77,78,79,80/69,70,71,72,73,74,75,77,78,79,80,81,82,83/69,70,75/69,70,77/69,71/69,71,72,73,74/69,71,73/69,71,74,75,77,78/69,73/69,76/69,77,78/70,71/70,71,72/70,71,72,73/70,71,72,73,74,75,76,77,78,79/70,71,72,73,74,75,77,78,79,80,81,82,83/70,71,72,73,75,76,77,78,79,80,81,82/70,71,72,74/70,71,73,75,78,79/70,71,78/70,71,79/70,72/70,72,73,74,77/70,73/71,72/71,72,73/71,72,73,74/71,72,73,74,75/71,72,73,74,75,76,77/71,72,73,74,75,76,77,78,79,80,81,82,83/71,72,73,74,75,76,77,79,80,81,82/71,72,73,74,75,76,77,79,80,81,82,83,84,85/71,72,73,74,75,76,77,80,81,82,83,84,85/71,72,73,74,75,77,78,79,80,81,82,83/71,72,73,74,75,79,82,83,84,85/71,72,73,74,76,77,79,80,81,82,83,84,85/71,72,73,74,83,84,85/71,72,73,75,76,77,78,79,80,81,82/71,72,74,75,76/71,72,74,75,77/71,72,74,75,78,79,80/71,72,74,77,81/71,72,74,78/71,73/71,73,74,75,76,77,78/71,73,75,77,80,82,84/71,74/71,74,75/71,74,77,78/71,75/71,77,78/71,78/72,73/72,73,74/72,73,74,75,76,77,78/72,73,74,77,78,79,80/72,73,74,77,78,79,80,81/72,73,74,79,80/72,73,75/72,73,75,76,77,78,79,80,81,82/72,73,76/72,74/72,74,75/72,74,76,79,81,83,85/72,75/72,76/72,76,79,81,83,85/73,74/73,74,75/73,74,75,77,78/73,74,75,77,78,79,80,81,82,83/73,74,77,81/73,75,78/73,78/74,75/74,75,76,77/74,75,76,77,79,80,81,82,83,84,85/74,76,77,78,81,82/74,76,77,81,82/74,77/74,77,78/74,77,78,79,80,81,82/74,77,78,79,81,82/74,77,78,81,82/74,77,79,81,82/74,81/75,76/75,76,77,78/75,76,77,78,79,80,81,82/75,76,77,78,81,82/75,76,77,79,80,81,82/75,76,77,79,80,81,82,83,84,85/75,77/75,78/76,77/76,77,78/76,77,78,79,80,81,82/76,77,78,79,80,81,82,83,84/76,77,78,79,80,81,82,83,84,85,86,87,88,89/76,77,79,80,81,82,83,84,85/76,77,79,81,82/76,77,81/76,78/77,78/77,78,79/77,78,80,81,82/78,79/78,79,80/78,79,80,81/78,79,80,81,82/78,79,80,81,82,83/78,79,80,81,82,83,84/78,79,80,81,82,83,84,85,87,88,89,90,91,92,93,94,95/78,79,80,81,82,83,84,85,88,89,90,91,92,93,94,95/78,79,80,81,82,84/78,79,80,81,84/78,79,80,82/78,79,80,82,83/78,79,80,82,83,84/78,79,81,82/78,79,81,82,83/78,79,82,83/78,80,81,82,83/78,80,82/78,80,83/78,81,82/79,80/79,80,81/79,80,81,82/79,80,81,82,83/79,80,81,82,83,84/79,80,81,82,83,84,85/79,80,81,82,83,84,85,86/79,80,81,82,83,84,85,86,87,88/79,80,81,82,83,85/79,80,81,82,84/79,80,81,83,84/79,80,81,83,85/79,80,81,85,86/79,80,82/79,80,82,83/79,80,82,83,84/79,80,82,83,85/79,80,82,84/79,81,82,83/79,81,82,83,84/79,81,82,84/79,81,84/79,82/80,81/80,81,82/80,81,82,83/80,81,82,83,84/80,81,82,83,84,85/80,81,82,83,84,85,86/80,81,82,83,84,85,86,87,88,89/80,81,82,83,84,86/80,81,82,84/80,81,82,84,86/80,81,83,84/80,82,83/80,82,83,84/80,82,83,85/80,82,84/80,84/81,82/81,82,83/81,82,83,84/81,82,83,84,85/81,82,83,84,85,86/81,82,83,84,85,86,87,88/81,82,83,84,85,86,87,88,89/81,82,83,84,85,86,87,88,89,90,91,92/81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102/81,82,83,84,85,86,87,88,89,90,92,93/81,82,83,84,85,86,88,89/81,82,83,84,85,88,89/81,82,83,84,87,88/81,82,83,85,86,88,89/81,82,84/81,82,84,85,86/81,82,84,86/81,82,86,89/81,82,87/81,82,90/81,83,84,88,89/81,83,90/81,84/81,84,85/81,84,86,88,89/81,85,86/81,85,86,89/81,87/81,88/82,83/82,83,84/82,83,84,85/82,83,84,85,86/82,83,84,85,86,88,89/82,83,84,85,86,89,90,91,92,93/82,83,84,85,87,88/82,83,84,86,88,89/82,83,84,88/82,83,85/82,84/82,84,86,87/82,85,86/83,84/83,84,85/83,84,85,86/83,84,85,86,87/83,84,85,86,87,88/83,84,85,86,87,88,89,91,92,94/83,84,85,86,87,88,91/83,84,85,86,87,88,91,92,94,95,96/83,84,85,86,88/83,84,85,86,88,89/83,84,85,86,88,89,90,91,92,94,95,96/83,84,85,86,88,89,90,91,92,94,95,96,100/83,84,85,86,89/83,84,85,87,88,89/83,84,85,88/83,84,86/83,84,89,90/83,85/83,85,86,87/83,85,87/83,86,87,88/83,86,88/83,87/83,88/84,85/84,85,86/84,85,86,87/84,85,86,87,90,91,92,93,94,95,97/84,85,86,88,89,90/84,85,86,89,90/84,85,86,89,90,91,92,93,96/84,85,88/84,86/85,86/85,86,87/85,86,87,88/85,86,87,88,89/85,86,87,88,89,91,92/85,86,87,88,89,91,92,93,94,95,96/85,86,87,88,90,91/85,86,87,88,90,91,92/85,86,87,88,90,91,92,93/85,86,87,88,90,91,92,94/85,86,87,89,90,92,93,94,96,97/85,86,87,89,90,92,93,94,96,97,99/85,86,88/85,86,88,89/85,86,88,89,90,91,92,93,94,95,96/85,86,88,89,90,91,92,93,94,95,96,99/85,86,89/85,87,89/85,88/85,88,89/85,88,91/86,87,88/86,87,88,89,90/86,87,88,89,90,91/86,87,88,89,91,92,93,94,95,96,100,102/86,87,88,90,91,92,94,95,96/86,87,89,90,92,93,94,96,97/86,88/86,88,89/86,88,89,90,91,92,93/86,89/86,90/86,96/87,88,89,90/87,88,89,90,91,92,93,95,96,97,98,99,100,101/87,98/88,89/89,90/89,91,92/90,91/94,95,96/98,99,100"
            to_create_week_pattern = to_create_string.split("/")
            bulk_insert_week_pattern = []

            for import_week_name in to_create_week_pattern:
                # create week_pattern first, only insert week_pattern_week
                bulk_insert_week_pattern.append(
                    TtWeekPattern(
                        code=import_week_name, # use this string as code, when i do new import i direct import to this code
                        name=import_week_name,
                        academic_term_id=academic_term_id,
                        status=TtWeekPattern.STATUS_TO_CODE['active']
                    )
                )
            created_week_pattern = TtWeekPattern.objects.bulk_create(bulk_insert_week_pattern)
            bulk_create_week_pattern_week = []
            redis_week_pattern_table = "week_pattern"
            redis_data = {
                "insert": {}
            }
            for week_pattern in created_week_pattern:
                # seperate the code from "62,63,64" become [62,63,64]
                redis_week_pattern_data = {
                    "id": week_pattern.id,
                    "code": week_pattern.code,
                    "name": week_pattern.name,
                    "week": [],
                }
                week_pattern_code = week_pattern.code
                import_week = week_pattern_code.split(",")
                for val in import_week:
                    week_start_date = week_with_start_date.get(int(val))
                    selected_week = weeks_key_by_start_date.get(week_start_date)
                    bulk_create_week_pattern_week.append(
                        TtWeekPatternWeek(
                            week_pattern_id=week_pattern.id,
                            week_id=selected_week.id
                        )
                    )
                    # week display in redis is start from 0, so need to -1, cause db is start from 1
                    redis_week_pattern_data["week"].append(int(selected_week.week) - 1)
                redis_data["insert"].setdefault(redis_week_pattern_table, []).append(redis_week_pattern_data)
            TtWeekPatternWeek.objects.bulk_create(bulk_create_week_pattern_week,batch_size=2000)

            bulk_sync_to_redis(redis_client, redis_data)
            method = "week_pattern_create"
            kafka_topic = "microservices-tt"
            # just get all week pattern to send, if got duplicate will auto skip
            new_data = TtWeekPattern.objects.filter(academic_term_id=academic_term_id).prefetch_related('week','tag__tag').order_by("id")
            relation_fields = [
                "week",
                "tag"
            ]
            kafka_data = self.generate_kafka_data(new_data, relation_fields)
            kafka_request_data = {
                "session_id": "",
                "week_pattern": kafka_data,
            }
            send_request(kafka_topic, kafka_request_data, None, method)

