#!/usr/bin/env bash

set -euo pipefail

GREEN='\033[1;32m'
NC='\033[0m'
apt_packages=(
    atop
    autossh
    bat
    borgbackup
    borgmatic
    build-essential
    calibre
    cmake
    curl
    direnv
    duf
    emacs
    firewalld
    fzf
    git
    git-core
    golang
    hdparm
    htop
    hugo
    jc
    jq
    lsd
    lynx
    maim
    neovim
    nmap
    nodejs
    npm
    papirus-icon-theme
    parallel
    pipx
    prometheus-node-exporter
    python3-dev
    python3-pip
    python3-poetry
    ripgrep
    rofi
    rsync
    rsyslog
    shfmt
    shellcheck
    tcpdump
    tealdeer
    trash-cli
    unzip
    w3m
    wget
    wireshark
    xclip
    zip
    zsh
)

dnf_packages=(
    age
    atop
    autossh
    bat
    borgbackup
    borgmatic
    btrfs-assistant
    calibre
    cmake
    curl
    diff-so-fancy
    direnv
    duf
    emacs
    ethtool
    eza
    fastfetch
    fd-find
    flatpak
    fzf
    git
    git-core
    golang
    hdparm
    htop
    hugo
    jc
    jq
    just
    lagrange
    ldns
    libtool
    lsd
    lsof
    lynx
    maim
    neovim
    nmap
    node-exporter
    nodejs
    nu
    parallel
    pipx
    poetry
    python3-devel
    python3-pip
    qbittorrent
    ripgrep
    rofi
    rsync
    rsyslog
    shfmt
    ShellCheck
    tcpdump
    tealdeer
    trash-cli
    vlc
    w3m
    wireshark
    xclip
    xfce4-docklike-plugin
    xfce4-genmon-plugin
    xfce4-weather-plugin
    zsh
)

copr_repos=(
    atim/starship
    hyperreal/better_fonts
    varlad/yazi
    varlad/zellij
)

flatpak_packages=(
    com.discordapp.Discord
    com.github.tchx84.Flatseal
    im.riot.Riot
    io.podman_desktop.PodmanDesktop
)

pipx_packages=(
    "black"
    "bpython"
    "isort"
    "pyright"
    "uv"
)

services_enable=(
    atop.service
    atopacct.service
    atop-rotate.timer
    firewalld.service
    prometheus-node-exporter.service
    rsyslog.service
    systemd-networkd.service
    tailscaled.service
)

services_disable=(
    avahi-daemon.service
    avahi-daemon.socket
    bluetooth.service
    cups.service
    cups-browsed.service
    NetworkManager.service
)

function action_label() {
    echo ""
    echo -e "${GREEN}--> ${1}...${NC}"
}

install_makedeb_prebuilt_packages() {
    wget -qO - 'https://proget.makedeb.org/debian-feeds/prebuilt-mpr.pub' | gpg --dearmor | sudo tee /usr/share/keyrings/prebuilt-mpr-archive-keyring.gpg 1>/dev/null
    echo "deb [arch=all,$(dpkg --print-architecture) signed-by=/usr/share/keyrings/prebuilt-mpr-archive-keyring.gpg] https://proget.makedeb.org prebuilt-mpr $(lsb_release -cs)" | sudo tee /etc/apt/sources.list.d/prebuilt-mpr.list
    sudo apt update
    sudo apt dist-upgrade -y
    sudo apt install just
}

# interactive
install_starship() {
    if ! test -f "$(command -v starship)"; then
        curl -sS https://starship.rs/install.sh | sh
    fi
}

function install_packages() {
    action_label "INSTALLING PACKAGES"
    if test -f /etc/debian_version; then
        sudo apt install -y "${apt_packages[@]}"
        install_makedeb_prebuilt_packages
        install_starship
        install_zellij
    fi

    if test -f /etc/redhat-release; then
        sudo dnf install -y "${dnf_packages[@]}"
        install_devel_groups
        enable_copr_repos
        install_copr_packages
        install_rpmfusion_repos
        install_rpmfusion_packages
    fi
}

function install_devel_groups() {
    action_label "INSTALLING DEVELOPMENT GROUPS"
    sudo dnf install -y '@c-development' '@development-tools' '@container-management'
}
function enable_copr_repos() {
    action_label "ENABLING COPR REPOS"
    for repo in "${copr_repos[@]}"; do sudo dnf copr enable -y "$repo"; done
}

