import os
import sys
import zipfile
import tempfile
import subprocess
import shutil
from PIL import Image
from pylibdmtx.pylibdmtx import decode
import fitz  # PyMuPDF
import time
# ==============================
# Замер времени: начало
# ==============================
start_time = time.time()
# ==============================
# Настройки
# ==============================
# Папка, где находится скрипт
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) if getattr(sys, 'frozen', False) else os.path.dirname(os.path.abspath(sys.argv[0]))
os.chdir(SCRIPT_DIR)
# Параметры изображения
DPI_PDF = 300  # DPI для PDF
DPI_EPS = 600  # DPI для EPS (маленькие метки)
TARGET_WIDTH_MM = 1.63
TARGET_HEIGHT_MM = 1.63
WIDTH_PX = int(TARGET_WIDTH_MM * DPI_EPS / 25.4)
HEIGHT_PX = int(TARGET_HEIGHT_MM * DPI_EPS / 25.4)
TARGET_WIDTH_MM_PDF = 15
TARGET_HEIGHT_MM_PDF = 15
WIDTH_PX_PDF = int(TARGET_WIDTH_MM_PDF * DPI_PDF / 25.4)
HEIGHT_PX_PDF = int(TARGET_HEIGHT_MM_PDF * DPI_PDF / 25.4)
# Временные папки
TEMP_EXTRACT_ROOT = os.path.join(SCRIPT_DIR, "dm_zip")
TEMP_CONVERT_DIR = os.path.join(SCRIPT_DIR, "temp_converted")
OUTPUT_FILE = "dm_codes.txt"
# Добавлять GS (0x1D) в начало?
FORCE_START_WITH_GS = True
# Удалять временные папки?
CLEAN_UP_TEMP = True
# ==============================
# Проверка Ghostscript (для EPS)
# ==============================
print("Проверка Ghostscript...")
try:
    result = subprocess.run(["gswin64c", "--version"], capture_output=True, text=True)
    if result.returncode == 0:
        print(f"Ghostscript: {result.stdout.strip()}")
    else:
        raise Exception("Код возврата не 0")
except Exception as e:
    print(f"Ghostscript не установлен: {e}")
    print("Скачайте с: https://github.com/ArtifexSoftware/ghostpdl-downloads/releases")
    input("Нажмите Enter для выхода...")
    exit()
# Создаём временную папку
os.makedirs(TEMP_CONVERT_DIR, exist_ok=True)
# ==============================
# Сбор файлов в текущей папке
# ==============================
zip_files = []
pdf_files = []
eps_files = []
for fname in os.listdir(SCRIPT_DIR):
    fpath = os.path.join(SCRIPT_DIR, fname)
    if os.path.isfile(fpath):
        lower = fname.lower()
        if lower.endswith(".zip"):
            zip_files.append(fpath)
        elif lower.endswith(".pdf"):
            pdf_files.append(fpath)
        elif lower.endswith(".eps"):
            eps_files.append(fpath)
print(f"ZIP: {len(zip_files)} | PDF: {len(pdf_files)} | EPS: {len(eps_files)}")
# ==============================
# Список для всех кодов
# ==============================
all_codes = []
# ==============================
# Функция: обработка изображения
# ==============================
def process_image(img):
    codes = []
    try:
        decoded_objects = decode(img)
        for obj in decoded_objects:
            raw_data = obj.data
            if raw_data.startswith(b'\x1d'):
                final_data = raw_data
            else:
                final_data = b'\x1d' + raw_data if FORCE_START_WITH_GS else raw_data
            codes.append(final_data)
    except Exception as e:
        print(f" Ошибка декодирования: {e}")
    return codes
