#!/bin/bash

################################################################################
# Storage Symlink Diagnostic Script
# Purpose: Diagnose why storage symlink is not accessible via Apache/cPanel
# Usage: ./scripts/diagnose-storage-symlink.sh
################################################################################

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"

echo "════════════════════════════════════════════════════════════════════════════"
echo "  STORAGE SYMLINK DIAGNOSTIC REPORT"
echo "════════════════════════════════════════════════════════════════════════════"
echo ""

cd "$PROJECT_ROOT"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

function print_section() {
    echo ""
    echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
    echo -e "${BLUE}  $1${NC}"
    echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
    echo ""
}

function print_ok() {
    echo -e "${GREEN}✓${NC} $1"
}

function print_error() {
    echo -e "${RED}✗${NC} $1"
}

function print_warning() {
    echo -e "${YELLOW}⚠${NC} $1"
}

function print_info() {
    echo -e "  $1"
}

################################################################################
# 1. ENVIRONMENT INFORMATION
################################################################################

print_section "1. ENVIRONMENT INFORMATION"

echo "Current Working Directory:"
print_info "$(pwd)"
echo ""

echo "User/Group:"
print_info "User: $(whoami)"
print_info "UID: $(id -u)"
print_info "GID: $(id -g)"
print_info "Groups: $(id -Gn)"
echo ""

echo "Hostname:"
print_info "$(hostname)"
echo ""

echo "Kernel:"
print_info "$(uname -a)"
echo ""

echo "PHP Version:"
if command -v php &> /dev/null; then
    print_info "$(php -v | head -n 1)"
else
    print_warning "PHP not found in PATH"
fi
echo ""

################################################################################
# 2. SYMLINK STATUS
################################################################################

print_section "2. SYMLINK STATUS"

echo "Checking public/storage symlink:"
if [ -L "public/storage" ]; then
    print_ok "Symlink exists"
    print_info "Type: $(ls -ld public/storage | awk '{print $1}')"
    print_info "Target (readlink): $(readlink public/storage)"
    print_info "Full path (readlink -f): $(readlink -f public/storage 2>/dev/null || echo 'N/A')"
    print_info "Owner: $(ls -ld public/storage | awk '{print $3":"$4}')"
elif [ -d "public/storage" ]; then
    print_warning "public/storage exists but is a DIRECTORY, not a symlink"
    print_info "$(ls -ld public/storage)"
elif [ -e "public/storage" ]; then
    print_error "public/storage exists but is not a symlink or directory"
    print_info "$(ls -ld public/storage)"
else
    print_error "public/storage does not exist"
fi
echo ""

echo "Checking storage/app/public directory:"
if [ -d "storage/app/public" ]; then
    print_ok "Target directory exists"
    print_info "$(ls -ld storage/app/public)"
    print_info "Permissions: $(stat -c '%a' storage/app/public 2>/dev/null || stat -f '%Lp' storage/app/public 2>/dev/null)"
    print_info "Owner: $(ls -ld storage/app/public | awk '{print $3":"$4}')"

    echo ""
    echo "Contents of storage/app/public:"
    ls -lah storage/app/public | head -20
else
    print_error "storage/app/public does not exist"
fi
echo ""

echo "Test file in storage/app/public:"
if [ -f "storage/app/public/test.txt" ]; then
    print_ok "test.txt exists"
    print_info "$(ls -l storage/app/public/test.txt)"
    print_info "Content: $(cat storage/app/public/test.txt)"
else
    print_warning "test.txt does not exist (creating now...)"
    echo "diagnostic_test_$(date +%s)" > storage/app/public/test.txt
    chmod 644 storage/app/public/test.txt
    print_ok "Created test.txt"
fi
echo ""

################################################################################
# 3. SYMLINK TRAVERSAL TEST
################################################################################

print_section "3. SYMLINK TRAVERSAL TEST"

