# retoor <retoor@molodetz.nl>

import json
import shutil
import sys
import zipfile
import zlib
from pathlib import Path

FIXED_DATE = (1980, 1, 1, 0, 0, 0)

CHUNK_SIZE = 1024 * 1024


def _build(source_dir: str, output_path: str) -> dict:
    bytes_in = 0
    file_count = 0
    dir_count = 0
    source_path = Path(source_dir)
    output_path_obj = Path(output_path)
    with zipfile.ZipFile(output_path, "w", zipfile.ZIP_DEFLATED) as archive:
        for root, dirs, files in Path(source_dir).walk():
            dirs.sort()
            for name in dirs:
                dir_count += 1
                arcname = str((root / name).relative_to(source_path)) + "/"
                info = zipfile.ZipInfo(arcname, date_time=FIXED_DATE)
                info.external_attr = (0o040755 << 16) | 0x10
                archive.writestr(info, b"")
            for name in sorted(files):
                full = root / name
                arcname = str(full.relative_to(source_path))
                bytes_in += full.stat().st_size
                info = zipfile.ZipInfo(arcname, date_time=FIXED_DATE)
                info.compress_type = zipfile.ZIP_DEFLATED
                info.external_attr = 0o644 << 16
                with full.open("rb") as source, archive.open(info, "w") as target:
                    shutil.copyfileobj(source, target)
                file_count += 1

    crc = 0
    with open(output_path, "rb") as handle:
        for chunk in iter(lambda: handle.read(CHUNK_SIZE), b""):
            crc = zlib.crc32(chunk, crc)

    return {
        "bytes_in": bytes_in,
        "bytes_out": output_path_obj.stat().st_size,
        "file_count": file_count,
        "dir_count": dir_count,
        "crc32": crc & 0xFFFFFFFF,
    }


def main(argv: list) -> int:
    if len(argv) != 3:
        sys.stderr.write("usage: zip_worker <source_dir> <output_zip>\n")
        return 2
    source_dir, output_path = argv[1], argv[2]
    if not Path(source_dir).is_dir():
        sys.stderr.write(f"source directory not found: {source_dir}\n")
        return 3
    stats = _build(source_dir, output_path)
    sys.stdout.write(json.dumps(stats))
    return 0


if __name__ == "__main__":
    raise SystemExit(main(sys.argv))
