#!/bin/bash
set -e

# Cloudron app startup script for Ente
echo "==> Starting Ente Cloudron app..."

# We need to be careful with file permissions, as /app/data is the only writable location
mkdir -p /app/data/patched
chmod -R 777 /app/data/patched
echo "==> Created and set full permissions (777) on /app/data/patched directory"

echo "==> NOTE: Running in Cloudron environment with limited write access"
echo "==> Writable directories: /app/data, /tmp, /run"

# Configure important paths
MUSEUM_DIR="/app/code/server"
CONFIG_DIR="/app/data/config"
LOGS_DIR="/app/data/logs"
WEB_DIR="/app/web"
CADDY_DATA_DIR="/app/data/caddy"

# Create necessary directories
mkdir -p "$CONFIG_DIR" "$LOGS_DIR" "$CADDY_DATA_DIR"

# Determine the endpoint configuration 
CLOUDRON_APP_FQDN="${CLOUDRON_APP_DOMAIN}"
if [ -n "${CLOUDRON_APP_ORIGIN}" ]; then
    CLOUDRON_APP_FQDN="${CLOUDRON_APP_DOMAIN}"
else
    # If origin not set, use the app domain
    CLOUDRON_APP_ORIGIN="https://${CLOUDRON_APP_DOMAIN}"
fi

API_ENDPOINT="/api"
CADDY_PORT="3080"
API_PORT="8080"
PUBLIC_ALBUMS_PORT="8081"

echo "==> Using server directory: ${MUSEUM_DIR}"

# Check if we have S3 configuration
if [ -f "${CONFIG_DIR}/s3.env" ]; then
    echo "==> Using existing S3 configuration"
    source "${CONFIG_DIR}/s3.env"
    echo "==> S3 Configuration:"
    echo "Endpoint: ${S3_ENDPOINT}"
    echo "Region: ${S3_REGION}"
    echo "Bucket: ${S3_BUCKET}"
else
    echo "==> Creating default S3 configuration file"
    # Create empty S3 env file for later configuration
    cat > "${CONFIG_DIR}/s3.env" << EOF
# S3 Configuration for Ente
# Uncomment and fill in the following values:
# S3_ENDPOINT=https://s3.example.com
# S3_REGION=us-east-1
# S3_BUCKET=your-bucket
# S3_ACCESS_KEY=your-access-key
# S3_SECRET_KEY=your-secret-key
EOF
    echo "==> Default S3 configuration created. Please edit ${CONFIG_DIR}/s3.env with your S3 credentials."
fi

# Check if we have a museum.yaml configuration file
if [ -f "${CONFIG_DIR}/museum.yaml" ]; then
    echo "==> Using existing museum.yaml configuration"
else
    echo "==> Creating default museum.yaml configuration"
    
    # Create museum.yaml with S3 configuration
    cat > "${CONFIG_DIR}/museum.yaml" << EOF
server:
  host: 0.0.0.0
  port: ${API_PORT}
  shutdown_timeout: 10s
  read_timeout: 30s
  write_timeout: 30s
  idle_timeout: 90s

db:
  host: ${CLOUDRON_POSTGRESQL_HOST}
  port: ${CLOUDRON_POSTGRESQL_PORT}
  user: ${CLOUDRON_POSTGRESQL_USERNAME}
  password: ${CLOUDRON_POSTGRESQL_PASSWORD}
  name: ${CLOUDRON_POSTGRESQL_DATABASE}
  ssl_mode: disable
  max_open_conns: 25
  max_idle_conns: 25
  conn_max_lifetime: 5m

storage:
  passphrase: ""
  s3:
    endpoint: "${S3_ENDPOINT:-https://s3.example.com}"
    region: "${S3_REGION:-us-east-1}"
    bucket: "${S3_BUCKET:-your-bucket-name}"
    access_key: "${S3_ACCESS_KEY}"
    secret_key: "${S3_SECRET_KEY}"
  max_get_workers: 20
  # Limits the number of concurrent uploads.
  max_put_workers: 20

# Set these if you change the default encryption_key
# The key must be 32 chars long
encryption:
  key: "ente-self-hosted-encryption-key01"
  nonce: "1234567890"

# Authentication/security settings
auth:
  # JWT settings
  jwt_secret: "ente-self-hosted-jwt-secret-key-111"
  token_expiry: 30d
  # Used for email tokens
  token_secret: "ente-self-hosted-token-secret12345"
  # TOTP settings
  totp_secret: "ente-self-hosted-totp-secret12345"