# Depends: enable_copr_repos
function install_copr_packages() {
    action_label "INSTALLING COPR PACKAGES"
    sudo dnf install -y starship fontconfig-font-replacements yazi zellij
}

function install_rpmfusion_repos() {
    action_label "INSTALLING RPMFUSION REPOS"
    sudo dnf install -y "https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm" "https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm"
}

# Depends: install_rpmfusion_repos
function install_rpmfusion_packages() {
    action_label "INSTALLING RPMFUSION PACKAGES"
    sudo dnf install -y --allowerasing ffmpeg-libs
}

install_zellij() {
    if test -f /etc/debian_version; then
        curl -s https://api.github.com/repos/zellij-org/zellij/releases/latest | grep "browser_download_url" | grep "zellij-$(uname -m)-unknown-linux-musl.tar.gz" | cut -d : -f 2,3 | tr -d '"' | wget -qi -
        curl -s https://api.github.com/repos/zellij-org/zellij/releases/latest | grep "browser_download_url" | grep "zellij-$(uname -m)-unknown-linux-musl.sha256sum" | cut -d : -f 2,3 | tr -d '"' | wget -qi -
        tar xvf "zellij-$(uname -m)-unknown-linux-musl.tar.gz"
        if [ $(sha256sum -c "zellij-$(uname -m)-unknown-linux-musl.sha256sum" | head -n 1 | awk '{print $2}') = "OK" ]; then
            sudo mv zellij /usr/local/bin
        fi
        rm -v zellij*
    fi
}

function install_charm_packages() {
    action_label "INSTALLING CHARM PACKAGES"

    if test -f /etc/debian_version; then
        curl -s https://api.github.com/repos/charmbracelet/gum/releases/latest | grep "browser_download_url.*deb" | grep "$(dpkg --print-architecture)" | cut -d : -f 2,3 | tr -d '"' | wget -qi -
        curl -s https://api.github.com/repos/charmbracelet/gum/releases/latest | grep "browser_download_url" | grep "checksums.txt" | head -n 1 | cut -d : -f 2,3 | tr -d '"' | wget -qi -
        if [ "$(grep $(dpkg --print-architecture).deb checksums.txt | sha256sum -c | head -n 1 | awk '{print $2}')" = "OK" ]; then
            sudo dpkg -i gum*.deb
            sudo apt -f install
        fi
        rm -v gum*
        rm -v checksums.txt
    fi

    if test -f /etc/redhat-release; then
        printf "[charm]\nname=Charm\nbaseurl=https://repo.charm.sh/yum/\nenabled=1\ngpgcheck=1\ngpgkey=https://repo.charm.sh/yum/gpg.key\n" | sudo tee /etc/yum.repos.d/charm.repo
        sudo rpm --import https://repo.charm.sh/yum/gpg.key
        sudo dnf install -y gum charm
    fi
}

function install_tailscale() {
    action_label "INSTALLING TAILSCALE"
    sudo rm -v /etc/yum.repos.d/tailscale.repo
    curl -fsSL https://tailscale.com/install.sh | sh
}

function enable_flathub() {
    action_label "ENABLING FLATHUB"
    flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
}

# Depends: enable_flathub
function install_flatpaks() {
    action_label "INSTALLING FLATPAKS"
    for pkg in "${flatpak_packages[@]}"; do flatpak install flathub -y "$pkg"; done
}

# Depends: install_packages
function install_pipx_packages() {
    action_label "INSTALLING PIPX PACKAGES"
    for pkg in "${pipx_packages[@]}"; do pipx install "$pkg"; done
    pipx install ansible --include-deps
}

function setup_networkd_conf() {
    action_label "SETTING UP SYSTEMD-NETWORKD CONFIG"
    echo '[Match]
Name=eno1

[Network]
DHCP=yes
#DNS=100.100.100.100
DNSSEC=allow-downgrade

[DHCPv4]
UseDNS=no' | sudo tee /etc/systemd/network/eno1.network
}

# After: setup_networkd_conf
function setup_resolv_conf() {
    action_label "SETTING UP RESOLV CONF"
    sudo rm -v /etc/resolv.conf
    sudo ln -sf /var/run/systemd/resolve/resolv.conf /etc/resolv.conf
    sudo systemctl restart systemd-resolved
}

