#!/usr/bin/env bash

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Determine the operating system
export OS=$(uname)

# Primary network interface
if [[ "$OS" != "Darwin" ]]; then
  export PRIMARY_IFACE=$(ip -o -4 route show to default | awk '{print $5}')
  echo -e "${GREEN}Found primary network interface $PRIMARY_IFACE${NC}"
fi

# Custom print function
_print() {
  if [[ "$OS" == "Darwin" ]]; then
    echo -e "$1"
  else
    echo "$1"
  fi
}

# Custom prompt function
_prompt() {
  local message="$1"
  local variable="$2"

  _print "$message"
  read -r $variable
}

insert_secrets_output() {
  local pattern="outputs = { self, darwin, nix-homebrew, homebrew-bundle, homebrew-core, homebrew-cask, home-manager, nixpkgs, disko, agenix } @inputs:"
  local insert_text="secrets "

  awk -v pat="$pattern" -v insert="$insert_text" '
    $0 ~ pat {
      sub(/} @inputs:/, ", " insert "} @inputs:"); # Replace the closing brace with the insert text followed by the brace
      gsub(/ ,/, ","); # Correct any spaces before commas
      print
      next
    }
    { print }
  ' flake.nix > flake.nix.tmp

  mv flake.nix.tmp flake.nix
}

insert_secrets_input() {
  # Define file path
  FILE_PATH="flake.nix"

  # Backup the original file
  cp "$FILE_PATH" "${FILE_PATH}.bak"

  # Temporary file for the text to insert
  TEMP_FILE="temp_insert.txt"

  # Write the formatted text to the temporary file
cat > "$TEMP_FILE" << 'EOF'
    secrets = {
      url = "git+ssh://git@github.com/%GITHUB_USER%/%GITHUB_SECRETS_REPO%.git";
      flake = false;
    };
EOF

  # Check if the 'secrets' block already exists
  if grep -q 'url = "git+ssh://git@github.com/%GITHUB_USER%/%GITHUB_SECRETS_REPO%.git"' "$FILE_PATH"; then
      echo "The 'secrets' block already exists in the file."
      rm "$TEMP_FILE"
      rm "${FILE_PATH}.bak"
      exit 0
  fi

  # Find the start and end line numbers of the 'disko' block
  START_LINE=$(grep -n 'disko = {' "$FILE_PATH" | head -n 1 | cut -d: -f1)
  END_LINE=$(tail -n +$START_LINE "$FILE_PATH" | grep -n '};' | head -n 1 | cut -d: -f1)
  END_LINE=$((START_LINE + END_LINE - 1))

  # Create a new file with the insertion
  {
      sed -n "1,${END_LINE}p" "$FILE_PATH"
      cat "$TEMP_FILE"
      sed -n "$((END_LINE + 1)),\$p" "$FILE_PATH"
  } > "${FILE_PATH}.new"

  # Replace the original file with the new file
  mv "${FILE_PATH}.new" "$FILE_PATH"

  # Clean up the temporary files
  rm "$TEMP_FILE"
  rm "${FILE_PATH}.bak"
}

ask_for_star() {
  _print "${YELLOW}Would you like to support my work by starring my GitHub repo? yes/no [yes]: ${NC}"
  local response
  read -r response
  response=${response:-yes} # Set default response to 'yes' if input is empty
  if [[ "$response" =~ ^[Yy](es)?$ ]] || [[ -z "$response" ]]; then
    if [[ "$OS" == "Darwin" ]]; then
      open "https://github.com/dustinlyons/nixos-config"
    else
      xdg-open "https://github.com/dustinlyons/nixos-config"
    fi
  fi
}

ask_for_star

# Fetch username from the system
export USERNAME=$(whoami)

# If the username is 'nixos' or 'root', ask the user for their username
if [[ "$USERNAME" == "nixos" ]] || [[ "$USERNAME" == "root" ]]; then
  _prompt "${YELLOW}You're running as $USERNAME. Please enter your desired username: ${NC}" USERNAME
fi

# Check if git is available
if command -v git >/dev/null 2>&1; then
  # Fetch email and name from git config
  export GIT_EMAIL=$(git config --get user.email)
  export GIT_NAME=$(git config --get user.name)
else
  _print "${RED}Git is not available on this system.${NC}"
fi

# If git email is not found or git is not available, ask the user
if [[ -z "$GIT_EMAIL" ]]; then
  _prompt "${YELLOW}Please enter your email: ${NC}" GIT_EMAIL
fi

# If git name is not found or git is not available, ask the user
if [[ -z "$GIT_NAME" ]]; then
  _prompt "${YELLOW}Please enter your name: ${NC}" GIT_NAME