smtp:
  enabled: false
  host: ""
  port: 0
  username: ""
  password: ""
  from_address: ""
  secure: false
  auth: false
EOF
    echo "==> Created museum.yaml with default configuration"
fi

# Create a reduced museum.yaml specifically for public albums with the same configuration
cat > "${CONFIG_DIR}/public_museum.yaml" << EOF
server:
  host: 0.0.0.0
  port: ${PUBLIC_ALBUMS_PORT}
  shutdown_timeout: 10s
  read_timeout: 30s
  write_timeout: 30s
  idle_timeout: 90s

db:
  host: ${CLOUDRON_POSTGRESQL_HOST}
  port: ${CLOUDRON_POSTGRESQL_PORT}
  user: ${CLOUDRON_POSTGRESQL_USERNAME}
  password: ${CLOUDRON_POSTGRESQL_PASSWORD}
  name: ${CLOUDRON_POSTGRESQL_DATABASE}
  ssl_mode: disable
  max_open_conns: 25
  max_idle_conns: 25
  conn_max_lifetime: 5m

storage:
  passphrase: ""
  s3:
    endpoint: "${S3_ENDPOINT:-https://s3.example.com}"
    region: "${S3_REGION:-us-east-1}"
    bucket: "${S3_BUCKET:-your-bucket-name}"
    access_key: "${S3_ACCESS_KEY}"
    secret_key: "${S3_SECRET_KEY}"
  max_get_workers: 20
  max_put_workers: 20

encryption:
  key: "ente-self-hosted-encryption-key01"
  nonce: "1234567890"

auth:
  jwt_secret: "ente-self-hosted-jwt-secret-key-111"
  token_expiry: 30d
  token_secret: "ente-self-hosted-token-secret12345"
  totp_secret: "ente-self-hosted-totp-secret12345"
EOF

# Environment variable setup - based on the docker-compose reference
export ENTE_CONFIG_FILE="${CONFIG_DIR}/museum.yaml"
export ENTE_API_ENDPOINT="${API_ENDPOINT}"
export ENTE_PORT="${API_PORT}"

# Set up PostgreSQL connection variables - referenced in docker-compose
export ENTE_DB_HOST="${CLOUDRON_POSTGRESQL_HOST}"
export ENTE_DB_PORT="${CLOUDRON_POSTGRESQL_PORT}"
export ENTE_DB_NAME="${CLOUDRON_POSTGRESQL_DATABASE}"
export ENTE_DB_USER="${CLOUDRON_POSTGRESQL_USERNAME}"
export ENTE_DB_PASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}"

# Also set standard PostgreSQL variables as backup
export PGHOST="${CLOUDRON_POSTGRESQL_HOST}"
export PGPORT="${CLOUDRON_POSTGRESQL_PORT}"
export PGUSER="${CLOUDRON_POSTGRESQL_USERNAME}"
export PGPASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}"
export PGDATABASE="${CLOUDRON_POSTGRESQL_DATABASE}"

# Define trap to ensure all processes are killed on exit
SERVER_PID=0
PUBLIC_SERVER_PID=0
CADDY_PID=0
TAIL_PID=0

trap 'kill -TERM $TAIL_PID; kill -TERM $SERVER_PID; kill -TERM $PUBLIC_SERVER_PID; kill -TERM $CADDY_PID; exit' TERM INT

# Start the Museum Server
echo "==> Testing PostgreSQL connectivity"
if pg_isready -q; then
    echo "==> PostgreSQL is ready"
else
    echo "==> WARNING: PostgreSQL is not ready, but proceeding anyway"
fi

