#!/bin/bash
#
# Jabali Demo Data Population Script
# Creates fictitious users, domains, WordPress sites, emails, databases, etc.
# For presentation and demo purposes on a fresh Jabali installation.
#
# Usage: ./populate-demo-data [--clean]
#   --clean  Remove all demo data before creating new data
#
# Run this script as root on a Jabali server.
#

set -e

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

# Configuration
JABALI_DIR="/var/www/jabali"
SOCKET_PATH="/var/run/jabali/agent.sock"

# Print colored status messages
print_status() {
    echo -e "${BLUE}[*]${NC} $1"
}

print_success() {
    echo -e "${GREEN}[✓]${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}[!]${NC} $1"
}

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

print_header() {
    echo ""
    echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
    echo -e "${CYAN}  $1${NC}"
    echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
    echo ""
}

# Check if running as root
check_root() {
    if [[ $EUID -ne 0 ]]; then
        print_error "This script must be run as root"
        exit 1
    fi
}

# Check prerequisites
check_prereqs() {
    if [[ ! -S "$SOCKET_PATH" ]]; then
        print_error "Jabali agent socket not found. Starting agent..."
        systemctl start jabali-agent
        sleep 2
    fi
}

# Run PHP command that talks to agent
run_php() {
    cd "$JABALI_DIR" && php -r "$1"
}

# Run artisan tinker command
artisan_tinker() {
    cd "$JABALI_DIR" && php artisan tinker --execute="$1" 2>/dev/null || true
}

# Send command to agent via PHP
agent_cmd() {
    local action="$1"
    local params="$2"

    run_php "
        require_once 'vendor/autoload.php';
        \$client = new App\Services\Agent\AgentClient();
        try {
            \$result = \$client->send('$action', $params);
            echo json_encode(\$result);
        } catch (Exception \$e) {
            echo json_encode(['error' => \$e->getMessage()]);
        }
    "
}

# Demo data
declare -A DEMO_USERS=(
    ["acme"]="Acme Corporation|acme@example.com"
    ["techstart"]="TechStart Inc|hello@techstart.io"
    ["greenleaf"]="GreenLeaf Organic|info@greenleaf.eco"
    ["bluewave"]="BlueWave Media|contact@bluewave.media"
    ["skyline"]="Skyline Properties|sales@skyline.realty"
)

DEMO_DOMAINS=(
    "acme:acme-corp.demo"
    "acme:shop.acme-corp.demo"
    "techstart:techstart.demo"
    "techstart:app.techstart.demo"
    "techstart:docs.techstart.demo"
    "greenleaf:greenleaf-organic.demo"
    "greenleaf:store.greenleaf.demo"
    "bluewave:bluewave-media.demo"
    "bluewave:portfolio.bluewave.demo"
    "skyline:skyline-properties.demo"
    "skyline:listings.skyline.demo"
    "skyline:agents.skyline.demo"
)

DEMO_WORDPRESS=(
    "acme:acme-corp.demo:Acme Corporation"
    "acme:shop.acme-corp.demo:Acme Shop"
    "techstart:techstart.demo:TechStart Innovation Hub"
    "greenleaf:greenleaf-organic.demo:GreenLeaf Organic Foods"
    "greenleaf:store.greenleaf.demo:GreenLeaf Store"
    "bluewave:bluewave-media.demo:BlueWave Creative Agency"
    "bluewave:portfolio.bluewave.demo:Our Portfolio"
    "skyline:skyline-properties.demo:Skyline Real Estate"
    "skyline:listings.skyline.demo:Property Listings"
)

DEMO_EMAILS=(
    "acme:acme-corp.demo:info"
    "acme:acme-corp.demo:support"
    "acme:acme-corp.demo:sales"
    "techstart:techstart.demo:hello"
    "techstart:techstart.demo:dev"
    "greenleaf:greenleaf-organic.demo:info"
    "greenleaf:greenleaf-organic.demo:orders"
    "bluewave:bluewave-media.demo:contact"
    "bluewave:bluewave-media.demo:projects"
    "skyline:skyline-properties.demo:info"
    "skyline:skyline-properties.demo:agents"
)

DEMO_DATABASES=(
    "acme:crm"
    "acme:inventory"
    "techstart:analytics"
    "greenleaf:orders"
    "bluewave:projects"
    "skyline:listings"
)

# Clean demo data
clean_demo_data() {
    print_header "Cleaning Demo Data"

    for username in "${!DEMO_USERS[@]}"; do
        print_status "Removing user: $username"

        # Delete system user via agent
        agent_cmd "user.delete" "{\"username\": \"$username\", \"remove_home\": true}" > /dev/null 2>&1 || true

        # Clean database - query models directly since User doesn't have all relationships
        artisan_tinker "\$user = App\\Models\\User::where('username', '$username')->first(); if (\$user) { App\\Models\\Domain::where('user_id', \$user->id)->delete(); App\\Models\\Mailbox::where('user_id', \$user->id)->delete(); App\\Models\\CronJob::where('user_id', \$user->id)->delete(); App\\Models\\MysqlCredential::where('user_id', \$user->id)->delete(); App\\Models\\Backup::where('user_id', \$user->id)->delete(); App\\Models\\EmailDomain::where('user_id', \$user->id)->delete(); \$user->delete(); }"

        print_success "Removed: $username"
    done

    print_success "Demo data cleaned"
}

