import config

# Function to find the closest perceptual hash (phash) match
def find_almost_identical_phash(phash, usernames, max_distance=1):
    """
    Find a username whose phash is nearly identical to the given phash.
    :param phash: The phash to compare (e.g., from the 'unknown' image).
    :param usernames: List of tuples containing (username, phash).
    :param max_distance: Maximum Hamming distance to consider as "identical".
    :return: The matching username and phash, or None if no match is found.
    """
    for username in usernames:
        dist = hamming_distance(phash, username[1])
        if dist <= max_distance:
            return username
    return None

def hamming_distance(phash1, phash2):
    """
    Calculate the Hamming distance between two binary strings.
    """
    if len(phash1) != len(phash2):
        raise ValueError("Hashes must be of the same length")
    return sum(c1 != c2 for c1, c2 in zip(phash1, phash2))


# Establish database connection
db, cursor = config.gen_connection()

# Fetch all images with an 'unknown' username
cursor.execute("SELECT id, username, phash FROM media WHERE username = 'unknown'")
rows = cursor.fetchall()

# Fetch all non-unknown usernames and their associated phash
cursor.execute("SELECT username, phash FROM media WHERE username != 'unknown' AND phash IS NOT NULL AND status = 'public'")
usernames = cursor.fetchall()

# Ensure there are valid usernames to compare against
if not usernames:
    print("No known usernames found in the database.")
    exit()

# Adjusted section in your script
for row in rows:
    id = row[0]
    phash = row[2]

    # Find a nearly identical phash match
    closest = find_almost_identical_phash(phash, usernames, max_distance=2)

    if closest:
        print(f"Found match for image {id}: {closest[0]} with phash {closest[1]}")
        cursor.execute(
            "UPDATE media SET username = %s WHERE id = %s",
            (closest[0], id),
        )
        db.commit()
    else:
        print(f"No nearly identical match found for image {id}.")