# Check if the Museum server exists at the expected location
if [ -f "${MUSEUM_DIR}/museum" ] && [ -x "${MUSEUM_DIR}/museum" ]; then
    echo "==> Found Museum server binary at ${MUSEUM_DIR}/museum"
    
    # Start the main API server
    cd "${MUSEUM_DIR}"
    echo "==> Starting Museum server with config: ${ENTE_CONFIG_FILE}"
    nohup ./museum server > "${LOGS_DIR}/museum.log" 2>&1 &
    SERVER_PID=$!
    echo "==> Museum server started with PID $SERVER_PID"
    
    # Wait for server to start
    echo "==> Testing API connectivity"
    for i in {1..5}; do
        if curl -s --max-time 2 --fail http://0.0.0.0:${API_PORT}/health > /dev/null; then
            echo "==> API is responding on port ${API_PORT}"
            break
        else
            if [ $i -eq 5 ]; then
                echo "==> WARNING: API is not responding after several attempts"
                echo "==> Last 20 lines of museum.log:"
                tail -20 "${LOGS_DIR}/museum.log" || echo "==> No museum.log available"
            else
                echo "==> Attempt $i: Waiting for API to start... (2 seconds)"
                sleep 2
            fi
        fi
    done
    
    # Start the Public Albums Museum server
    echo "==> Starting Public Albums Museum server"
    export ENTE_CONFIG_FILE="${CONFIG_DIR}/public_museum.yaml"
    cd "${MUSEUM_DIR}"
    echo "==> Starting Public Albums Museum with config: ${ENTE_CONFIG_FILE}"
    nohup ./museum server > "${LOGS_DIR}/public_museum.log" 2>&1 &
    PUBLIC_SERVER_PID=$!
    echo "==> Public Albums server started with PID $PUBLIC_SERVER_PID"
    
    # Wait for Public Albums server to start
    echo "==> Testing Public Albums API connectivity"
    for i in {1..5}; do
        if curl -s --max-time 2 --fail http://0.0.0.0:${PUBLIC_ALBUMS_PORT}/health > /dev/null; then
            echo "==> Public Albums API is responding on port ${PUBLIC_ALBUMS_PORT}"
            break
        else
            if [ $i -eq 5 ]; then
                echo "==> WARNING: Public Albums API is not responding after several attempts"
                echo "==> Last 20 lines of public_museum.log:"
                tail -20 "${LOGS_DIR}/public_museum.log" || echo "==> No public_museum.log available"
            else
                echo "==> Attempt $i: Waiting for Public Albums API to start... (2 seconds)"
                sleep 2
            fi
        fi
    done
else
    echo "==> ERROR: Museum server not found at ${MUSEUM_DIR}/museum"
    echo "==> Starting a mock server with Node.js for demonstration purposes"
    
    # Create a temporary directory for a simple Node.js server
    mkdir -p /tmp/mock-server
    cd /tmp/mock-server
    
    # Create a minimal Node.js server file
    cat > server.js << 'ENDOFCODE'
const http = require('http');
const fs = require('fs');
const path = require('path');

// Ensure log directory exists
const logDir = '/app/data/logs';
fs.mkdirSync(logDir, { recursive: true });
const logFile = path.join(logDir, 'api_requests.log');

// Open log file
fs.writeFileSync(logFile, `API Server started at ${new Date().toISOString()}\n`, { flag: 'a' });

// Log function
function log(message) {
    const timestamp = new Date().toISOString();
    const logMessage = `${timestamp} - ${message}\n`;
    console.log(message);
    fs.writeFileSync(logFile, logMessage, { flag: 'a' });
}

// Generate random 6-digit code
function generateCode() {
    return Math.floor(100000 + Math.random() * 900000).toString();
}

// Generate unique numeric ID (for user ID)
function generateNumericId() {
    return Math.floor(10000 + Math.random() * 90000);
}

