"""
Генератор номеров документов для различных операций в inventory.
"""

from inventory.models import DocumentCounter


def generate_writeoff_document_number():
    """
    Генерирует уникальный номер документа списания.

    Формат: WO-XXXXXX (6 цифр)
    Thread-safe через DocumentCounter.

    Returns:
        str: Сгенерированный номер документа (например, WO-000001)
    """
    next_number = DocumentCounter.get_next_value('writeoff')
    return f"WO-{next_number:06d}"


def generate_transfer_document_number():
    """
    Генерирует уникальный номер документа перемещения.

    Формат: MOVE-XXXXXX (6 цифр)

    Returns:
        str: Сгенерированный номер документа (например, MOVE-000001)
    """
    next_number = DocumentCounter.get_next_value('transfer')
    return f"MOVE-{next_number:06d}"


def _extract_number_from_document_number(doc_number):
    """
    Извлекает числовое значение из номера документа.
    Поддерживает оба формата: IN-0000-0003 и IN-000002.
    
    Для старого формата IN-XXXX-YYYY извлекается YYYY (последние 4 цифры).
    Для нового формата IN-XXXXXX извлекается XXXXXX (6 цифр).
    
    Args:
        doc_number: строка номера документа (например, 'IN-0000-0003' или 'IN-000002')
    
    Returns:
        int: числовое значение или 0 если не удалось распарсить
    """
    try:
        # Убираем префикс 'IN-'
        if not doc_number.startswith('IN-'):
            return 0
        
        parts = doc_number[3:].split('-')  # ['0000', '0003'] или ['000002']
        
        if len(parts) == 2:
            # Старый формат: IN-0000-0003
            # Берем последнюю часть (0003) и конвертируем в число
            return int(parts[1])
        elif len(parts) == 1:
            # Новый формат: IN-000002
            return int(parts[0])
        else:
            return 0
    except (ValueError, IndexError):
        return 0


def _initialize_incoming_counter_if_needed():
    """
    Инициализирует DocumentCounter для 'incoming' максимальным номером
    из существующих документов, если счетчик еще не инициализирован.
    
    Вызывается только если счетчик равен 0 (не инициализирован).
    Thread-safe через select_for_update.
    """
    from inventory.models import IncomingDocument
    from django.db import transaction

    # Быстрая проверка без блокировки - если счетчик существует и > 0, выходим
    if DocumentCounter.objects.filter(
        counter_type='incoming',
        current_value__gt=0
    ).exists():
        return

    # Только если счетчик не инициализирован - делаем полную проверку с блокировкой
    with transaction.atomic():
        counter = DocumentCounter.objects.select_for_update().filter(
            counter_type='incoming'
        ).first()

        # Двойная проверка: возможно другой поток уже инициализировал
        if counter and counter.current_value > 0:
            return

        # Собираем все номера документов из IncomingDocument
        all_numbers = list(IncomingDocument.objects.filter(
            document_number__startswith='IN-'
        ).values_list('document_number', flat=True))
        
        if all_numbers:
            # Извлекаем максимальный номер из всех форматов
            max_number = max(_extract_number_from_document_number(num) for num in all_numbers)
        else:
            # Нет существующих документов - начинаем с 0
            max_number = 0
        
        # Создаем или обновляем счетчик
        if not counter:
            DocumentCounter.objects.create(
                counter_type='incoming',
                current_value=max_number
            )
        elif counter.current_value == 0:
            counter.current_value = max_number
            counter.save(update_fields=['current_value'])


def generate_incoming_document_number():
    """
    Генерирует уникальный номер документа поступления.

    Формат: IN-XXXXXX (6 цифр) - унифицирован с WO-000001 и MOVE-000001.
    Thread-safe через DocumentCounter.

    При первом использовании автоматически инициализирует DocumentCounter
    максимальным номером из существующих документов IncomingDocument.

    Returns:
        str: Сгенерированный номер документа (например, IN-000001)
    """
    # Инициализируем счетчик, если нужно (только если он равен 0)
    _initialize_incoming_counter_if_needed()
    
    # Используем стандартный метод, как и другие функции
    next_number = DocumentCounter.get_next_value('incoming')
    return f"IN-{next_number:06d}"


def generate_inventory_document_number():
    """
    Генерирует уникальный номер документа инвентаризации.

    Формат: INV-XXXXXX (6 цифр)
    Thread-safe через DocumentCounter.

    Returns:
        str: Сгенерированный номер документа (например, INV-000001)
    """
    next_number = DocumentCounter.get_next_value('inventory')
    return f"INV-{next_number:06d}"