echo "Can we access files through the symlink?"
if [ -L "public/storage" ]; then
    if [ -e "public/storage/test.txt" ]; then
        print_ok "File accessible through symlink path"
        print_info "$(ls -l public/storage/test.txt)"
    else
        print_error "File NOT accessible through symlink path"
        print_info "Symlink may be broken or blocked"
    fi

    echo ""
    echo "Testing cd into symlink:"
    if cd public/storage 2>/dev/null; then
        print_ok "Can cd into symlink"
        print_info "PWD: $(pwd)"
        cd "$PROJECT_ROOT"
    else
        print_error "Cannot cd into symlink"
    fi
else
    print_warning "Skipping (symlink doesn't exist)"
fi
echo ""

################################################################################
# 4. APACHE/WEB SERVER CONFIGURATION
################################################################################

print_section "4. APACHE/WEB SERVER CONFIGURATION"

echo "Checking .htaccess in public/:"
if [ -f "public/.htaccess" ]; then
    print_ok ".htaccess exists"
    echo ""
    echo "Content:"
    cat public/.htaccess
    echo ""

    if grep -q "FollowSymLinks" public/.htaccess; then
        print_ok "FollowSymLinks option found in .htaccess"
    else
        print_warning "FollowSymLinks option NOT found in .htaccess"
    fi
else
    print_error "public/.htaccess does not exist"
fi
echo ""

echo "Checking .htaccess in public/storage/:"
if [ -L "public/storage" ] && [ -f "public/storage/.htaccess" ]; then
    print_ok ".htaccess exists in storage"
    cat public/storage/.htaccess
elif [ -d "public/storage" ] && [ -f "public/storage/.htaccess" ]; then
    print_ok ".htaccess exists in storage (directory)"
    cat public/storage/.htaccess
else
    print_warning "No .htaccess in public/storage/"
fi
echo ""

echo "Apache configuration (if accessible):"
if [ -f "/etc/httpd/conf/httpd.conf" ]; then
    print_info "Main config: /etc/httpd/conf/httpd.conf"
    grep -i "FollowSymLinks\|SymLinksIfOwnerMatch" /etc/httpd/conf/httpd.conf 2>/dev/null | head -5 || print_warning "Cannot read httpd.conf"
elif [ -f "/etc/apache2/apache2.conf" ]; then
    print_info "Main config: /etc/apache2/apache2.conf"
    grep -i "FollowSymLinks\|SymLinksIfOwnerMatch" /etc/apache2/apache2.conf 2>/dev/null | head -5 || print_warning "Cannot read apache2.conf"
else
    print_warning "Apache config not accessible (cPanel restriction)"
fi
echo ""

################################################################################
# 5. SELINUX / SECURITY MODULES
################################################################################

print_section "5. SELINUX / SECURITY MODULES"

echo "SELinux Status:"
if command -v getenforce &> /dev/null; then
    SELINUX_STATUS=$(getenforce 2>/dev/null || echo "Unknown")
    if [ "$SELINUX_STATUS" = "Enforcing" ]; then
        print_warning "SELinux is ENFORCING (may block symlinks)"
        print_info "Status: $SELINUX_STATUS"

        echo ""
        echo "SELinux context for storage:"
        ls -Z storage/app/public 2>/dev/null | head -5 || print_warning "Cannot get SELinux context"

        echo ""
        echo "SELinux context for public/storage:"
        ls -Z public/storage 2>/dev/null | head -5 || print_warning "Cannot get SELinux context"
    elif [ "$SELINUX_STATUS" = "Permissive" ]; then
        print_info "SELinux is in permissive mode (allows symlinks)"
    else
        print_ok "SELinux is disabled"
    fi
else
    print_info "SELinux not installed (likely not the issue)"
fi
echo ""

echo "AppArmor Status:"
if command -v aa-status &> /dev/null; then
    print_warning "AppArmor detected"
    aa-status 2>/dev/null | head -10 || print_info "Cannot read AppArmor status"
else
    print_info "AppArmor not installed"
fi
echo ""