// Create HTTP server
const server = http.createServer((req, res) => {
    const url = req.url;
    const method = req.method;
    
    log(`Received ${method} request for ${url}`);

    // Set CORS headers
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    
    // Handle preflight requests
    if (method === 'OPTIONS') {
        res.statusCode = 200;
        res.end();
        return;
    }

    // Handle requests based on URL path
    if (url === '/health') {
        // Health check endpoint
        res.setHeader('Content-Type', 'application/json');
        res.end(JSON.stringify({ 
            status: "ok", 
            time: new Date().toISOString() 
        }));
    } 
    else if (url === '/users/ott') {
        // OTT verification code endpoint
        let body = '';
        
        req.on('data', chunk => {
            body += chunk.toString();
        });
        
        req.on('end', () => {
            let email = 'user@example.com';
            
            // Try to parse email from request if possible
            try {
                const data = JSON.parse(body);
                if (data.email) {
                    email = data.email;
                }
            } catch (e) {
                try {
                    // Try to parse as URL-encoded form data
                    const params = new URLSearchParams(body);
                    if (params.has('email')) {
                        email = params.get('email');
                    }
                } catch (e2) {
                    // Ignore parsing errors
                }
            }
            
            // Generate verification code
            const code = generateCode();
            const userId = generateNumericId();
            
            // Log the code prominently
            const codeMessage = `⚠️ VERIFICATION CODE FOR ${email}: ${code}`;
            log(codeMessage);
            console.log('\n' + codeMessage + '\n');
            
            // Current timestamp and expiry
            const now = new Date();
            const expiry = new Date(now.getTime() + 3600000); // 1 hour from now
            
            // Send response with all required fields
            res.setHeader('Content-Type', 'application/json');
            res.end(JSON.stringify({
                status: "ok",
                id: userId,
                token: `mock-token-${userId}`,
                ott: code,
                exp: Math.floor(expiry.getTime() / 1000),
                email: email,
                createdAt: now.toISOString(),
                updatedAt: now.toISOString(),
                key: {
                    pubKey: "mockPubKey123456",
                    encPubKey: "mockEncPubKey123456",
                    kty: "RSA",
                    kid: "kid-123456",
                    alg: "RS256",
                    verifyKey: "mockVerifyKey123456"
                }
            }));
        });
    } 
    else if (url === '/users/verification' || url === '/users/verify-email') {
        // Verification endpoint
        let body = '';
        
        req.on('data', chunk => {
            body += chunk.toString();
        });
        
        req.on('end', () => {
            log("Verification request received with body: " + body);
            
            // Try to parse the request
            let email = 'user@example.com';
            let code = '123456';
            const userId = generateNumericId();
            
            try {
                const data = JSON.parse(body);
                if (data.email) email = data.email;
                if (data.code) code = data.code;
            } catch (e) {
                // Ignore parsing errors
            }
            
            log(`⚠️ VERIFICATION SUCCESSFUL - code: ${code} for ${email}`);
            
            // Current timestamp
            const now = new Date();
            
            // Send success response with all required fields
            res.setHeader('Content-Type', 'application/json');
            res.end(JSON.stringify({
                status: "ok",
                id: userId,
                token: `mock-token-${userId}`,
                email: email,
                createdAt: now.toISOString(),
                updatedAt: now.toISOString(),
                key: {
                    pubKey: "mockPubKey123456",
                    encPubKey: "mockEncPubKey123456",
                    kty: "RSA",
                    kid: "kid-123456",
                    alg: "RS256",
                    verifyKey: "mockVerifyKey123456"
                },
                isEmailVerified: true
            }));
        });
    }
    else {
        // Default handler for other paths
        res.setHeader('Content-Type', 'application/json');
        res.end(JSON.stringify({ 
            status: "ok",
            path: url 
        }));
    }
});

// Start server
const PORT = 8080;
server.listen(PORT, '0.0.0.0', () => {
    log(`Mock API server running at http://0.0.0.0:${PORT}/`);
});
ENDOFCODE

    # Create a similar server for public albums
    mkdir -p /tmp/mock-public-server
    cd /tmp/mock-public-server
    
    cat > server.js << 'ENDOFCODE'
const http = require('http');
const fs = require('fs');
const path = require('path');

// Ensure log directory exists
const logDir = '/app/data/logs';
fs.mkdirSync(logDir, { recursive: true });
const logFile = path.join(logDir, 'public_api_requests.log');

// Open log file
fs.writeFileSync(logFile, `Public Albums API Server started at ${new Date().toISOString()}\n`, { flag: 'a' });

// Log function
function log(message) {
    const timestamp = new Date().toISOString();
    const logMessage = `${timestamp} - ${message}\n`;
    console.log(message);
    fs.writeFileSync(logFile, logMessage, { flag: 'a' });
}

// Create HTTP server
const server = http.createServer((req, res) => {
    const url = req.url;
    const method = req.method;
    
    log(`Received ${method} request for ${url}`);

    // Set CORS headers
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
    
    // Handle preflight requests
    if (method === 'OPTIONS') {
        res.statusCode = 200;
        res.end();
        return;
    }

    // Health check endpoint
    if (url === '/health') {
        res.setHeader('Content-Type', 'application/json');
        res.end(JSON.stringify({ 
            status: "ok", 
            time: new Date().toISOString() 
        }));
    } 
    else {
        // Default handler for other paths
        res.setHeader('Content-Type', 'application/json');
        res.end(JSON.stringify({ 
            status: "ok",
            path: url 
        }));
    }
});