# Create demo users
create_users() {
    print_header "Creating Demo Users"

    for username in "${!DEMO_USERS[@]}"; do
        IFS='|' read -r name email <<< "${DEMO_USERS[$username]}"

        print_status "Creating user: $username ($name)"

        # Generate password
        password=$(openssl rand -base64 12 | tr -dc 'a-zA-Z0-9' | head -c 12)

        # Create system user via agent
        result=$(agent_cmd "user.create" "{\"username\": \"$username\", \"password\": \"$password\"}")

        if echo "$result" | grep -q '"error"'; then
            if echo "$result" | grep -qi "exists"; then
                print_warning "System user $username already exists"
            else
                print_warning "Agent: $(echo "$result" | grep -o '"error":"[^"]*"' | cut -d'"' -f4)"
            fi
        fi

        # Create in database (escape single quotes in name)
        escaped_name=$(echo "$name" | sed "s/'/\\\\'/g")
        artisan_tinker "App\\Models\\User::updateOrCreate(['username' => '$username'], ['name' => '$escaped_name', 'email' => '$email', 'password' => bcrypt('$password'), 'is_admin' => false, 'is_active' => true, 'disk_quota_mb' => 10240]);"

        print_success "Created: $username (password: $password)"
    done
}

# Create demo domains
create_domains() {
    print_header "Creating Demo Domains"

    for domain_data in "${DEMO_DOMAINS[@]}"; do
        IFS=':' read -r username domain <<< "$domain_data"

        print_status "Creating domain: $domain for $username"

        # Create via agent
        result=$(agent_cmd "domain.create" "{\"username\": \"$username\", \"domain\": \"$domain\"}")

        if echo "$result" | grep -q '"error"'; then
            if echo "$result" | grep -qi "exists"; then
                print_warning "Domain $domain already exists"
            else
                print_warning "$(echo "$result" | grep -o '"error":"[^"]*"' | cut -d'"' -f4)"
            fi
        fi

        # Ensure in database
        artisan_tinker "\$user = App\\Models\\User::where('username', '$username')->first(); if (\$user) { App\\Models\\Domain::updateOrCreate(['name' => '$domain'], ['name' => '$domain', 'user_id' => \$user->id, 'document_root' => '/home/$username/domains/$domain/public_html', 'is_active' => true]); }"

        print_success "Created domain: $domain"
    done
}

# Create WordPress installations
create_wordpress() {
    print_header "Installing WordPress Sites"

    for wp_data in "${DEMO_WORDPRESS[@]}"; do
        IFS=':' read -r username domain title <<< "$wp_data"

        print_status "Installing WordPress: $title on $domain"

        # Generate credentials
        admin_pass=$(openssl rand -base64 12 | tr -dc 'a-zA-Z0-9' | head -c 12)
        admin_email="admin@${domain}"

        # Install via agent
        result=$(agent_cmd "wp.install" "{
            \"username\": \"$username\",
            \"domain\": \"$domain\",
            \"site_title\": \"$title\",
            \"admin_user\": \"admin\",
            \"admin_password\": \"$admin_pass\",
            \"admin_email\": \"$admin_email\"
        }")

        if echo "$result" | grep -q '"error"'; then
            print_error "Failed: $(echo "$result" | grep -o '"error":"[^"]*"' | cut -d'"' -f4)"
            continue
        fi

        print_success "WordPress installed: $domain"
        echo -e "         Admin: ${GREEN}admin${NC} / ${GREEN}$admin_pass${NC}"

        sleep 1
    done
}

# Create email accounts
create_emails() {
    print_header "Creating Email Accounts"

    declare -A enabled_domains

    for email_data in "${DEMO_EMAILS[@]}"; do
        IFS=':' read -r username domain localpart <<< "$email_data"
        email="${localpart}@${domain}"

        # Enable email domain if not done
        if [[ -z "${enabled_domains[$domain]}" ]]; then
            print_status "Enabling email for: $domain"
            agent_cmd "email.enable_domain" "{\"username\": \"$username\", \"domain\": \"$domain\"}" > /dev/null 2>&1 || true

            artisan_tinker "\$user = App\\Models\\User::where('username', '$username')->first(); \$dom = App\\Models\\Domain::where('name', '$domain')->first(); if (\$user && \$dom) { App\\Models\\EmailDomain::updateOrCreate(['domain_id' => \$dom->id], ['user_id' => \$user->id, 'is_active' => true]); }"
            enabled_domains[$domain]=1
        fi

        print_status "Creating mailbox: $email"

        result=$(agent_cmd "email.mailbox_create" "{
            \"username\": \"$username\",
            \"email\": \"$email\",
            \"password\": \"Demo123!\",
            \"quota_bytes\": 1073741824
        }")

        if echo "$result" | grep -q '"error"'; then
            if echo "$result" | grep -qi "exists"; then
                print_warning "Mailbox exists"
            else
                print_warning "$(echo "$result" | grep -o '"error":"[^"]*"' | cut -d'"' -f4)"
            fi
            continue
        fi

        # Add to database
        artisan_tinker "\$user = App\\Models\\User::where('username', '$username')->first(); \$emailDom = App\\Models\\EmailDomain::whereHas('domain', fn(\$q) => \$q->where('name', '$domain'))->first(); if (\$user && \$emailDom) { App\\Models\\Mailbox::updateOrCreate(['email' => '$email'], ['user_id' => \$user->id, 'email_domain_id' => \$emailDom->id, 'quota_bytes' => 1073741824, 'is_active' => true]); }"

        print_success "Created: $email"
    done
}

# Create databases
create_databases() {
    print_header "Creating Databases"

    for db_data in "${DEMO_DATABASES[@]}"; do
        IFS=':' read -r username dbsuffix <<< "$db_data"
        dbname="${username}_${dbsuffix}"

        print_status "Creating database: $dbname"

        result=$(agent_cmd "mysql.create_database" "{\"username\": \"$username\", \"database\": \"$dbname\"}")

        if echo "$result" | grep -q '"error"'; then
            if echo "$result" | grep -qi "exists"; then
                print_warning "Database exists"
            else
                print_warning "$(echo "$result" | grep -o '"error":"[^"]*"' | cut -d'"' -f4)"
            fi
            continue
        fi

        artisan_tinker "\$user = App\\Models\\User::where('username', '$username')->first(); if (\$user) { App\\Models\\MysqlCredential::updateOrCreate(['database_name' => '$dbname'], ['user_id' => \$user->id, 'db_user' => '$username', 'db_host' => 'localhost']); }"

        print_success "Created: $dbname"
    done
}

# Create SSL certificates
create_ssl() {
    print_header "Creating SSL Certificates"

    for domain_data in "${DEMO_DOMAINS[@]}"; do
        IFS=':' read -r username domain <<< "$domain_data"

        print_status "SSL for: $domain"

        result=$(agent_cmd "ssl.generate_self_signed" "{\"domain\": \"$domain\", \"username\": \"$username\", \"days\": 365}")

        if echo "$result" | grep -q '"error"'; then
            print_warning "SSL skipped for $domain"
            continue
        fi

        artisan_tinker "\$dom = App\\Models\\Domain::where('name', '$domain')->first(); if (\$dom) { App\\Models\\SslCertificate::updateOrCreate(['domain_id' => \$dom->id], ['type' => 'self-signed', 'status' => 'active', 'issued_at' => now(), 'expires_at' => now()->addYear(), 'auto_renew' => false]); }"

        print_success "SSL: $domain"
    done
}

# Create backup records
create_backups() {
    print_header "Creating Backup Records"

    for username in "${!DEMO_USERS[@]}"; do
        print_status "Backup records for: $username"

        artisan_tinker "\$user = App\\Models\\User::where('username', '$username')->first(); if (\$user) { for (\$i = 0; \$i < 3; \$i++) { App\\Models\\Backup::create(['user_id' => \$user->id, 'name' => 'backup_' . date('Y-m-d', strtotime('-' . (\$i * 7) . ' days')), 'type' => 'full', 'size' => rand(50000000, 500000000), 'path' => '/var/backups/users/$username/backup_' . date('Y-m-d', strtotime('-' . (\$i * 7) . ' days')) . '.tar.gz', 'status' => 'completed', 'created_at' => now()->subDays(\$i * 7)]); } }"

        print_success "Backups: $username"
    done
}

# Print summary
print_summary() {
    print_header "Demo Data Complete"

    echo -e "${GREEN}Created:${NC}"
    echo "  - Users: ${#DEMO_USERS[@]}"
    echo "  - Domains: ${#DEMO_DOMAINS[@]}"
    echo "  - WordPress: ${#DEMO_WORDPRESS[@]}"
    echo "  - Emails: ${#DEMO_EMAILS[@]}"
    echo "  - Databases: ${#DEMO_DATABASES[@]}"
    echo ""
    echo -e "${YELLOW}Note:${NC} Domains use .demo TLD - add to /etc/hosts for testing"
    echo -e "${GREEN}Email password:${NC} Demo123!"
    echo ""
}

# Main
main() {
    echo ""
    echo -e "${CYAN}╔═════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${CYAN}║       ${GREEN}Jabali Demo Data Population Script${CYAN}                  ║${NC}"
    echo -e "${CYAN}╚═════════════════════════════════════════════════════════════╝${NC}"

    check_root
    check_prereqs

    if [[ "$1" == "--clean" ]]; then
        clean_demo_data
        echo ""
        read -p "Repopulate demo data? (y/n) " -n 1 -r
        echo ""
        [[ ! $REPLY =~ ^[Yy]$ ]] && exit 0
    fi

    create_users
    create_domains
    create_wordpress
    create_emails
    create_databases
    create_ssl
    create_backups

    print_status "Clearing caches..."
    cd "$JABALI_DIR" && php artisan optimize:clear > /dev/null 2>&1 || true

    print_summary
}

main "$@"
