from __future__ import annotations

# -------------------------
# Imports
# -------------------------
import json
import hashlib
from pathlib import Path

# -------------------------
# Config
# -------------------------
ROOT_DIR = Path(__file__).resolve().parent
SC_DIR = ROOT_DIR / "seamlesscoop"
PACKS_JSON = ROOT_DIR / "packs.json"
MANIFEST_JSON = SC_DIR / "manifest.json"
PACK_CONFIG_JSON = SC_DIR / "pack_config.json"

# Public URL where the seamlesscoop folder is hosted
SC_BASE_URL = "https://files.vmvproductions.net/downloads/EldenRingModsDB/seamlesscoop/"

# Files inside seamlesscoop that should NOT be hashed into the SC payload manifest
IGNORE_FILENAMES = {
    "manifest.json",
    "pack_config.json",
}

# -------------------------
# Helpers
# -------------------------
def sha256_file(path: Path) -> str:
    # Hash a file in chunks so large files do not use too much memory
    h = hashlib.sha256()
    with open(path, "rb") as f:
        while True:
            chunk = f.read(1024 * 1024)
            if not chunk:
                break
            h.update(chunk)
    return h.hexdigest().lower()

def load_json(path: Path, default):
    # Load JSON from disk or return the provided default if missing/bad
    try:
        return json.loads(path.read_text(encoding="utf-8"))
    except Exception:
        return default

# -------------------------
# Build SC manifest
# -------------------------
def build_sc_manifest() -> dict:
    # Scan the seamlesscoop folder and hash every real payload file
    files = []

    if not SC_DIR.exists():
        raise RuntimeError(f"Missing SC directory: {SC_DIR}")

    for p in sorted(SC_DIR.rglob("*")):
        if not p.is_file():
            continue
        if p.name in IGNORE_FILENAMES:
            continue

        rel = p.relative_to(SC_DIR).as_posix()
        files.append({
            "path": rel,
            "sha256": sha256_file(p),
        })

    return {
        "base_url": SC_BASE_URL,
        "files": files,
    }

# -------------------------
# Build / preserve per-pack config
# -------------------------
def build_pack_config() -> dict:
    # Start from the existing pack config so manually entered values survive reruns
    existing = load_json(PACK_CONFIG_JSON, {})

    # Read packs.json so every known pack gets an entry
    packs = load_json(PACKS_JSON, [])
    out = {}

    for item in packs:
        zip_name = (item.get("zip") or "").strip()
        if not zip_name:
            continue

        prev = existing.get(zip_name, {})
        out[zip_name] = {
            "cooppassword": str(prev.get("cooppassword", "")).strip(),
            "save_file_extension": str(prev.get("save_file_extension", "")).strip(),
            "target_subdir": str(prev.get("target_subdir", "")).strip(),
        }

    # Preserve old/manual entries even if a pack is temporarily not in packs.json
    for zip_name, prev in existing.items():
        if zip_name not in out:
            out[zip_name] = {
                "cooppassword": str(prev.get("cooppassword", "")).strip(),
                "save_file_extension": str(prev.get("save_file_extension", "")).strip(),
                "target_subdir": str(prev.get("target_subdir", "")).strip(),
            }

    return out

# -------------------------
# Main
# -------------------------
def main():
    SC_DIR.mkdir(parents=True, exist_ok=True)

    manifest = build_sc_manifest()
    pack_cfg = build_pack_config()

    MANIFEST_JSON.write_text(json.dumps(manifest, indent=2), encoding="utf-8")
    PACK_CONFIG_JSON.write_text(json.dumps(pack_cfg, indent=2), encoding="utf-8")

    print(f"Wrote {MANIFEST_JSON}")
    print(f"Wrote {PACK_CONFIG_JSON}")
    print(f"SC payload file count: {len(manifest['files'])}")
    print(f"Pack config entry count: {len(pack_cfg)}")

if __name__ == "__main__":
    main()