import subprocess
import time
from pathlib import Path
import zipfile
import zstandard as zstd

# ============================================================
# CONFIG
# ============================================================

SRC = Path(r"D:\medicusbackup\MEDICUS_2026-01-24_17-07-44.fbk")
BASE = SRC.with_suffix("")
CHUNK = 8 * 1024 * 1024  # 8 MB

SEVENZIP_EXE = r"c:\Program Files (x86)\7-Zip\7z.exe"

ORIG_SIZE = SRC.stat().st_size


# ============================================================
# ZIP (ZIP64 + progress)
# ============================================================

def zip_test():
    dst = BASE.with_suffix(".zip")
    total = ORIG_SIZE
    processed = 0

    start = time.time()

    with zipfile.ZipFile(
        dst,
        "w",
        compression=zipfile.ZIP_DEFLATED,
        compresslevel=9,
    ) as zf:

        zi = zipfile.ZipInfo(SRC.name)
        zi.compress_type = zipfile.ZIP_DEFLATED

        # ⬇⬇⬇ KLÍČOVÁ OPRAVA ⬇⬇⬇
        with zf.open(zi, "w", force_zip64=True) as z:
            with open(SRC, "rb") as f:
                while buf := f.read(CHUNK):
                    z.write(buf)
                    processed += len(buf)
                    print(
                        f"\rZIP   {processed*100/total:6.2f}%",
                        end="",
                        flush=True,
                    )

    print()
    return time.time() - start, dst.stat().st_size


# ============================================================
# 7Z (CLI + progress)
# ============================================================

def sevenzip_test():
    dst = BASE.with_suffix(".7z")

    start = time.time()

    proc = subprocess.Popen(
        [SEVENZIP_EXE, "a", "-t7z", "-mx=9", str(dst), str(SRC)],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        text=True,
    )

    for line in proc.stdout:
        if "%" in line:
            print(f"\r7Z    {line.strip():>6}", end="", flush=True)

    proc.wait()
    print()

    return time.time() - start, dst.stat().st_size


# ============================================================
# ZSTD (stream + progress)
# ============================================================

def zstd_test():
    dst = BASE.with_suffix(".zst")
    total = ORIG_SIZE
    processed = 0

    cctx = zstd.ZstdCompressor(level=19)
    start = time.time()

    with open(SRC, "rb") as src, open(dst, "wb") as out:
        with cctx.stream_writer(out) as compressor:
            while buf := src.read(CHUNK):
                compressor.write(buf)
                processed += len(buf)
                print(
                    f"\rZSTD  {processed*100/total:6.2f}%",
                    end="",
                    flush=True,
                )

    print()
    return time.time() - start, dst.stat().st_size


# ============================================================
# MAIN
# ============================================================

results = {}

print("\n--- ZIP ---")
t, s = zip_test()
results["ZIP"] = (t, s)

# print("\n--- 7Z ---")
# t, s = sevenzip_test()
# results["7Z"] = (t, s)
#
# print("\n--- ZSTD ---")
# t, s = zstd_test()
# results["ZSTD"] = (t, s)


# ============================================================
# SUMMARY
# ============================================================

print("\n=== SUMMARY ===")
for name, (t, size) in results.items():
    ratio = 100 * (1 - size / ORIG_SIZE)
    print(
        f"{name:5s}: "
        f"{t:7.1f} s   "
        f"{size/1024/1024:8.1f} MB   "
        f"(-{ratio:5.1f} %)"
    )
