import streamlit as st
import io
from PIL import Image, ImageOps

# Пытаемся импортировать библиотеку, но не прерываем работу глобально при ошибке
try:
    from pystrich.datamatrix import DataMatrixEncoder, DataMatrixData, FNC1
    HAS_PYSTRICH = True
except ImportError:
    HAS_PYSTRICH = False


# ==========================================
# 1. ГЛОБАЛЬНАЯ ЗОНА (Строго без UI-виджетов!)
# ==========================================
DPI = 203
LABEL_SIZE_MM = 20
TOTAL_DOTS = int((LABEL_SIZE_MM / 25.4) * DPI)  # 160 пикселей

def parse_cz_mark_to_parts(raw_string):
    """
    1. Исправляет русскую раскладку (если сканер был на RU).
    2. Разделяет марку на логические блоки для правильной вставки GS1 разделителей.
    """
    layout_map = str.maketrans(
        "йцукенгшщзхъфывапролджэячсмитьбюЁЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ",
        "qwertyuiop[]asdfghjkl;'zxcvbnm,.`QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>"
    )
    raw_string = raw_string.translate(layout_map)
    raw_string = raw_string.replace('<GS>', '\x1d').replace('[GS]', '\x1d')
    
    # Если разделители уже есть, бьем по ним
    if '\x1d' in raw_string or '\u001d' in raw_string:
        return raw_string.replace('\u001d', '\x1d').split('\x1d')
        
    if len(raw_string) < 16:
        return [raw_string]
        
    parts = []
    current_part = raw_string[:16] # 01 + GTIN (всегда 16 символов)
    remaining = raw_string[16:]
    
    i = 0
    while i < len(remaining):
        if i + 2 <= len(remaining):
            pair = remaining[i:i+2]
            # Ставим разделители перед криптохвостами 91, 92, 93
            if pair in ("91", "92", "93"):
                parts.append(current_part)
                current_part = pair
                i += 2
                continue
        
        current_part += remaining[i]
        i += 1
        
    parts.append(current_part)
    return parts

def create_duplicate_label(raw_dm_string):
    # 1. Получаем блоки (GTIN, серийник, ключи), которые нужно склеить
    parts = parse_cz_mark_to_parts(raw_dm_string)
    
    # 2. Формируем правильную структуру GS1 DataMatrix
    # Марка всегда должна начинаться со спецсимвола FNC1
    args = [FNC1]
    for i, part in enumerate(parts):
        args.append(part)
        if i < len(parts) - 1:
            args.append(FNC1) # Вставляем аппаратный разделитель вместо обычного текста
            
    # Собираем данные в payload
    payload = DataMatrixData(*args, encoding='ascii')
    encoder = DataMatrixEncoder(payload)
    
    # Генерируем картинку штрихкода
    dm_img = encoder.get_pilimage()
    
    # 3. Подготавливаем холст 160x160
    img = Image.new('RGB', (TOTAL_DOTS, TOTAL_DOTS), 'white')
    PAD = 16 # "Тихая зона", чтобы камера телефона легко ловила фокус
    
    # 4. Обрезаем поля по умолчанию и масштабируем до нужного размера
    gray = dm_img.convert('L')
    inverted = ImageOps.invert(gray)
    bbox = inverted.getbbox()
    if bbox: 
        dm_img = dm_img.crop(bbox)
        
    # Вычисляем размер одного пикселя внутри штрихкода
    pixels = dm_img.convert('L').load()
    module_size = next((x for x in range(1, dm_img.width) if pixels[x, 0] != pixels[0, 0]), 1)
            
    modules_x = dm_img.width // module_size
    modules_y = dm_img.height // module_size
    small_dm = dm_img.resize((modules_x, modules_y), Image.NEAREST)
    
    max_dm_space = TOTAL_DOTS - (PAD * 2)
    scale = max_dm_space // modules_x
    if scale < 1: scale = 1
    
    final_dm_size = modules_x * scale
    final_dm = small_dm.resize((final_dm_size, final_dm_size), Image.NEAREST)
    
    # 5. Центрируем DataMatrix ровно посередине
    x_pos = (TOTAL_DOTS - final_dm_size) // 2
    y_pos = (TOTAL_DOTS - final_dm_size) // 2
    img.paste(final_dm, (x_pos, y_pos))

    return img.convert('1')


# ==========================================
# 2. ОСНОВНАЯ ФУНКЦИЯ
# ==========================================
def run(plugin_info):
    
    if not HAS_PYSTRICH:
        st.error("Ошибка: библиотека pyStrich не установлена! Выполните в консоли: pip install pyStrich")
        st.stop()
        
    # --- БЛОК ВВОДА ДАННЫХ ---
    with st.container(border=True):
        st.markdown("### 📷 Ввод данных сканера")
        scanned_code = st.text_input("Отсканируйте марку:", placeholder="Введите сырую строку DataMatrix...")
        
    # --- ОСНОВНАЯ ЛОГИКА ---
    if scanned_code:
        if st.button("🚀 Создать дубликат", type="primary", use_container_width=True):
            
            with st.spinner("⏳ Генерация марки..."):
                try:
                    # Вызов чистой функции обработки строго с оригинальной логикой
                    label_img = create_duplicate_label(scanned_code.strip())
                    
                    st.success("✅ Идеальный дубликат успешно создан!")
                    
                    # --- ДЕМОНСТРАЦИЯ РЕЗУЛЬТАТА ---
                    display_img = label_img.resize((label_img.width * 3, label_img.height * 3), Image.NEAREST)
                    
                    col1, col2, col3 = st.columns([1, 2, 1])
                    with col2:
                        st.image(display_img, caption="Сгенерированный дубликат марки", use_container_width=True)
                    
                    # --- ГЕНЕРАЦИЯ ФАЙЛА В ПАМЯТИ И СКАЧИВАНИЕ ---
                    output = io.BytesIO()
                    label_img.save(output, format="PNG")
                    processed_image = output.getvalue()
                    
                    st.download_button(
                        label="💾 Скачать марку (PNG)",
                        data=processed_image,
                        file_name="datamatrix_duplicate.png",
                        mime="image/png",
                        type="primary",
                        use_container_width=True
                    )
                except Exception as e:
                    st.error(f"✖ Произошла ошибка при генерации: {e}")