# ==============================
# 1. Обработка ZIP-архивов
# ==============================
for zip_path in zip_files:
    zip_name = os.path.basename(zip_path)
    extract_dir = os.path.join(TEMP_EXTRACT_ROOT, os.path.splitext(zip_name)[0])
    os.makedirs(extract_dir, exist_ok=True)
    print(f"\nРаспаковка: {zip_name}")
    try:
        with zipfile.ZipFile(zip_path, 'r') as z:
            z.extractall(extract_dir)
        print(f" Архив распакован")
    except Exception as e:
        print(f" Ошибка распаковки: {e}")
        continue
    for root, _, files in os.walk(extract_dir):
        for fname in files:
            fpath = os.path.join(root, fname)
            lower = fname.lower()
            try:
                if lower.endswith(".pdf"):
                    print(f" PDF из ZIP: {fname}")
                    doc = fitz.open(fpath)
                    for page_num in range(len(doc)):
                        mat = fitz.Matrix(DPI_PDF / 72, DPI_PDF / 72)  # Масштаб по DPI
                        pix = doc[page_num].get_pixmap(matrix=mat)
                        img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
                        img = img.convert('L')  # Grayscale
                        #img = img.resize((WIDTH_PX_PDF, HEIGHT_PX_PDF), Image.LANCZOS)
                        all_codes.extend(process_image(img))
                    doc.close()
                elif lower.endswith(".eps"):
                    print(f" EPS из ZIP: {fname}")
                    temp_png = os.path.join(TEMP_CONVERT_DIR, f"zip_{fname}.png")                  
                    gs_cmd = [
                        "gswin64c", "-dBATCH", "-dNOPAUSE", "-dSAFER",
                        f"-r{DPI_EPS}", "-sDEVICE=pnggray",
                        f"-dDEVICEWIDTHPOINTS={WIDTH_PX}", f"-dDEVICEHEIGHTPOINTS={HEIGHT_PX}",
                        "-dPDFFitPage", "-dTextAlphaBits=1", "-dGraphicsAlphaBits=1",
                        f"-sOutputFile={temp_png}", fpath
                    ]
 
                    res = subprocess.run(gs_cmd, capture_output=True, text=True, encoding='utf-8')
                    if res.returncode != 0:
                        print(f" GS ошибка: {res.stderr[:100]}...")
                    else:
                        img = Image.open(temp_png).convert('L')
                        all_codes.extend(process_image(img))
            except Exception as e:
                print(f" Ошибка: {e}")
# ==============================
# 2. Обработка PDF и EPS напрямую
# ==============================
for fpath in pdf_files + eps_files:
    fname = os.path.basename(fpath)
    print(f"Прямой файл: {fname}")
    try:
        if fname.lower().endswith(".pdf"):
            doc = fitz.open(fpath)
            for page_num in range(len(doc)):
                mat = fitz.Matrix(DPI_PDF / 72, DPI_PDF / 72)
                pix = doc[page_num].get_pixmap(matrix=mat)
                img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
                img = img.convert('L')
                #img = img.resize((WIDTH_PX_PDF, HEIGHT_PX_PDF), Image.LANCZOS)
                all_codes.extend(process_image(img))
            doc.close()
        elif fname.lower().endswith(".eps"):
            temp_png = os.path.join(TEMP_CONVERT_DIR, f"direct_{fname}.png")
            gs_cmd = [
                        "gswin64c", "-dBATCH", "-dNOPAUSE", "-dSAFER",
                        f"-r{DPI_EPS}", "-sDEVICE=pnggray",
                        f"-dDEVICEWIDTHPOINTS={WIDTH_PX}", f"-dDEVICEHEIGHTPOINTS={HEIGHT_PX}",
                        "-dPDFFitPage", "-dTextAlphaBits=1", "-dGraphicsAlphaBits=1",
                        f"-sOutputFile={temp_png}", fpath
            ]
            res = subprocess.run(gs_cmd, capture_output=True, text=True, encoding='utf-8')
            if res.returncode != 0:
                print(f" GS ошибка: {res.stderr[:100]}...")
            else:
                img = Image.open(temp_png).convert('L')
                all_codes.extend(process_image(img))
    except Exception as e:
        print(f" Ошибка: {e}")
# ==============================
# Сохранение всех кодов
# ==============================
with open(OUTPUT_FILE, "wb") as f:
    for code in all_codes:
        f.write(code + b'\n')
print(f"\nГотово!")
print(f"ZIP: {len(zip_files)} | PDF/EPS: {len(pdf_files) + len(eps_files)}")
print(f"Всего найдено кодов: {len(all_codes)}")
print(f"Результат: {OUTPUT_FILE}")
# ==============================
# Удаление временных папок
# ==============================
if CLEAN_UP_TEMP:
    print("\nУдаление временных папок...")
    try:
        if os.path.exists(TEMP_CONVERT_DIR):
            shutil.rmtree(TEMP_CONVERT_DIR, ignore_errors=True)
            print(f" Удалено: {TEMP_CONVERT_DIR}")
    except Exception as e:
        print(f" Ошибка удаления {TEMP_CONVERT_DIR}: {e}")
    try:
        if os.path.exists(TEMP_EXTRACT_ROOT):
            shutil.rmtree(TEMP_EXTRACT_ROOT, ignore_errors=True)
            print(f" Удалено: {TEMP_EXTRACT_ROOT}")
    except Exception as e:
        print(f" Ошибка удаления {TEMP_EXTRACT_ROOT}: {e}")
# ==============================
# Время выполнения
# ==============================
end_time = time.time()
total_time = end_time - start_time
hours, rem = divmod(total_time, 3600)
minutes, seconds = divmod(rem, 60)
time_str = "{:02}:{:02}:{:02}".format(int(hours), int(minutes), int(seconds))
print(f"\n⏱ Время работы скрипта: {time_str}")
# Завершение
input("\nНажмите Enter для выхода...")