import hashlib
import hmac
import re

from nacl.bindings import crypto_pwhash_ALG_ARGON2ID13
from nacl.bindings import crypto_pwhash_alg
from nacl.exceptions import CryptoError

ARGON_AGNOSTIC_RE = re.compile(r"^3_(?P<seed>\d+)_(?P<ops>\d+)_(?P<mem>\d+)$")

def _magento_argon_hash(password: str, salt: str, seed: int, ops: int, mem: int) -> str:
    # Magento pads or truncates salt to libsodium SALTBYTES (16)
    salt_bytes = salt.encode("utf-8")
    if len(salt_bytes) < 16:
        repeat_count = (16 // len(salt_bytes)) + 1 if len(salt_bytes) > 0 else 16
        salt_bytes = (salt_bytes * repeat_count)[:16]
    elif len(salt_bytes) > 16:
        salt_bytes = salt_bytes[:16]

    hashed = crypto_pwhash_alg(
        seed,
        password.encode("utf-8"),
        salt_bytes,
        ops,
        mem,
        crypto_pwhash_ALG_ARGON2ID13,
    )
    return hashed.hex()

def verify_password(plain_password: str, stored_hash: str) -> bool:
    hash_part, salt, version_str = stored_hash.split(":", 2)
    versions = version_str.split(":")  # Magento supports upgraded chains like 1:3_32_2_67108864

    recreated = plain_password

    for version in versions:
        m = ARGON_AGNOSTIC_RE.match(version)
        if m:
            recreated = _magento_argon_hash(
                recreated,
                salt,
                int(m.group("seed")),
                int(m.group("ops")),
                int(m.group("mem")),
            )
        else:
            v = int(version)
            if v == 0:
                recreated = hashlib.md5((salt + recreated).encode("utf-8")).hexdigest()
            elif v == 1:
                recreated = hashlib.sha256((salt + recreated).encode("utf-8")).hexdigest()
            else:
                return False

    print(f"Recreated: {recreated}")
    print(f"Hash_part: {hash_part}")
    return hmac.compare_digest(recreated, hash_part)

my_hash = "09dd90e72abcba5647f967582033873e5cc5362dfa82284ab15505fe97fd5a4b:49wzfGpcLxiXp59syBehAbovk38zzsKQ:3_32_2_67108864"
password = "Dolphin@0120"
print(verify_password(password, my_hash))