#!/bin/bash
# ================================================
#                 PhantomPHP Server Script
# ================================================
#
# Description:
# This script sets up and serves a PHP application using PHP's built-in server.
# It provides various command-line options to customize server behavior, including
# selecting the port, specifying the directory, and enabling SSH port forwarding.
# The script also handles custom error pages, creates an index file if none exists,
# allows for running specific PHP files, and opens the GitHub repository for the project.
#
# Features:
# - Customizable port and directory for the PHP server.
# - SSH tunneling for port forwarding using Serveo.
# - Automatic creation of a custom error page if no index file is found.
# - Ability to run specific PHP files directly.
# - Option to start MySQL and phpMyAdmin.
#
# Author: Uthman Dev
# GitHub: https://github.com/codetesla51/phantom-php
# License: MIT
# Portfolio: https://uthmandev.vercel.app
# 
# Let's build more projects together! This project is under the MIT license.
# Contributions are welcome.
# ================================================

# ---------------------------- Phantom PHP Server - Code Map ----------------------------
#
# Color Variables
#   - Define color variables to use for console output styling throughout the script.
#     - `NC`: Resets the color to default (used to end colored text).
#     - `RED`: Used for error and warning messages to alert the user.
#     - `GREEN`: Used for success messages to confirm actions completed.
#     - `YELLOW`: Used for informational messages or process updates.
#     - `BLUE`: For additional informational messages or secondary data.
#
# Script Variables
#   - Set up primary variables for controlling the behavior of the script.
#     - `directory`: Defines the directory where the PHP server will run (defaults to current directory).
#     - `port`: Sets the default port for the PHP server to start on (e.g., 8000).
#     - `show_logo`: Sets a default database name when interacting with MySQL.
#     - `ssh_output_file`: Configures the delay (in seconds) used by the loader animation for a smoother experience.
#
# Helper Functions
#   - General utility functions to improve the usability of the script.
#
#   show_loader
#     - Function to show a loading animation while certain operations are in progress.
#     - Provides visual feedback to the user, especially helpful for long-running tasks.
#
#   show_help
#     - Displays the available commands, options, and flags for the script.
#     - Lists and explains each feature, its usage syntax, and purpose.
#     - Includes descriptions for key flags like `-p` for port and `-d` for directory.
#
# phpMyAdmin Setup installation
#     -mariadb and phpMyAdmin installation

# Port Forwarding Function
#   - port_forwarding
#     - Sets up port forwarding to redirect traffic from one port to another.
#     - Example usage: Forwarding from default port `8000` to another port like `3000`.
#     - Useful for cases where the default port is unavailable or for connecting to other services.
#
# File Management Functions
#   - Functions to manage files within the target directory, particularly for creating index files.
#
#
# Server Function
#   - serve
#     - Starts a PHP development server in the specified directory on the designated port.
#     - Checks if the server is already running and provides feedback.
#     - Ensures only one instance runs at a time for the specified configuration.
#
# MySQL Management Functions
#   - Functions to initialize and manage a MySQL server instance if needed.
#
#   mysql_db
#     - Starts the MySQL server if it isn’t already running.
#     - Automatically connects to a default or user-specified database (`db_name`).
#     - Useful for projects requiring a database connection, allowing quick start-up.
#
# Script Execution Functions
#   - Functions dedicated to executing and managing custom PHP scripts.
#
#   run_script
#     - Executes PHP scripts located in the specified directory.
#     - Displays output and handles any errors that occur during execution.
#     - Allows running custom logic directly from the CLI in the specified project directory.
#
# Flag Handling
#   - Manage the command-line flags for the script to control behavior and options.
#     - `-p [port]`: Allows the user to specify a custom port number for the server.
#     - `-d [directory]`: Specifies a custom directory in which the server should run.
#     - `-D`: Activates MySQL functionality, including database checks and connections.
#     - `-h`: Triggers the help menu, showing available commands and usage examples.
#
# ---------------------------------------------------------------------------------------




RED='\033[1;91m'
GREEN='\033[1;92m'
YELLOW='\033[1;93m'
BLUE='\033[1;94m'
CYAN='\033[1;96m'    
MAGENTA='\033[1;95m' 
NC='\033[0m'         # No color (reset)

sleep 1
show_loader() {
    local delay=0.2
    local spin='/-\|'
    local i=0
    while kill -0 "$1" 2>/dev/null; do
        printf "\r${spin:i++%${#spin}:1} Loading..."
        sleep $delay
    done
    printf "\r"  # Clear the loader
}

(sleep 2) & 
dummy_pid=$!
show_loader "$dummy_pid"
wait "$dummy_pid" 

