{
  config,
  namespace,
  pkgs,
  ...
}:
let
  git-token = config.sops.secrets."github-token".path;

  update-checker = pkgs.writeScriptBin "update-checker" ''
    #!/usr/bin/env nix-shell
    #! nix-shell -i python3 --pure
    #! nix-shell -p python3 python3Packages.pygithub python3Packages.feedparser python3Packages.requests nix-prefetch-scripts nix

    import os
    import json
    import subprocess
    from github import Github
    from github import Auth
    import feedparser
    import requests

    token = None

    with open('${git-token}', 'r') as token_file:
        token = token_file.readline()

    auth = Auth.Token(token)

    def check_github(owner, repo, version):
        try:
            release = None
            result = None
            prefetch = None
            ghub = Github(auth=auth)
            print('  getting repo ' + owner + '/' + repo)
            repo = ghub.get_repo(owner + '/' + repo)
            if '-b' in version:
                release = repo.get_releases()[0]
                latest_version = release.name
            else:
                try:
                    release = repo.get_latest_release()
                    latest_version = release.tag_name
                except:
                    tags = repo.get_tags()
                    try:
                        if tags is not None:
                            latest_version = tags[0].name
                    except:
                        commits = repo.get_commits()
                        latest_version = commits[0].sha

            if latest_version is not None:

                if latest_version.replace('v',''\'') != version.replace('v',''\''):
                    print('  update found')
                    print('  Current version: ' + version)
                    print('  Latest version: ' + latest_version)
                    result = subprocess.check_output(['nix-prefetch-git', '--quiet', repo.clone_url, '--rev', latest_version])
                    prefetch = json.loads(result)
                    print('  New hash: ' + prefetch.get('hash'))
                else:
                    print('  no update')
            ghub.close()
        except Exception as e:
            print(e)

    def check_codeberg(owner, repo, version):
        feed = feedparser.parse('https://codeberg.org/{0}/{1}/releases.rss'.format(owner, repo))
        if feed.status == 200:
            entry = feed.entries[0]
            if entry.title.replace('v',''\'') != version.replace('v',''\''):
                print('  update found')
                print('  Current version: ' + version)
                print('  Latest version: ' + entry.title)
                sha256 = subprocess.check_output(['nix-prefetch-url', url.replace(''\'''\${version}', entry.title.replace('v', ''\''))])
                prefetch = subprocess.check_output(['nix', 'hash', 'convert', '--hash-algo', 'sha256', str(sha256.decode('utf-8').strip())])
                print('  New hash: ' + prefetch.decode('utf-8').strip())
            else:
                print('  no update')

    def check_open_vsx(publisher, name, version):
        open_vsx = requests.get('https://open-vsx.org/api/' + publisher + '/' + name)
        if open_vsx.status_code == 200:
            extension = open_vsx.json()
            latest_version = extension.get('version')
            url = extension.get('files').get('download')
            if latest_version.replace('v',''\'') != version.replace('v',''\''):
                print('  update found')
                print('  Current version: ' + version)
                print('  Latest version: ' + latest_version)
                sha256 = subprocess.check_output(['nix-prefetch-url', url])
                prefetch = subprocess.check_output(['nix', 'hash', 'convert', '--hash-algo', 'sha256', str(sha256.decode('utf-8').strip())])
                print('  New hash: ' + prefetch.decode('utf-8').strip())
            else:
                print('  no update')

    def parse_nix(package_spec):
        version = None
        url = None
        current_hash = None
        owner = None
        repo = None
        pname = None
        name = None
        publisher = None
        for line in package_spec.readlines():
            if 'owner = "' in line and owner is None:
                owner = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
            if 'repo = "' in line and repo is None:
                repo = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
            if 'version = "' in line and version is None:
                version = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
            if 'rev = "' in line and ''\'''\${version}' not in line:
                version = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
            if 'url = "' in line and url is None:
                url = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
            if 'sha256 = "' in line or ' hash = "' in line and current_hash is None:
                current_hash = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
            if 'pname = "' in line and pname is None:
                pname = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
            if ' name = "' in line and name is None:
                name = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
            if 'publisher = "' in line and publisher is None:
                publisher = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')

        if url is None and repo is not None:
            if 'pname' in repo:
                repo = repo.replace(''\'''\${pname}', pname)
            url = 'https://github.com/{0}/{1}/releases/tag/{2}'.format(owner, repo, version)

        if url is not None and repo is None and 'github' in url:
            owner = url.split('github.com/')[-1].split('/')[0]
            repo = url.split('github.com/')[-1].split('/')[1]

        if url is not None and repo is None and 'codeberg' in url:
            owner = url.split('codeberg.org/')[-1].split('/')[0]
            repo = url.split('codeberg.org/')[-1].split('/')[1]

        if url is not None and version is None:
            version = url.split('/')[-1].replace('.tar.gz', ''\'')

        if url is not None and publisher is not None:
            url = url.replace(''\'''\${publisher}', publisher).replace(''\'''\${name}', name)

        return url, current_hash, owner, repo, pname, name, publisher, version

    def parse_json(json_versions, flavor=''\''):
        versions = json.load(json_versions)
        linux_versions = versions.get('linux')
        config_versions = versions.get('config')
        patch_versions = versions.get('patches')
        zfs_versions = versions.get('zfs')
                
        check_kernel(linux_versions, flavor)
        check_cachy_config(config_versions, flavor)
        check_patch_versions(patch_versions, flavor)
        check_zfs_versions(zfs_versions, flavor)

    def check_kernel(linux_versions, flavor=''\''):
        srcinfo = requests.get('https://raw.githubusercontent.com/CachyOS/linux-cachyos/master/linux-cachyos' + flavor + '/.SRCINFO')
        for line in srcinfo.text.split('\n'):
            if 'pkgver = ' in line:
                kernel_version = line.split('=')[-1].strip()
                if kernel_version[-2:] == '.0':
                    kernel_version = kernel_version[:-2]
                if flavor in [''\'', '-lts', '-server', '-gcc', '-hardened']:
                    release_src = 'https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-' + kernel_version + '.tar.xz'
                if flavor == '-rc':
                    release_src = 'https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/snapshot/linux-' + kernel_version.replace('.rc', '-rc') + '.tar.gz'
        sha256 = subprocess.check_output(['nix-prefetch-url', release_src])
        prefetch = subprocess.check_output(['nix', 'hash', 'convert', '--hash-algo', 'sha256', str(sha256.decode('utf-8').strip())])
        current_version = linux_versions.get('version')
        current_hash = linux_versions.get('hash')
        latest_hash = prefetch.decode('utf-8').strip()
        print('  Checking linux versions...')
        if current_hash != latest_hash:
            print('    Current rev: ' + current_version)
            print('    Current hash: ' + current_hash)
            print('    New rev: ' + kernel_version)
            print('    New hash: ' + latest_hash)
        else:
            print('    no update')

    def check_cachy_config(config_versions, flavor=''\''):
        result = subprocess.check_output(['nix-prefetch-git', '--quiet', 'https://github.com/CachyOS/linux-cachyos.git'])
        prefetch = json.loads(result)
        current_version = config_versions.get('rev')
        latest_version = prefetch.get('rev')
        print('  Checking config versions...')
        if current_version != latest_version:
            print('    Current rev: ' + current_version)
            print('    New rev: ' + latest_version)
            print('    New hash: ' + prefetch.get('hash'))
        else:
            print('    no update')

    def check_patch_versions(patch_versions, flavor=''\''):
        result = subprocess.check_output(['nix-prefetch-git', '--quiet', 'https://github.com/CachyOS/kernel-patches.git'])
        prefetch = json.loads(result)
        current_version = patch_versions.get('rev')
        latest_version = prefetch.get('rev')
        print('  Checking patch versions...')
        if current_version != latest_version:
            print('    Current rev: ' + current_version)
            print('    New rev: ' + latest_version)
            print('    New hash: ' + prefetch.get('hash'))
        else:
            print('    no update')

    def kconfig_to_nix(flavor=''\''):
        kconfig_result = subprocess.check_output(['nix', 'build', '.#nixosConfigurations.jallen-nas.pkgs.linuxPackages_cachyos' + flavor + '.kernel.kconfigToNix', '--no-link', '--print-out-paths'])
        config_file = kconfig_result.decode('utf-8').strip()
        if flavor == ''\'':
            cachy_flavor = '-gcc'
        result = subprocess.check_output(['cat', config_file])
        with open('/etc/nixos/packages/linux-cachyos/config-nix/cachyos' + cachy_flavor + '.x86_64-linux.nix', 'w') as config:
            config.write(result.decode('utf-8').strip())

    def check_zfs_versions(zfs_versions, flavor=''\''):
        result = requests.get('https://raw.githubusercontent.com/CachyOS/linux-cachyos/master/linux-cachyos' + flavor + '/PKGBUILD')
        for line in result.text.split('\n'):
            if 'git+https://github.com/cachyos/zfs.git#commit=' in line:
                zfs_rev = line.split('zfs.git#commit=')[-1].replace('")', ''\'')
        result = subprocess.check_output(['nix-prefetch-git', '--quiet', 'https://github.com/CachyOS/zfs.git', '--rev', zfs_rev])
        prefetch = json.loads(result)
        current_version = zfs_versions.get('rev')
        latest_version = prefetch.get('rev')
        print('  Checking zfs versions...')
        if current_version != latest_version:
            print('    Current rev: ' + current_version)
            print('    New rev: ' + latest_version)
            print('    New hash: ' + prefetch.get('hash'))
        else:
            print('    no update')

    for (root,dirs,files) in os.walk('/etc/nixos/packages',topdown=True):
        if 'default.nix' in files and 'versions.json' not in files:
            print(root.split('/')[-1])
            with open(root + '/default.nix', 'r') as package_spec:
                url, current_hash, owner, repo, pname, name, publisher, version = parse_nix(package_spec)

            if owner is not None and repo is not None and 'codeberg' in url:
                check_codeberg(owner, repo, version)

            elif owner is not None and repo is not None and 'github' in url:
                check_github(owner, repo, version)

            elif publisher is not None and 'open-vsx' in url:
                check_open_vsx(publisher, name, version)

            else:
                if url is not None:
                    print(url)
        
        if 'default.nix' in files and 'versions.json' in files:
            with open(root + '/versions.json', 'r') as json_versions:
                print('Checking Linux CachyOS')
                parse_json(json_versions)
            with open(root + '/versions-rc.json', 'r') as json_versions:
                print('Checking Linux CachyOS RC')
                parse_json(json_versions, '-rc')
            with open(root + '/versions-lts.json', 'r') as json_versions:
                print('Checking Linux CachyOS LTS')
                parse_json(json_versions, '-lts')
            with open(root + '/versions-hardened.json', 'r') as json_versions:
                print('Checking Linux CachyOS Hardened')
                parse_json(json_versions, '-hardened')
  '';
in
{
  config = {

    sops = {
      age.keyFile = "/home/${config.${namespace}.user.name}/.config/sops/age/keys.txt";
      defaultSopsFile = "/etc/nixos/secrets/secrets.yaml";
      validateSopsFiles = false;
      secrets = {
        "github-token" = { };
      };
      templates = {
        ".env".content = ''
          GITHUB_TOKEN = "${config.sops.placeholder.github-token}"
        '';
      };
    };
    home.packages = [ update-checker ];
  };
}
