import struct
import sys
from pathlib import Path

DUMPS_DIR = Path(__file__).parent / "dumps"


def read_tdf(path: str) -> tuple:
    with open(path, "rb") as f:
        data = f.read()

    assert data[:4] == b"TDF$", f"Not TDF: {path}"
    version = struct.unpack("<I", data[4:8])[0]
    payload = data[8:]
    return version, payload


def read_qbytearray(data: bytes, offset: int) -> tuple:
    length = struct.unpack(">I", data[offset : offset + 4])[0]
    offset += 4
    if length == 0xFFFFFFFF:
        return b"", offset
    value = data[offset : offset + length]
    offset += length
    return value, offset


def extract_hash(dump_id: str, tgdata_path: Path) -> str:
    ver, payload = read_tdf(str(tgdata_path / "key_datas"))

    offset = 0
    salt, offset = read_qbytearray(payload, offset)
    key_encrypted, offset = read_qbytearray(payload, offset)

    # $telegram$2*iterations*salt_hex*key_encrypted_hex
    return f"$telegram$2*100000*{salt.hex()}*{key_encrypted.hex()}"


def main():
    hashes = []
    for d in sorted(DUMPS_DIR.iterdir()):
        tgdata = d / "tgdata"
        if not (tgdata / "key_datas").exists():
            continue

        try:
            h = extract_hash(d.name, tgdata)
            hashes.append((d.name, h))
            print(f"{d.name}: OK", file=sys.stderr)
        except Exception as e:
            print(f"{d.name}: FAIL - {e}", file=sys.stderr)

    with open(Path(__file__).parent / "data" / "tg_hashes.txt", "w") as f:
        for dump_id, h in hashes:
            f.write(f"{h}\n")

    print(f"\n[*] Extracted {len(hashes)} hashes -> data/tg_hashes.txt", file=sys.stderr)

    for dump_id, h in hashes:
        print(f"# {dump_id}")
        print(h)


if __name__ == "__main__":
    main()