log() {
    local color="$1"
    shift
    echo -e "${color}$*${NC}"
}


show_logo=true
phpmyadmin=false
install=false
port=8000
directory=$(pwd)
ssh_output_file="$HOME/PhantomPHP_ssh_output.txt"
server_log="$HOME/bin/PhantomPHP_server_log.txt"


validate_port() {
    if ! [[ "$port" =~ ^[0-9]+$ ]] || [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
        echo -e "${RED}Invalid port number. Please specify a port between 1 and 65535.${NC}"
        exit 1
    fi
    
}
#check port function does not work ,lets just comment it
#Check_por(){
 # while lsof -i :$port &> /dev/null; do
  #      echo -e "${YELLOW}Port $port is already in use. Trying port $((port + 1))...${NC}"
  #      port=$((port + 1))
        
        # Exit if the port exceeds 65535
 #       if [ "$port" -gt 65535 ]; then
         #   echo -e "${RED}No available ports found below 65535.${NC}"
    #        exit 1
  #      fi
  #  done

  #  echo -e "${GREEN}Using port $port${NC}"
#}

install_server() {
  set -e
  show_loader
  log "${BLUE}" "Checking Dependencies..."
  sleep 2

  log "${BLUE}" "\nChecking if PHP is installed..."
  sleep 1

  if command -v php >/dev/null 2>&1; then
    log "${GREEN}" "PHP is installed\n"
  else
    log "${RED}" "PHP is not installed"
    read -p "Do you want to install PHP? (y/n): " choice
    if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
      log "${YELLOW}" "Installing PHP..."
      apt install php -y
      until command -v php >/dev/null 2>&1; do
        sleep 2
      done
      log "${GREEN}" "PHP installed successfully!\n"
    fi
  fi
  sleep 2

  log "${BLUE}" "Checking if MySQL is installed..."
  sleep 1

  if command -v mysql >/dev/null 2>&1; then
    log "${GREEN}" "MySQL is installed\n"
  else
    log "${RED}" "MySQL is not installed"
    read -p "Do you want to install MySQL? (y/n): " choice
    if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
      log "${YELLOW}" "Installing MySQL..."
      apt install phpmyadmin
      until command -v mysql >/dev/null 2>&1; do
        sleep 2
      done
      log "${GREEN}" "MySQL installed successfully!\n"
    fi
  fi
  sleep 2

  log "${BLUE}" "Checking if MariaDB is installed..."
  sleep 1

  if command -v mariadb >/dev/null 2>&1; then
    log "${GREEN}" "MariaDB is installed\n"
  else
    log "${RED}" "MariaDB is not installed"
    read -p "Do you want to install MariaDB? (y/n): " choice
    if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
      log "${YELLOW}" "Installing MariaDB..."
      apt install mariadb -y
      until command -v mariadb >/dev/null 2>&1; do
        sleep 2
      done
      log "${GREEN}" "MariaDB installed successfully!\n"
    fi
  fi

  log "${BLUE}" "Checking if Composer is installed..."
  sleep 1

  if command -v composer >/dev/null 2>&1; then
    log "${GREEN}" "Composer is installed\n"
  else
    log "${RED}" "Composer is not installed"
    read -p "Do you want to install Composer? (y/n): " choice
    if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
      log "${YELLOW}" "Downloading Composer installer..."
      php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
      log "${BLUE}" "Verifying Composer installer..."
      php -r "if (hash_file('sha384', 'composer-setup.php') === 'dac665fdc30fdd8ec78b38b9800061b4150413ff2e3b6f88543c636f7cd84f6db9189d43a81e5503cda447da73c7e5b6') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
      
      if [ $? -eq 0 ]; then
        log "${GREEN}" "Composer installer verified."
        php composer-setup.php
        php -r "unlink('composer-setup.php');"
        
        until command -v composer >/dev/null 2>&1; do
          sleep 2
        done
        
        mkdir -p "$HOME/bin"
        
        log "${YELLOW}" "Moving composer.phar to $HOME/bin..."
        mv composer.phar "$HOME/bin/composer"
        chmod +x "$HOME/bin/composer"
        
        if [[ ":$PATH:" != *":$HOME/bin:"* ]]; then
          log "${YELLOW}" "Adding $HOME/bin to PATH..."
          echo 'export PATH="$HOME/bin:$PATH"' >> "$HOME/.bashrc"
          source "$HOME/.bashrc"
        fi
        
        log "${GREEN}" "Composer installed successfully and moved to $HOME/bin!\n"
      else
        log "${RED}" "Composer installer verification failed."
        exit 1
      fi
    fi
  fi
  sleep 2


  log "${GREEN}" "Everything is installed. All set for Phantom-PHP!\n"
  sleep 1

  log "${YELLOW}" "Installing Phantom-PHP...\n"
  show_loader
  sleep 1

  log "${BLUE}" "Initializing phpMyAdmin server...\n"
  sleep 2

  echo -e "\n"
  echo -e "${GREEN}Starting phpMyAdmin server...${NC}"
  cd || exit

  mysql_install_db &> /dev/null
  mariadbd-safe -u root &> /dev/null &

  if cd ../usr/share/phpmyadmin &> /dev/null; then
    echo -e "${GREEN}Navigated to phpMyAdmin directory${NC}"
  else
    echo -e "${RED}phpMyAdmin directory not found!${NC}"
    return 1
  fi

  if [ -f "config.inc.php" ]; then
    echo -e "${YELLOW}config.inc.php file found. Removing old file...${NC}"
    rm config.inc.php &> /dev/null
  else
    echo -e "${YELLOW}No config file found. Creating a new one...${NC}"
  fi

  echo -e "${BLUE}Creating config.inc.php file...${NC}"

  cat <<EOF > config.inc.php &> /dev/null
<?php
/**
 * phpMyAdmin sample configuration, you can use it as base for
 * manual configuration. For easier setup you can use setup/
 *
 * All directives are explained in documentation in the doc/ folder
 * or at <https://docs.phpmyadmin.net/>.
 */

declare(strict_types=1);

/**
 * This is needed for cookie-based authentication to encrypt the cookie.
 * Needs to be a 32-bytes long string of random bytes. See FAQ 2.10.
 */
\$cfg['blowfish_secret'] = 'YOUR_RANDOM_32_BYTE_STRING_HERE'; /* YOU MUST FILL IN THIS FOR COOKIE AUTH! */

/**
 * Servers configuration
 */
\$i = 0;

/**
 * First server
 */
\$i++;
/* Authentication type */
\$cfg['Servers'][\$i]['auth_type'] = 'cookie';
/* Server parameters */
\$cfg['Servers'][\$i]['host'] = '127.0.0.1';
\$cfg['Servers'][\$i]['compress'] = false;
\$cfg['Servers'][\$i]['AllowNoPassword'] = true;

/**
 * phpMyAdmin configuration storage settings.
 */

/* User used to manipulate with storage */
// \$cfg['Servers'][\$i]['controlhost'] = '';
// \$cfg['Servers'][\$i]['controlport'] = '';
// \$cfg['Servers'][\$i]['controluser'] = 'pma';
// \$cfg['Servers'][\$i]['controlpass'] = 'pmapass';

/* Storage database and tables */
// \$cfg['Servers'][\$i]['pmadb'] = 'phpmyadmin';
// \$cfg['Servers'][\$i]['bookmarktable'] = 'pma__bookmark';
// \$cfg['Servers'][\$i]['relation'] = 'pma__relation';
// \$cfg['Servers'][\$i]['table_info'] = 'pma__table_info';
// \$cfg['Servers'][\$i]['table_coords'] = 'pma__table_coords';
// \$cfg['Servers'][\$i]['pdf_pages'] = 'pma__pdf_pages';
// \$cfg['Servers'][\$i]['column_info'] = 'pma__column_info';
// \$cfg['Servers'][\$i]['history'] = 'pma__history';
// \$cfg['Servers'][\$i]['table_uiprefs'] = 'pma__table_uiprefs';
// \$cfg['Servers'][\$i]['tracking'] = 'pma__tracking';
// \$cfg['Servers'][\$i]['userconfig'] = 'pma__userconfig';
// \$cfg['Servers'][\$i]['recent'] = 'pma__recent';
// \$cfg['Servers'][\$i]['favorite'] = 'pma__favorite';
// \$cfg['Servers'][\$i]['users'] = 'pma__users';
// \$cfg['Servers'][\$i]['usergroups'] = 'pma__usergroups';
// \$cfg['Servers'][\$i]['navigationhiding'] = 'pma__navigationhiding';
// \$cfg['Servers'][\$i]['savedsearches'] = 'pma__savedsearches';
// \$cfg['Servers'][\$i]['central_columns'] = 'pma__central_columns';
// \$cfg['Servers'][\$i]['designer_settings'] = 'pma__designer_settings';
// \$cfg['Servers'][\$i]['export_templates'] = 'pma__export_templates';

/**
 * End of servers configuration
 */

/**
 * Directories for saving/loading files from server
 */
\$cfg['UploadDir'] = '';
\$cfg['SaveDir'] = '';

EOF

  if [ $? -eq 0 ]; then
    echo -e "${GREEN}phpMyAdmin setup completed!${NC}"
  else
    echo -e "${RED}Failed to create config.inc.php file.${NC}"
  fi
}

#port port_frowarding function for forwarding local host 🤦
#we used serveo
port_frowarding(){
    echo -e "${YELLOW}Establishing SSH tunnel for PhantomPHP Server...${NC}"
    show_loader

    # Define SSH output file path
    ssh_output_file="$HOME/bin/ssh_output.txt"

    # Ensure the output file exists
    if [ ! -f "$ssh_output_file" ]; then
        touch "$ssh_output_file"
    fi

    # Start SSH tunnel with remote forwarding and redirect output
    ssh_command="ssh -R 80:localhost:$port serveo.net > $ssh_output_file 2>&1 &"
    eval $ssh_command
    sleep 2

    # Extract the tunnel URL
    tunnel_url=""
    while [ -z "$tunnel_url" ]; do
        if [ -f "$ssh_output_file" ]; then
            tunnel_url=$(grep -o "https://[^\s]*serveo.net" "$ssh_output_file")
            if [ ! -z "$tunnel_url" ]; then
                echo -e "${GREEN}Tunnel URL: $tunnel_url${NC}"
                break
            fi
        fi
        sleep 1
    done

    # Check if tunnel URL was found
    if [ -z "$tunnel_url" ]; then
        echo -e "${RED}Failed to establish SSH tunnel. Check ssh_output.txt for details.${NC}"
        echo -e "${YELLOW}SSH Output Log:${NC}"
        cat "$ssh_output_file"
    else
        echo -e "${GREEN}SSH tunnel established successfully!${NC}"
    fi
}
#run php files function 
script_run() {
    file="$1.php"
             echo -e "\n"
    echo -e "${BLUE} attempting to run $file"
             echo -e "\n"

    show_loader
    if [ -f "$file" ]; then
        php "$file"
    else
         echo -e "\n"
        echo -e "${RED}File $file not found.${NC}"
        exit 1
    fi
}
show_help() {
    echo -e "${CYAN}==============================================${NC}"
    echo -e "${MAGENTA}             ${GREEN}Usage Guide${NC}             ${MAGENTA}"
    echo -e "${CYAN}==============================================${NC}"
    echo ""
    echo -e "${BLUE}Command:${NC} ${CYAN}serve [options]${NC}"
    echo ""
    echo -e "${YELLOW}Options:${NC}"
    echo -e "  ${GREEN}-h | --help${NC}                ${YELLOW}Display help and usage information.${NC}"
    echo -e "  ${GREEN}-p | --port ${YELLOW}<port>${NC}          ${YELLOW}Specify the port number (e.g., ${GREEN}--port 8080${YELLOW}).${NC}"
    echo -e "  ${GREEN}-d | --dir ${YELLOW}<directory>${NC}     ${YELLOW}Specify the working directory (e.g., ${GREEN}--dir /path/to/dir${YELLOW}).${NC}"
    echo -e "  ${GREEN}-g | --github${NC}               ${YELLOW}Open the GitHub repository in your browser.${NC}"
    echo -e "  ${GREEN}-f | --forward${NC}              ${YELLOW}Enable forwarding mode.${NC}"
    echo -e "  ${GREEN}-R | --run ${YELLOW}<file>${NC}          ${YELLOW}Run a specific PHP file (e.g., ${GREEN}--run script.php${YELLOW}).${NC}"
    echo ""
    echo -e "${CYAN}Examples:${NC}"
    echo -e "  ${GREEN}serve --help${NC}                ${YELLOW}Display the help information.${NC}"
    echo -e "  ${GREEN}serve --port 8080${NC}           ${YELLOW}Set the port to 8080.${NC}"
    echo -e "  ${GREEN}serve --dir /path/to/dir${NC}    ${YELLOW}Set the working directory.${NC}"
    echo -e "  ${GREEN}serve --github${NC}              ${YELLOW}Open the GitHub repository.${NC}"
    echo -e "  ${GREEN}serve --run script.php${NC}      ${YELLOW}Run the script.php PHP file.${NC}"
    echo ""
    echo -e "${CYAN}==============================================${NC}"
    echo -e "${MAGENTA}             ${GREEN}End of Guide${NC}             ${MAGENTA}"
    echo -e "${CYAN}==============================================${NC}"
}

mysql_db() {
    cd || exit

    if ! cd ../usr/share/phpmyadmin; then
        echo -e "${RED}Error: /usr/share/phpmyadmin not found${NC}"
        return 1
    fi
    port="${1:-8080}" 
    echo -e "\n${YELLOW}Attempting to start phpMyAdmin server at http://localhost:$port ${NC}\n"
    php -S localhost:"$port" &> "$server_log" &
    server_pid=$!
    sleep 1

    if ps -p $server_pid > /dev/null; then
        echo -e "${GREEN}phpMyAdmin server started at http://localhost:$port${NC}"
    else
        echo -e "${RED}Failed to start the server on port $port. It may be in use. Try a different port or check server_log.txt for details.${NC}"
        cat "$server_log"
    fi
}

run_server=true

while [ "$1" != "" ]; do
  case $1 in
    -h | --help)
      show_help
       install=false

      exit 0
      ;;