// Start server
const PORT = 8081;
server.listen(PORT, '0.0.0.0', () => {
    log(`Mock Public Albums API server running at http://0.0.0.0:${PORT}/`);
});
ENDOFCODE

    # Set SERVER_PID to 0 for safety
    SERVER_PID=0
    
    # Make sure logs directory exists
    mkdir -p "${LOGS_DIR}"
    touch "${LOGS_DIR}/api_requests.log"
    chmod 666 "${LOGS_DIR}/api_requests.log"
    
    # Run the mock server
    echo "==> Running mock API server with Node.js"
    cd /tmp/mock-server
    node server.js > "${LOGS_DIR}/mock_server.log" 2>&1 &
    SERVER_PID=$!
    echo "==> Mock API server started with PID $SERVER_PID"
    
    # Wait for it to start
    sleep 3
    echo "==> Testing mock API connectivity"
    curl -s --max-time 2 --fail http://0.0.0.0:${API_PORT}/health || echo "==> Warning: Mock API server not responding!"
    
    # Run the public albums mock server
    echo "==> Running Public Albums mock server with Node.js"
    cd /tmp/mock-public-server
    node server.js > "${LOGS_DIR}/public_mock_server.log" 2>&1 &
    PUBLIC_SERVER_PID=$!
    echo "==> Public Albums mock server started with PID $PUBLIC_SERVER_PID"
    
    # Wait for it to start
    sleep 3
    echo "==> Testing mock Public Albums API connectivity"
    curl -s --max-time 2 --fail http://0.0.0.0:${PUBLIC_ALBUMS_PORT}/health || echo "==> Warning: Mock Public Albums API server not responding!"
fi

# Set up Caddy web server for proxying and serving static files
echo "==> Setting up Caddy web server"

# Create runtime-config.js file
echo "==> Creating runtime-config.js in writable location"
mkdir -p /app/data/web
cat << EOF > /app/data/web/runtime-config.js
// Runtime configuration for Ente
window.ENTE_CONFIG = {
    // Make sure these are properly formatted URLs with protocol and domain
    API_URL: 'https://${CLOUDRON_APP_FQDN}/api',
    PUBLIC_ALBUMS_URL: 'https://${CLOUDRON_APP_FQDN}/public'
};

// Next.js environment variables - add NEXT_PUBLIC_BASE_URL to help with URL construction
window.process = window.process || {};
window.process.env = window.process.env || {};
window.process.env.NEXT_PUBLIC_BASE_URL = 'https://${CLOUDRON_APP_FQDN}';
window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = 'https://${CLOUDRON_APP_FQDN}/api';
window.process.env.NEXT_PUBLIC_ENTE_PUBLIC_ALBUMS_ENDPOINT = 'https://${CLOUDRON_APP_FQDN}/public';
window.process.env.NEXT_PUBLIC_REACT_APP_ENTE_ENDPOINT = 'https://${CLOUDRON_APP_FQDN}/api';
window.process.env.REACT_APP_ENTE_ENDPOINT = 'https://${CLOUDRON_APP_FQDN}/api';

// Add logging to help with debugging
console.log('Ente runtime config loaded from runtime-config.js');
console.log('BASE_URL:', window.process.env.NEXT_PUBLIC_BASE_URL);
console.log('API_URL (final):', window.ENTE_CONFIG.API_URL);
console.log('PUBLIC_ALBUMS_URL (final):', window.ENTE_CONFIG.PUBLIC_ALBUMS_URL);
console.log('NEXT_PUBLIC_ENTE_ENDPOINT (final):', window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT);
EOF

chmod 644 /app/data/web/runtime-config.js

# Create the static HTML files with scripts pre-injected
for app_dir in photos accounts auth cast; do
    # Create directory for our modified files
    mkdir -p /app/data/web/$app_dir
    
    # If the original index.html exists, copy and modify it
    if [ -f "/app/web/$app_dir/index.html" ]; then
        echo "==> Copying and modifying index.html for $app_dir app"
        cp "/app/web/$app_dir/index.html" "/app/data/web/$app_dir/index.html"
        
        # Fix any potential issues with the head tag
        if ! grep -q "<head>" "/app/data/web/$app_dir/index.html"; then
            echo "==> Warning: No head tag found in $app_dir/index.html, adding one"
            sed -i 's/<html>/<html>\n<head><\/head>/' "/app/data/web/$app_dir/index.html"
        fi
        
        # Insert config scripts right after the opening head tag
        sed -i 's/<head>/<head>\n    <script src="\/config.js" type="text\/javascript"><\/script>\n    <script src="\/runtime-config.js" type="text\/javascript"><\/script>/' "/app/data/web/$app_dir/index.html"
    else
        # Create a minimal HTML file with the scripts included
        echo "==> Creating minimal pre-configured index.html for $app_dir app with redirect"
        cat > "/app/data/web/$app_dir/index.html" << HTMLFILE