################################################################################
# 6. FILESYSTEM CAPABILITIES
################################################################################

print_section "6. FILESYSTEM CAPABILITIES"

echo "Testing symlink creation:"
TEST_DIR=$(mktemp -d -p /tmp)
echo "test" > "$TEST_DIR/source.txt"
ln -s "$TEST_DIR/source.txt" "$TEST_DIR/link.txt" 2>/dev/null

if [ -L "$TEST_DIR/link.txt" ]; then
    print_ok "System supports symlinks"
    if [ -e "$TEST_DIR/link.txt" ]; then
        print_ok "Symlinks are traversable"
    else
        print_error "Symlinks created but not traversable!"
    fi
else
    print_error "System does NOT support symlinks"
fi
rm -rf "$TEST_DIR"
echo ""

echo "Filesystem type:"
DF_OUTPUT=$(df -T . 2>/dev/null | tail -1)
print_info "$DF_OUTPUT"
echo ""

################################################################################
# 7. PHP CONFIGURATION
################################################################################

print_section "7. PHP CONFIGURATION"

if command -v php &> /dev/null; then
    echo "PHP open_basedir restriction:"
    OPEN_BASEDIR=$(php -r "echo ini_get('open_basedir');" 2>/dev/null || echo "")
    if [ -z "$OPEN_BASEDIR" ]; then
        print_ok "open_basedir is not set (no restriction)"
    else
        print_warning "open_basedir is SET: $OPEN_BASEDIR"
        print_info "This may prevent symlink access outside allowed paths"
    fi
    echo ""

    echo "PHP disable_functions:"
    DISABLED_FUNCS=$(php -r "echo ini_get('disable_functions');" 2>/dev/null || echo "")
    if [ -z "$DISABLED_FUNCS" ]; then
        print_ok "No functions disabled"
    else
        print_info "Disabled: $DISABLED_FUNCS"
    fi
    echo ""

    echo "PHP safe_mode (deprecated but may exist):"
    SAFE_MODE=$(php -r "echo ini_get('safe_mode');" 2>/dev/null || echo "")
    if [ -z "$SAFE_MODE" ] || [ "$SAFE_MODE" = "0" ]; then
        print_ok "safe_mode is off"
    else
        print_warning "safe_mode is ON: $SAFE_MODE"
    fi
else
    print_warning "PHP not available for testing"
fi
echo ""

################################################################################
# 8. WEB SERVER ACCESS TEST
################################################################################

print_section "8. WEB SERVER ACCESS TEST"

echo "Attempting to fetch via HTTP:"

# Try to detect the domain
if [ -f ".env" ]; then
    APP_URL=$(grep "^APP_URL=" .env | cut -d= -f2- | tr -d '"' | tr -d "'")
    if [ -n "$APP_URL" ]; then
        print_info "APP_URL from .env: $APP_URL"

        TEST_URL="$APP_URL/storage/test.txt"
        echo ""
        echo "Testing: $TEST_URL"

        HTTP_CODE=$(curl -s -o /tmp/curl_output.txt -w "%{http_code}" "$TEST_URL" 2>/dev/null || echo "000")

        if [ "$HTTP_CODE" = "200" ]; then
            print_ok "HTTP 200 - File accessible!"
            print_info "Response: $(cat /tmp/curl_output.txt)"
        elif [ "$HTTP_CODE" = "404" ]; then
            print_error "HTTP 404 - File not found"
            print_info "Response: $(cat /tmp/curl_output.txt | head -5)"
        elif [ "$HTTP_CODE" = "403" ]; then
            print_error "HTTP 403 - Forbidden (permission issue)"
            print_info "Response: $(cat /tmp/curl_output.txt | head -5)"
        elif [ "$HTTP_CODE" = "500" ]; then
            print_error "HTTP 500 - Server error"
            print_info "Response: $(cat /tmp/curl_output.txt | head -5)"
        else
            print_error "HTTP $HTTP_CODE - Unknown error"
        fi
        rm -f /tmp/curl_output.txt
    else
        print_warning "APP_URL not set in .env"
    fi
