#!/usr/bin/env python3

import datetime
import hashlib
import json
import os
import re
import shutil
import subprocess
import sys
import urllib.request

PACKAGE_PATTERN = re.compile(r"^(Package|Version): (.*)$", re.MULTILINE)

# packages_path = os.environ['HOME'] + '/src/termux-packages'
# if not os.path.isdir(packages_path): sys.exit(packages_path + '" does not exist')
supported_arches = ["aarch64", "x86_64", "arm"]

subpkg_to_parent_pkg = {}

repo_json = json.load(open("repo.json"))


def is_package_built(package_name, local_version, arch):
    deb_to_build = f"{package_name}_{local_version}_{arch}.deb"
    deb_to_build_arch_all = f"{package_name}_{local_version}_all.deb"
    for path in [f"output/{deb_to_build}", f"output/{deb_to_build_arch_all}"]:
        if os.path.exists(path):
            print(
                f"{package_name}@{local_version} {arch} Already built - {path}"
            )
            return True
    return False


for arch in supported_arches:
    name_to_local_version = {}
    proc = subprocess.run(
        ["./scripts/list-versions", "-a", arch],
        capture_output=True,
        check=True,
        text=True,
    )
    for line in proc.stdout.splitlines():
        [pkg_name, version] = line.split("=")
        if "<-" in pkg_name:
            [pkg_name, parent_pkg_name] = pkg_name.split("<-")
            subpkg_to_parent_pkg[pkg_name] = parent_pkg_name
        name_to_local_version[pkg_name] = version

    remote_packages = set()
    reported_packages = set()

    for entry in repo_json.keys():
        base_url = repo_json[entry]['url']
        distribution = repo_json[entry]['distribution']

        # https://termux.net/dists/stable/main/binary-{arch}/Packages
        url = f"{base_url}/dists/{distribution}/main/binary-{arch}/Packages"
        arch_package_file = urllib.request.urlopen(url)
        arch_package_str = arch_package_file.read().decode("utf-8")

        current_package = None
        current_is_static = False
        for m in re.finditer(PACKAGE_PATTERN, arch_package_str):
            if m.group(1) == "Package":
                current_package = m.group(2)
                remote_packages.add(current_package)
                if (
                    current_package.endswith("-static")
                    and current_package not in name_to_local_version
                ):
                    current_is_static = True
                    current_package = current_package.removesuffix("-static")
                else:
                    current_is_static = False
            else:
                remote_version = m.group(2)
                if current_package not in name_to_local_version:
                    name_to_report = current_package
                    if current_is_static:
                        name_to_report += "-static"
                    print(
                        f"{name_to_report} {arch} Delete {entry} - published package not in local"
                    )
                else:
                    local_version = name_to_local_version[current_package]

                    package_to_report = current_package
                    if current_package in subpkg_to_parent_pkg:
                        # Report that parent package needs rebuilding
                        package_to_report = subpkg_to_parent_pkg[current_package]

                    if (
                        local_version != remote_version
                        and package_to_report not in reported_packages
                    ):
                        if current_is_static:
                            current_package += "-static"
                        if not is_package_built(current_package, local_version, arch):
                            print(
                                f"{package_to_report} {arch} Version mismatch - local={local_version}, remote={remote_version} (from {current_package})"
                            )

                        reported_packages.add(package_to_report)

    if name_to_local_version:
        already_reported = set()
        for pkg in name_to_local_version.keys():
            if pkg not in remote_packages:
                if pkg in subpkg_to_parent_pkg:
                    parent_pkg = subpkg_to_parent_pkg[pkg]
                    if parent_pkg not in already_reported:
                        if not is_package_built(parent_pkg, name_to_local_version[parent_pkg], arch):
                            already_reported.add(parent_pkg)
                            print(f"{parent_pkg} {arch} Needs to be rebuilt as subpackage {pkg} exists locally but is not published")
                elif pkg not in already_reported:
                    if not is_package_built(pkg, name_to_local_version[pkg], arch):
                        already_reported.add(pkg)
                        print(f"{pkg} {arch} Package exists locally but is not published")

