from apps.tags.models import Tag
from django.db import transaction

from apps.herd.models import Herd
from apps.livestock.models import LiveStock, LiveStockType
from apps.tag.models import TemporaryTags

BATCH_SIZE = 1000


class TemporaryTagsSyncService:

    @classmethod
    @transaction.atomic
    def sync_tags_to_livestock(cls):
        # Preload herds
        herds = {h.code: h for h in Herd.objects.all()}

        # Preload existing LiveStocks for speed
        live_stocks_map = {}
        for ls in LiveStock.objects.select_related('herd', 'type').all():
            key = (ls.herd.code, ls.birthdate.date() if ls.birthdate else None, ls.gender)
            live_stocks_map.setdefault(key, []).append(ls)

        # Preload LiveStockType
        gender_type_map = {t.name.lower(): t for t in LiveStockType.objects.all()}

        # Preload existing tags
        existing_tags = {t.tag_code: t for t in Tag.objects.all()}

        new_herds = []
        new_livestock = []
        new_tags = []

        for temp in TemporaryTags.objects.iterator():
            herd = herds.get(temp.herd_code)
            if not herd:
                herd = Herd(code=temp.herd_code, name=temp.herd_code, province_id=30)
                new_herds.append(herd)
                herds[temp.herd_code] = herd

            # Gender mapping
            gender_lower = temp.gender.lower() if temp.gender else 'male'
            ls_type = gender_type_map.get(gender_lower)

            birthdate = temp.birthdate  # convert to datetime if needed

            key = (herd.code, birthdate, ls_type.id if ls_type else None)
            live_stock_list = live_stocks_map.get(key, [])

            if live_stock_list:
                # دام موجود است، فقط Tag ایجاد می‌کنیم
                ls = live_stock_list[0]  # می‌توانیم چندتا هم داشته باشیم
            else:
                # دام جدید ایجاد می‌کنیم
                ls = LiveStock(
                    herd=herd,
                    type=ls_type,
                    gender=1 if gender_lower == 'male' else 2,
                    birthdate=birthdate
                )
                new_livestock.append(ls)
                live_stocks_map[key] = [ls]

            # ----------------------
            # Tag برای هر دام
            # ----------------------
            if temp.serial:  # یا temp.tag_code
                tag_code = f"{temp.country_code}{temp.static_code}{temp.ownership_code}{temp.species_code}{temp.serial}"
                if tag_code not in existing_tags:
                    tag = Tag(
                        serial=temp.serial,
                        country_code=getattr(temp, 'country_code', 364),
                        static_code=getattr(temp, 'static_code', 0),
                        ownership_code=getattr(temp, 'ownership_code', 0),
                        species_code=getattr(temp, 'species_code', 0),
                        tag_code=tag_code,
                        status='F'
                    )
                    new_tags.append(tag)
                    existing_tags[tag_code] = tag
                else:
                    tag = existing_tags[tag_code]

                # Assign Tag to LiveStock
                ls.tag = tag

            # Batch insert
            if len(new_livestock) >= BATCH_SIZE:
                cls._bulk_insert(new_herds, new_livestock, new_tags)
                new_herds.clear()
                new_livestock.clear()
                new_tags.clear()

        # insert remaining
        cls._bulk_insert(new_herds, new_livestock, new_tags)

    @staticmethod
    def _bulk_insert(herds, livestock, tags):
        if herds:
            Herd.objects.bulk_create(herds, ignore_conflicts=True, batch_size=BATCH_SIZE)
        if tags:
            Tag.objects.bulk_create(tags, ignore_conflicts=True, batch_size=BATCH_SIZE)
        if livestock:
            LiveStock.objects.bulk_create(livestock, ignore_conflicts=True, batch_size=BATCH_SIZE)
