#!/bin/bash

# Function to detect the appropriate Docker Compose command
detect_docker_compose_command() {
    if docker compose version &>/dev/null; then
        echo "docker compose"
    else
        echo "docker-compose"
    fi
}

# Function to determine the environment files to use
get_env_files() {
    local env_files=(".env")
    for envFile in ".env.local" "env.local"; do
        if [ -f "$envFile" ]; then
            env_files+=("$envFile")
            break
        fi
    done
    echo "${env_files[@]}"
}

# Function to check Docker and Docker Compose versions and display additional information
stack_status() {
    check_compose_version

    # Get container status
    echo "Container Status:"
    $DOCKER_COMPOSE_CMD ps
    echo

    # Get resource usage
    echo "Resource Usage:"
    $DOCKER_COMPOSE_CMD top
    echo

    display_rabbitmq_info
    echo 

    display_db_info
}

# Function to display information about the environment
display_info() {
    echo "Checking environment information..."
    echo

    # Kernel version (Linux and macOS compatible)
    echo "Kernel Version:"
    uname -sr
    echo
    
    check_compose_version

    local env_files=($(get_env_files))
    for env_file in "${env_files[@]}"; do
        if [ -f "$env_file" ]; then
            set -a
            source "$env_file"
            set +a
        fi
    done
    
    # Display Docker tag and registry information
    echo "Phraseanet Docker Tag: ${PHRASEANET_DOCKER_TAG:-Not set}"
    echo "Phraseanet Docker Registry: ${PHRASEANET_DOCKER_REGISTRY:-Not set}"
    echo

    # Construct and display the internal URL of the Phraseanet instance
    if [ -n "$PHRASEANET_HOSTNAME" ] && [ -n "$PHRASEANET_SCHEME" ] && [ -n "$PHRASEANET_APP_PORT" ]; then
        local internal_url="${PHRASEANET_SCHEME}://${PHRASEANET_HOSTNAME}:${PHRASEANET_APP_PORT}"
        echo "Internal URL of Phraseanet Instance: $internal_url"
        echo
    else
        echo "Internal URL of Phraseanet Instance: Cannot be determined (missing environment variables)."
        echo
    fi

    # Check if Phraseanet is installed by looking for config/configuration.yml
    if [ -f "config/configuration.yml" ]; then
        echo "Phraseanet is installed: config/configuration.yml found."

        # Get creation date of the configuration file
        local creation_date=$(date -r "$(stat -f %B "config/configuration.yml" 2>/dev/null || stat -c %Y "config/configuration.yml" 2>/dev/null)" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "Unknown")
        echo "Installation Date (configuration.yml creation date): $creation_date"

        # Check for the compiled configuration file and get its last modification date
        if [ -f "config/configuration-compiled.php" ]; then
            local last_modified_date=$(date -r "$(stat -f %m "config/configuration-compiled.php" 2>/dev/null || stat -c %Y "config/configuration-compiled.php" 2>/dev/null)" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "Unknown")
            echo "Last Update Date (configuration-compiled.yml update date): $last_modified_date"
            echo
        else
            echo "Last Update unknown, config/configuration-compiled.php not found."
            echo
        fi

        # Check if the Phraseanet container is running
        if $DOCKER_COMPOSE_CMD ps | grep -q "phraseanet.*Up"; then
            echo "Phraseanet container is running. Fetching version information..."

            # Extract version from Version.php file
            local version_php_file="lib/Alchemy/Phrasea/Core/Version.php"
            if [ -f "$version_php_file" ]; then
                local version_from_file=$(grep -o "private \$number = '[^']*" "$version_php_file" | sed "s/private \$number = '//;s/'//")
                echo "Version from Version.php: $version_from_file"
            else
                echo "Version.php file not found."
            fi

            # Execute the command to get Phraseanet version from console
            local version_from_console=$($DOCKER_COMPOSE_CMD exec phraseanet sh -c 'bin/console --version | grep -o "KONSOLE KOMMANDER version [^ ]* [^ ]*" | awk "{print \$NF}"')
            echo "Version from console: $version_from_console"

            # Compare versions
            if [ "$version_from_file" == "$version_from_console" ]; then
                echo "Versions match."
                echo
            else
                echo "Versions do not match."
                echo
            fi
        else
            # Extract version from Version.php file
            local version_php_file="lib/Alchemy/Phrasea/Core/Version.php"
            if [ -f "$version_php_file" ]; then
                local version_from_file=$(grep -o "private \$number = '[^']*" "$version_php_file" | sed "s/private \$number = '//;s/'//")
                echo "Version from Version.php: $version_from_file"
            else
                echo "Version.php file not found."
            fi
            echo "Phraseanet container is not running. Cannot fetch version information from container."
            echo
        fi
    else
        echo "Phraseanet is not installed: config/configuration.yml not found."
        echo
    fi

    # Fetch the latest version from GitHub
    echo "Fetching the latest Phraseanet version from GitHub..."
    local latest_version=$(curl -s https://api.github.com/repos/alchemy-fr/Phraseanet/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
    echo "Latest Phraseanet Version on GitHub: $latest_version"
    echo
}

# Function to display logs
display_logs() {
    if [ -n "$1" ]; then
        echo "Displaying logs for container: $1"
        $DOCKER_COMPOSE_CMD logs -f "$1"
    else
        echo "Displaying logs for all containers"
        $DOCKER_COMPOSE_CMD logs -f
    fi
}

DOCKER_COMPOSE_CMD=$(detect_docker_compose_command)

# Function to start the Docker stack
start_stack() {
    echo "Starting the Docker stack..."
    local env_files=($(get_env_files))
    $DOCKER_COMPOSE_CMD "${env_files[@]/#/--env-file=}" up -d
}

# Function to stop the Docker stack
stop_stack() {
    echo "Stopping the Docker stack..."
    local env_files=($(get_env_files))
    $DOCKER_COMPOSE_CMD down
}

# Function rabbimq queue information
display_rabbitmq_info() {
    echo "RabbitMQ queue informations :"
    $DOCKER_COMPOSE_CMD exec rabbitmq sh -c 'rabbitmqctl --version  & rabbitmqctl list_queues --vhost $PHRASEANET_RABBITMQ_VHOST'
    echo
}

# Function check compose version
check_compose_version() {
    local compose_version=$($DOCKER_COMPOSE_CMD version --short)
    if [[ $compose_version == *"v2"* ]]; then
        echo "Docker Compose v2 detected."
    else
        echo "Docker Compose v1 detected."
    fi

    local required_docker_version="27.3.1"
    local required_compose_version="2.30.3"

    # Get Docker version
    local docker_version=$(docker --version | awk -F'[ ,]' '{print $3}')
    if [ "$(printf '%s\n' "$required_docker_version" "$docker_version" | sort -V | head -n1)" != "$required_docker_version" ]; then
        echo "Error: Docker version $docker_version is less than the required version $required_docker_version."
        exit 1
    fi

    # Get Docker Compose version
    local compose_version=$($DOCKER_COMPOSE_CMD version --short)
    if [ "$(printf '%s\n' "$required_compose_version" "$compose_version" | sort -V | head -n1)" != "$required_compose_version" ]; then
        echo "Error: Docker Compose version $compose_version is less than the required version $required_compose_version."
        exit 1
    fi

    echo "Docker and Docker Compose versions are compatible."
    echo "Docker Version: $docker_version"
    echo "Docker Compose Version: $compose_version"
    echo
}

# Function db status
display_db_info () {
    echo "DB status"
    $DOCKER_COMPOSE_CMD exec db sh -c 'env |grep MYSQL_ & mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SHOW DATABASES;SHOW PROCESSLIST;"'
    echo
}
 # Function to enable or disable maintenance mode
maintenance_mode() {
    if [ "$1" == "on" ]; then
        echo "Enabling maintenance mode..."
        $DOCKER_COMPOSE_CMD exec phraseanet sh -c 'envsubst < "/usr/local/etc/maintenance.html" > /var/alchemy/Phraseanet/datas/nginx/maintenance.html'
        echo "Maintenance mode is now enabled. it will be disabling after the next restart of stack."
        echo "if you want persist maintenance mode, you must set the environment variable PHRASEANET_MAINTENANCE_MODE=1 in your .env file."
    elif [ "$1" == "off" ]; then
        echo "Disabling maintenance mode..."
        $DOCKER_COMPOSE_CMD exec phraseanet sh -c 'rm -rf /var/alchemy/Phraseanet/datas/nginx/maintenance.html'
        echo "Maintenance mode is now disabled."
    else
        echo "Usage: $0 maintenance {on|off}"
        exit 1
    fi
}
# Function to apply setup
apply_setup() {
    echo "Applying setup..."
    local env_files=($(get_env_files))
    $DOCKER_COMPOSE_CMD "${env_files[@]/#/--env-file=}" run --rm setup
    if [ $? -eq 0 ]; then
        echo "Setup applied successfully."
    else
        echo "Failed to apply setup."
        exit 1
    fi
}
# Check the argument passed to the script
case "$1" in
    start)
        start_stack
        ;;
    stop)
        stop_stack
        ;;
    status)
        stack_status
        ;;
    version)
        display_info
        ;;
    logs)
        display_logs "$2"
        ;;
    maintenance)
        if [ -n "$2" ]; then
            maintenance_mode "$2"
        else
            echo "Usage: $0 maintenance {on|off}"
            exit 1
        fi
        ;;
    apply-setup)
        apply_setup
        ;;
    *)
        echo "Usage: $0 {start|stop|status|version|maintenance [on|off]|logs [container_name]|apply-setup}"
        exit 1
esac

exit 0