else
    print_warning ".env file not found"
fi
echo ""

################################################################################
# 9. ERROR LOGS
################################################################################

print_section "9. ERROR LOGS"

echo "Recent Laravel errors (last 20 lines):"
if [ -d "storage/logs" ]; then
    LATEST_LOG=$(ls -t storage/logs/laravel-*.log 2>/dev/null | head -1)
    if [ -n "$LATEST_LOG" ]; then
        print_info "Log file: $LATEST_LOG"
        echo ""
        tail -20 "$LATEST_LOG" | grep -i "storage\|symlink\|404\|403" || print_info "No storage-related errors in last 20 lines"
    else
        print_warning "No Laravel log files found"
    fi
else
    print_error "storage/logs directory does not exist"
fi
echo ""

echo "Apache error logs (if accessible):"
if [ -r "/var/log/httpd/error_log" ]; then
    tail -20 /var/log/httpd/error_log | grep -i "storage\|symlink\|FollowSymLinks" || print_info "No relevant errors"
elif [ -r "/var/log/apache2/error.log" ]; then
    tail -20 /var/log/apache2/error.log | grep -i "storage\|symlink\|FollowSymLinks" || print_info "No relevant errors"
else
    print_warning "Apache error logs not accessible (cPanel restriction)"
fi
echo ""

################################################################################
# 10. CPANEL DETECTION
################################################################################

print_section "10. CPANEL DETECTION"

if [ -d "/usr/local/cpanel" ]; then
    print_warning "cPanel detected - symlinks may be restricted by hosting provider"

    if [ -f "/var/cpanel/version" ]; then
        print_info "cPanel version: $(cat /var/cpanel/version)"
    fi

    echo ""
    echo "cPanel may restrict symlinks for security. Possible solutions:"
    print_info "1. Contact hosting provider to enable SymLinksIfOwnerMatch"
    print_info "2. Use file copying instead of symlinks"
    print_info "3. Request VPS/dedicated hosting for full control"
else
    print_info "cPanel not detected"
fi
echo ""

################################################################################
# 11. RECOMMENDATIONS
################################################################################

print_section "11. RECOMMENDATIONS"

echo "Based on diagnostic results:"
echo ""

# Check if symlink exists and is correct
if [ ! -L "public/storage" ]; then
    print_error "ISSUE: Symlink does not exist"
    print_info "→ Run: php artisan storage:link"
elif [ "$(readlink public/storage)" = "/home/"* ]; then
    print_error "ISSUE: Symlink uses absolute path"
    print_info "→ Run: rm public/storage && ln -s ../../storage/app/public public/storage"
fi

# Check permissions
if [ -d "storage/app/public" ]; then
    PERMS=$(stat -c '%a' storage/app/public 2>/dev/null || stat -f '%Lp' storage/app/public 2>/dev/null)
    if [ "$PERMS" != "755" ]; then
        print_error "ISSUE: storage/app/public has permissions $PERMS (should be 755)"
        print_info "→ Run: chmod 755 storage/app/public"
    fi
fi

# Check .htaccess
if [ -f "public/.htaccess" ]; then
    if ! grep -q "FollowSymLinks" public/.htaccess; then
        print_error "ISSUE: .htaccess missing FollowSymLinks option"
        print_info "→ Add: Options +FollowSymLinks"
    fi
fi

# Check if cPanel is blocking
if [ -d "/usr/local/cpanel" ] && [ "$HTTP_CODE" = "404" ]; then
    print_warning "LIKELY ISSUE: cPanel is blocking symlink traversal"
    print_info "→ Solution 1: Contact hosting support to enable symlinks"
    print_info "→ Solution 2: Use rsync to copy files to public/storage"
    print_info "→ Solution 3: Modify upload code to save directly to public/storage"
fi

echo ""
print_section "END OF DIAGNOSTIC REPORT"
echo ""