-v | --version)
      showversion=true
      show_logo=false
      phpmyadmin=false
  echo -e "\n"
echo -e "${GREEN}PhantomPHP - Installed Version 1.0${NC}"
echo -e "${YELLOW}-----------------------------------------${NC}"
echo -e "${BLUE}Version Check: ${NC}1.0"
echo -e "${YELLOW}-----------------------------------------${NC}"
      exit 0
      ;;
    -s | --serve)
      shift
      port=$1
      serve
      show_logo
     install=false

      ;;
    -i | --install)
      install=true
      show_logo=true
      phpmyadmin=false
      run_server=false
      ;;
    -p | --port)
      shift
      port=$1
      validate_port
           install=false

      ;;
    -f | --forward)
      forward="true"
           install=false

      ;;
    -d | --dir)
      shift
      directory=$1
      if [ ! -d "$directory" ]; then
        echo -e "${RED}Directory $directory does not exist.${NC}"
        exit 1
      fi
           install=false

      ;;
    -g | --github)
      echo -e "\n"
      echo -e "${GREEN}Opening GitHub Repository...${NC}"
      if ! xdg-open "https://github.com/codetesla51/phantom-php" &> /dev/null; then
        echo -e "${RED}Failed to open GitHub repository.${NC}"
      fi
           install=false

      exit 0
      ;;
    -R | --run)
      shift
      file=$1
      script_run "$file"
           install=false

      exit 
      ;;
    -D | --db)
      shift
      port=$1
      validate_port
      phpmyadmin=true
      run_server=false 
      show_logo=false
           install=false

      ;;
    *)
      echo "Invalid option: $1"
      show_help
      exit 1
      ;;
  esac
  shift