# Depends: enable_tailscale
function setup_rsyslog_conf() {
    action_label "SETTING UP RSYSLOG"
    echo '# Forward to main monitoring node (nas-aux.lyrebird-marlin.ts.net)
*.* action(type="omfwd" target="100.86.148.42" port="514" protocol="tcp"
    action.resumeRetryCount="100"
    queue.type="linkedList" queue.size="10000")' | sudo tee /etc/rsyslog.d/00forward-to-nas.conf
}

# After: setup_networkd_conf
function disable_services() {
    action_label "DISABLING SYSTEMD SERVICES"
    for service in "${services_disable[@]}"; do
        if sudo systemctl is-active "$service"; then
            sudo systemctl disable --now "$service"
        fi
    done
}

# After:
# - setup_networkd_conf
# - install_packages
function enable_services() {
    action_label "ENABLING SYSTEMD SERVICES"
    for service in "${services_enable[@]}"; do sudo systemctl enable --now "$service"; done
    if test -f /etc/debian_version; then
        sudo systemctl enable --now ssh.service
    elif test -f /etc/redhat-release; then
        sudo systemctl enable --now sshd.service
    fi
}

function disable_ipv6() {
    action_label "DISABLING IPV6"
    if test -f /etc/debian_version; then
        if ! grep "net.ipv6.conf.all.disable_ipv6" /etc/sysctl.conf; then
            echo "net.ipv6.conf.all.disable_ipv6 = 1" | sudo tee -a /etc/sysctl.conf
            echo "net.ipv6.conf.default.disable_ipv6 = 1" | sudo tee -a /etc/sysctl.conf
            echo "net.ipv6.conf.lo.disable_ipv6 = 1" | sudo tee -a /etc/sysctl.conf
            sudo sysctl -p
        else
            echo "IPv6 already disabled."
        fi
    elif test -f /etc/redhat-release; then
        if ! sudo grep "ipv6.disable=1" /boot/grub2/grub.cfg; then
            sudo grubby --args=ipv6.disable=1 --update-kernel=ALL
            sudo grub2-mkconfig -o /boot/grub2/grub.cfg
        else
            echo "IPv6 already disabled."
        fi
    fi
}

function build_bat_cache() {
    action_label "BUILDING BAT CACHE"
    if test -f /etc/debian_version; then
        batcat cache --build
    elif test -f /etc/redhat-release; then
        bat cache --build
    fi
}

# Depends: install_packages
function update_tealdeer_cache() {
    action_label "UPDATING TEALDEER CACHE"
    tldr --update
}

# Depends: install_tailscale
function setup_firewalld() {
    action_label "SETTING UP FIREWALLD"
    if ! sudo firewall-cmd --get-zones | grep "tailnet"; then
        sudo firewall-cmd --permanent --new-zone=tailnet
        sudo firewall-cmd --permanent --zone=tailnet --add-interface=tailscale0
        sudo firewall-cmd --permanent --zone=tailnet --add-port=1025-65535/tcp
        sudo firewall-cmd --permanent --zone=tailnet --add-port=1025-65535/udp
        sudo firewall-cmd --permanent --zone=tailnet --add-service=ssh
    else
        echo "firewalld tailnet zone already configured"
    fi
    if test -f /etc/debian_version; then
        sudo firewall-cmd --permanent --zone=public --remove-service={dhcpv6-client,samba-client}
    elif test -f /etc/redhat-release; then
        sudo firewall-cmd --permanent --zone=FedoraWorkstation --remove-service={dhcpv6-client,samba-client}
    fi
    sudo firewall-cmd --reload
}

function install_rclone() {
    action_label "INSTALLING LATEST RCLONE"
    curl https://rclone.org/install.sh | sudo bash
    command -v rclone
}

install_packages
install_charm_packages
install_tailscale

if test -f /etc/redhat-release; then
    enable_flathub
    install_flatpaks
    setup_networkd_conf
fi

install_pipx_packages
setup_resolv_conf
setup_rsyslog_conf
disable_services
enable_services
disable_ipv6
build_bat_cache
update_tealdeer_cache
setup_firewalld
install_rclone

action_label "DONE SETTING UP ALL THE THINGS ^_^"