fi

_prompt "${YELLOW}Please enter your Github username: ${NC}" GITHUB_USER
_prompt "${YELLOW}Please enter your Github secrets repository name: ${NC}" GITHUB_SECRETS_REPO

export GITHUB_USER
export GITHUB_SECRETS_REPO

select_boot_disk() {
  local disks
  local _boot_disk

  _print "${YELLOW}Available disks:${NC}"
  disks=$(lsblk -nd --output NAME,SIZE | grep -v loop)
  echo "$disks"

  # Warning message for data deletion
  _print "${RED}WARNING: All data on the chosen disk will be erased during the installation!${NC}"
  _prompt "${YELLOW}Please enter the name of your boot disk (e.g., sda, nvme0n1). Do not include the full path ("/dev/"): ${NC}" _boot_disk

  # Confirmation for disk selection to prevent accidental data loss
  _print "${YELLOW}You have selected $_boot_disk as the boot disk. This will delete everything on this disk. Are you sure? (Y/N): ${NC}"
  read -r confirmation
  if [[ "$confirmation" =~ ^[Yy]$ ]]; then
    export BOOT_DISK=$_boot_disk
  else
    _print "${RED}Disk selection cancelled by the user. Please run the script again to select the correct disk.${NC}"
    exit 1
  fi
}

# Set hostname and find primary disk if this is NixOS
if [[ "$OS" != "Darwin" ]]; then
  _prompt "${YELLOW}Please enter a hostname for the system: ${NC}" HOST_NAME
  export HOST_NAME
  select_boot_disk
fi

# Confirmation step
confirm_details() {
  _print "${GREEN}Username: $USERNAME"
  _print "Email: $GIT_EMAIL"
  _print "Name: $GIT_NAME${NC}"

  if([[ "$OS" != "Darwin" ]]); then
    _print "${GREEN}Primary interface: $PRIMARY_IFACE"
    _print "Boot disk: $BOOT_DISK"
    _print "Hostname: $HOST_NAME${NC}"
  fi

  _print "${GREEN}Secrets repository: $GITHUB_USER/$GITHUB_SECRETS_REPO${NC}"

  _prompt "${YELLOW}Is this correct? yes/no: ${NC}" choice

  case "$choice" in
    [Nn] | [Nn][Oo] ) 
      _print "${RED}Exiting script.${NC}" 
      exit 1
      ;;
    [Yy] | [Yy][Ee][Ss] ) 
      _print "${GREEN}Continuing...${NC}"
      ;;
    * ) 
      _print "${RED}Invalid option. Exiting script.${NC}" 
      exit 1
      ;;
  esac
}

# Call the confirmation function
confirm_details

# Function to replace tokens in each file
replace_tokens() {
  local file="$1"
  if [[ $(basename $1) != "apply" ]]; then
    if [[ "$OS" == "Darwin" ]]; then
      # macOS
      LC_ALL=C LANG=C sed -i '' -e "s/%USER%/$USERNAME/g" "$file"
      LC_ALL=C LANG=C sed -i '' -e "s/%EMAIL%/$GIT_EMAIL/g" "$file"
      LC_ALL=C LANG=C sed -i '' -e "s/%NAME%/$GIT_NAME/g" "$file"
      LC_ALL=C LANG=C sed -i '' -e "s/%GITHUB_USER%/$GITHUB_USER/g" "$file"
      LC_ALL=C LANG=C sed -i '' -e "s/%GITHUB_SECRETS_REPO%/$GITHUB_SECRETS_REPO/g" "$file"
    else
      # Linux or other
      sed -i -e "s/%USER%/$USERNAME/g" "$file"
      sed -i -e "s/%EMAIL%/$GIT_EMAIL/g" "$file"
      sed -i -e "s/%NAME%/$GIT_NAME/g" "$file"
      sed -i -e "s/%INTERFACE%/$PRIMARY_IFACE/g" "$file"
      sed -i -e "s/%DISK%/$BOOT_DISK/g" "$file"
      sed -i -e "s/%HOST%/$HOST_NAME/g" "$file"
      sed -i -e "s/%GITHUB_USER%/$GITHUB_USER/g" "$file"
      sed -i -e "s/%GITHUB_SECRETS_REPO%/$GITHUB_SECRETS_REPO/g" "$file"
    fi
  fi
}

# Insert secrets repo into flake
insert_secrets_input
insert_secrets_output

# Traverse directories and call replace_tokens on each Nix file
export -f replace_tokens
find . -type f -exec bash -c 'replace_tokens "$0"' {} \;

echo "$USERNAME" > /tmp/username.txt
_print "${GREEN}User $USERNAME information applied.${NC}"