done


if [ "$show_logo" = true ]; then
    clear
    sleep 1
    echo -e "${GREEN}
           ▄▄▄▄▄▄▄▄▄▄▄▄
        ▄█▀▀▀▀▀▀▀▀▀▀▀▀▀█▄
      ▄█▀     ▄▄▄▄▄▄     ▀█▄
     ██     ██████████     ██
    ██      ██████████      ██
     ██     ██████████     ██
       ▀█▄    ▀████▀    ▄█▀u
          ▀▀▀▄▄▄▄▄▄▄▀▀▀

         PhantomPHP Server
      Fast and Reliable.

         Made by Uthman Dev
    ${NC}"
    echo -e "\n"
fi

display_server_info() {
    printf "\n\n"
    echo -e "${YELLOW}Starting PhantomPHP Server...${NC}"
    printf "\n"
    echo -e "${GREEN}Serving PHP app at http://localhost:$port${NC}"
    printf "\n"
    echo -e "${BLUE}Opening in device Browser${NC}"
    printf "\n"
    echo -e "${BLUE}Serving files from: $directory${NC}"
    printf "\n"
}

serve(){
    validate_port
    display_server_info

    echo -e "\n${YELLOW}Attempting to start PHP server at http://localhost:$port ${NC}\n"
    php -S localhost:$port -t "$directory" &> $server_log &
    server_pid=$!
    
    sleep 1
    if ps -p $server_pid > /dev/null; then
        echo -e "${GREEN}PHP server started at http://localhost:$port${NC}"
    else
        echo -e "${RED}Failed to start the server on port $port. It may be in use. Try a different port or check server_log.txt for details.${NC}"
       cat "$server_log"

    fi
}
if [ "$run_server" = true ]; then
    serve

    if ps -p $server_pid > /dev/null; then
        if command -v xdg-open &> /dev/null; then
            xdg-open "http://localhost:$port"
        elif command -v termux-open &> /dev/null; then
            termux-open "http://localhost:$port"
        else
            echo -e "${RED}Error: No compatible browser open command found.${NC}"
        fi
    
    fi
fi

if [ "$phpmyadmin" = "true" ]; then
    mysql_db
  elif [ "$forward" = "true" ]; then
    port_frowarding
  elif [ "$install" = "true" ]; then
    install_server
fi
wait