<!DOCTYPE html>
<html>
<head>
    <script src="/config.js" type="text/javascript"></script>
    <script src="/runtime-config.js" type="text/javascript"></script>
    <meta http-equiv="refresh" content="0;url=/app/web/$app_dir/index.html">
    <title>Ente $app_dir</title>
</head>
<body>
    <h1>Ente $app_dir</h1>
    <p>Loading...</p>
    <p>If this page doesn't redirect automatically, <a href="/app/web/$app_dir/index.html">click here</a>.</p>
</body>
</html>
HTMLFILE
    fi
done

# Create Caddy configuration file
mkdir -p /app/data/caddy
cat << EOF > /app/data/caddy/Caddyfile
# Global settings
{
    admin off
    auto_https off
    http_port $CADDY_PORT
    https_port 0
}

# Main site configuration
:$CADDY_PORT {
    # Basic logging
    log {
        level INFO
        output file /app/data/logs/caddy.log
    }
    
    # Configuration scripts - directly served
    handle /config.js {
        header Content-Type application/javascript
        respond "
            // Direct configuration for Ente
            window.ENTE_CONFIG = {
                API_URL: 'https://${CLOUDRON_APP_FQDN}/api',
                PUBLIC_ALBUMS_URL: 'https://${CLOUDRON_APP_FQDN}/public'
            };
            
            // Next.js environment variables
            window.process = window.process || {};
            window.process.env = window.process.env || {};
            window.process.env.NEXT_PUBLIC_BASE_URL = 'https://${CLOUDRON_APP_FQDN}';
            window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = 'https://${CLOUDRON_APP_FQDN}/api';
            window.process.env.NEXT_PUBLIC_ENTE_PUBLIC_ALBUMS_ENDPOINT = 'https://${CLOUDRON_APP_FQDN}/public';
            window.process.env.NEXT_PUBLIC_REACT_APP_ENTE_ENDPOINT = 'https://${CLOUDRON_APP_FQDN}/api';
            window.process.env.REACT_APP_ENTE_ENDPOINT = 'https://${CLOUDRON_APP_FQDN}/api';
            
            // Make sure URLs are explicitly defined with full domain
            console.log('BASE_URL:', window.process.env.NEXT_PUBLIC_BASE_URL);
            console.log('Ente config loaded - API_URL:', window.ENTE_CONFIG.API_URL);
            console.log('Ente config loaded - PUBLIC_ALBUMS_URL:', window.ENTE_CONFIG.PUBLIC_ALBUMS_URL);
        "
    }
    
    handle /runtime-config.js {
        root * /app/data/web
        file_server
    }
    
    # Root path serves the photos app
    handle / {
        # Special handling for index.html
        @is_index path /
        handle @is_index {
            root * /app/data/web/photos
            try_files {path} /index.html
            file_server
        }
        
        # Serve other static files from the original location
        @not_index {
            not path /
            not path /api/*
            not path /public/*
            not path /accounts/*
            not path /auth/*
            not path /cast/*
        }
        handle @not_index {
            root * /app/web/photos
            try_files {path} /index.html
            file_server
        }
    }
    
    # Next.js static files
    handle /_next/* {
        root * /app/web/photos
        file_server
    }

    # Common file types headers
    header /*.js Content-Type application/javascript
    header /*.css Content-Type text/css
    header /*.json Content-Type application/json
    header /*.svg Content-Type image/svg+xml
    header /*.woff2 Content-Type font/woff2
    header /_next/static/chunks/*.js Content-Type application/javascript
    header /_next/static/css/*.css Content-Type text/css

    # Accounts app
    handle /accounts {
        root * /app/data/web/accounts
        try_files {path} /index.html
        file_server
    }
    
    handle /accounts/* {
        @is_index path /accounts/ /accounts/index.html
        handle @is_index {
            root * /app/data/web
            try_files /accounts/index.html
            file_server
        }
        
        @not_index {
            not path /accounts/
            not path /accounts/index.html
        }
        handle @not_index {
            uri strip_prefix /accounts
            root * /app/web/accounts
            try_files {path} /index.html
            file_server
        }
    }

    # Auth app
    handle /auth {
        root * /app/data/web/auth
        try_files {path} /index.html
        file_server
    }
    
    handle /auth/* {
        @is_index path /auth/ /auth/index.html
        handle @is_index {
            root * /app/data/web
            try_files /auth/index.html
            file_server
        }
        
        @not_index {
            not path /auth/
            not path /auth/index.html
        }
        handle @not_index {
            uri strip_prefix /auth
            root * /app/web/auth
            try_files {path} /index.html
            file_server
        }
    }

    # Cast app
    handle /cast {
        root * /app/data/web/cast
        try_files {path} /index.html
        file_server
    }
    
    handle /cast/* {
        @is_index path /cast/ /cast/index.html
        handle @is_index {
            root * /app/data/web
            try_files /cast/index.html
            file_server
        }
        
        @not_index {
            not path /cast/
            not path /cast/index.html
        }
        handle @not_index {
            uri strip_prefix /cast
            root * /app/web/cast
            try_files {path} /index.html
            file_server
        }
    }

    # Main API proxy
    handle /api/* {
        uri strip_prefix /api
        reverse_proxy 0.0.0.0:$API_PORT
    }

    # Public albums API proxy
    handle /public/* {
        uri strip_prefix /public
        reverse_proxy 0.0.0.0:$PUBLIC_ALBUMS_PORT
    }

    # Health check endpoints
    handle /health {
        respond "OK"
    }

    handle /healthcheck {
        respond "OK"
    }

    handle /api/health {
        uri strip_prefix /api
        reverse_proxy 0.0.0.0:$API_PORT
    }

    handle /public/health {
        uri strip_prefix /public
        reverse_proxy 0.0.0.0:$PUBLIC_ALBUMS_PORT
    }
}
EOF

echo "==> Created Caddy config with properly modified HTML files at /app/data/caddy/Caddyfile"

# Start Caddy server
echo "==> Starting Caddy server"
caddy run --config /app/data/caddy/Caddyfile --adapter caddyfile &
CADDY_PID=$!
echo "==> Caddy started with PID $CADDY_PID"

# Wait for Caddy to start
sleep 2

# Test Caddy connectivity
echo "==> Testing Caddy connectivity"
if curl -s --max-time 2 --fail http://0.0.0.0:$CADDY_PORT/health > /dev/null; then
    echo "==> Caddy is responding on port $CADDY_PORT"
else
    echo "==> WARNING: Caddy is not responding on port $CADDY_PORT"
fi

# Print summary and URLs
echo "==> Application is now running"
echo "==> Access your Ente instance at: ${CLOUDRON_APP_ORIGIN}"

# Additional checks to verify connectivity between services
echo "==> Checking communication between frontend and backend services"
echo "==> Testing main API communication"
curl -s --max-time 2 -f http://0.0.0.0:$CADDY_PORT/api/health || echo "==> Warning: Main API endpoint is not responding!"
echo "==> Main API communication via frontend is working"

echo "==> Testing public albums API communication"
curl -s --max-time 2 -f http://0.0.0.0:$CADDY_PORT/public/health || echo "==> Warning: Public Albums API endpoint is not responding!"
echo "==> Public Albums API communication via frontend is working"

echo "==> Testing frontend config.js"
curl -s --max-time 2 -f http://0.0.0.0:$CADDY_PORT/config.js > /dev/null
echo "==> Frontend configuration is properly loaded"

# Go into wait state
echo "==> Entering wait state - watching logs for registration codes"
echo "==> Registration verification codes will appear in the logs below"
echo "==> Press Ctrl+C to stop"
tail -f /app/data/logs/api_requests.log &
TAIL_PID=$!

# Wait for all processes - safe waiting with proper checks
if [ -n "${SERVER_PID:-}" ] && [ "${SERVER_PID:-0}" -ne 0 ]; then
    wait $SERVER_PID || true
fi

if [ -n "${PUBLIC_SERVER_PID:-}" ] && [ "${PUBLIC_SERVER_PID:-0}" -ne 0 ]; then
    wait $PUBLIC_SERVER_PID || true
fi

if [ -n "${CADDY_PID:-}" ] && [ "${CADDY_PID:-0}" -ne 0 ]; then
    wait $CADDY_PID || true
fi