#!/bin/bash

# Stoatchat Setup Script
# Automated deployment of Revolt chat backend for st.vish.gg

set -euo pipefail

# Configuration
STOATCHAT_DIR="/opt/stoatchat"
DOMAIN="st.vish.gg"
REPO_URL="https://github.com/stoatchat/stoatchat.git"

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

# Logging functions
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# Check if running as root
check_root() {
    if [[ $EUID -eq 0 ]]; then
        log_error "This script should not be run as root"
        exit 1
    fi
}

# Check system requirements
check_requirements() {
    log_info "Checking system requirements..."

    # Check OS
    if [[ ! -f /etc/os-release ]]; then
        log_error "Cannot determine OS version"
        exit 1
    fi

    source /etc/os-release
    if [[ "$ID" != "ubuntu" && "$ID" != "debian" ]]; then
        log_warning "This script is designed for Ubuntu/Debian. Proceeding anyway..."
    fi

    # Check available memory
    local mem_gb=$(free -g | awk '/^Mem:/{print $2}')
    if [[ $mem_gb -lt 4 ]]; then
        log_warning "Less than 4GB RAM detected. Stoatchat may not perform well."
    fi

    # Check available disk space
    local disk_gb=$(df -BG / | awk 'NR==2{print $4}' | sed 's/G//')
    if [[ $disk_gb -lt 20 ]]; then
        log_error "Less than 20GB free disk space. Cannot proceed."
        exit 1
    fi

    log_success "System requirements check passed"
}

# Install system dependencies
install_dependencies() {
    log_info "Installing system dependencies..."

    sudo apt update
    sudo apt install -y \
        curl \
        wget \
        git \
        build-essential \
        pkg-config \
        libssl-dev \
        ca-certificates \
        gnupg \
        lsb-release \
        jq

    # Install Docker if not present
    if ! command -v docker &> /dev/null; then
        log_info "Installing Docker..."
        curl -fsSL https://get.docker.com -o get-docker.sh
        sudo sh get-docker.sh
        sudo usermod -aG docker $USER
        rm get-docker.sh
        log_success "Docker installed"
    else
        log_info "Docker already installed"
    fi

    # Install Docker Compose if not present
    if ! command -v docker-compose &> /dev/null; then
        log_info "Installing Docker Compose..."
        sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
        sudo chmod +x /usr/local/bin/docker-compose
        log_success "Docker Compose installed"
    else
        log_info "Docker Compose already installed"
    fi

    # Install mise (Rust toolchain manager)
    if ! command -v mise &> /dev/null; then
        log_info "Installing mise..."
        curl https://mise.run | sh
        echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc
        export PATH="$HOME/.local/bin:$PATH"
        log_success "mise installed"
    else
        log_info "mise already installed"
    fi

    log_success "Dependencies installed"
}

# Clone and setup stoatchat
setup_stoatchat() {
    log_info "Setting up Stoatchat..."

    # Create directory
    sudo mkdir -p $STOATCHAT_DIR
    sudo chown $USER:$USER $STOATCHAT_DIR

    # Clone repository
    if [[ ! -d "$STOATCHAT_DIR/.git" ]]; then
        log_info "Cloning Stoatchat repository..."
        git clone $REPO_URL $STOATCHAT_DIR
    else
        log_info "Updating Stoatchat repository..."
        cd $STOATCHAT_DIR
        git pull origin main
    fi

    cd $STOATCHAT_DIR

    # Setup LiveKit configuration
    if [[ ! -f "livekit.yml" ]]; then
        log_info "Creating LiveKit configuration..."
        cp livekit.example.yml livekit.yml

        # Update LiveKit config with domain
        sed -i "s/localhost:7880/voice.$DOMAIN/g" livekit.yml
        sed -i "s/redis_host: localhost/redis_host: localhost/g" livekit.yml
        sed -i "s/redis_port: 6379/redis_port: 6380/g" livekit.yml
    fi

    # Create production configuration
    log_info "Creating production configuration..."
    cat > Revolt.overrides.toml << EOF
[api]
url = "https://api.$DOMAIN"

[events]
url = "wss://events.$DOMAIN"

[autumn]
url = "https://files.$DOMAIN"

[january]
url = "https://proxy.$DOMAIN"

[livekit]
url = "wss://voice.$DOMAIN"

[database]
mongodb = "mongodb://localhost:27017/revolt"

[redis]
url = "redis://localhost:6380"

[s3]
endpoint = "http://localhost:14009"
access_key_id = "minioadmin"
secret_access_key = "minioadmin"
bucket = "revolt-files"
region = "us-east-1"

[rabbitmq]
url = "amqp://guest:guest@localhost:5672"

[email]
smtp_host = "smtp.gmail.com"
smtp_port = 587
smtp_username = "your-email@example.com"
smtp_password = "REDACTED_PASSWORD"
from_address = "your-email@example.com"
smtp_tls = true

[features]
registration = true
email_verification = false
invite_only = false
EOF

    log_success "Stoatchat setup completed"
}

# Start supporting services
start_infrastructure() {
    log_info "Starting supporting services..."

    cd $STOATCHAT_DIR

    # Start Docker services
    docker-compose up -d

    # Wait for services to be ready
    log_info "Waiting for services to be ready..."
    sleep 30

    # Check service health
    local services=("database" "redis" "minio" "rabbitmq")
    for service in "${services[@]}"; do
        if docker-compose ps | grep -q "stoatchat-$service.*Up"; then
            log_success "$service is running"
        else
            log_error "$service failed to start"
            docker-compose logs stoatchat-$service
            exit 1
        fi
    done

    log_success "Infrastructure services started"
}

# Build stoatchat
build_stoatchat() {
    log_info "Building Stoatchat..."

    cd $STOATCHAT_DIR

    # Activate mise environment
    export PATH="$HOME/.local/bin:$PATH"
    eval "$(mise activate bash)"

    # Build the project
    if mise run build; then
        log_success "Stoatchat built successfully"
    else
        log_error "Failed to build Stoatchat"
        exit 1
    fi
}

# Start stoatchat services
start_stoatchat_services() {
    log_info "Starting Stoatchat services..."

    cd $STOATCHAT_DIR

    # Create logs directory
    mkdir -p logs

    # Start services in background
    export PATH="$HOME/.local/bin:$PATH"
    eval "$(mise activate bash)"

    mise service:api > logs/api.log 2>&1 &
    echo $! > logs/api.pid

    mise service:events > logs/events.log 2>&1 &
    echo $! > logs/events.pid

    mise service:files > logs/files.log 2>&1 &
    echo $! > logs/files.pid

    mise service:proxy > logs/proxy.log 2>&1 &
    echo $! > logs/proxy.pid

    mise service:gifbox > logs/gifbox.log 2>&1 &
    echo $! > logs/gifbox.pid

    mise service:pushd > logs/pushd.log 2>&1 &
    echo $! > logs/pushd.pid

    mise service:crond > logs/crond.log 2>&1 &
    echo $! > logs/crond.pid

    # Wait for services to start
    sleep 10

    # Check if services are running
    local ports=(14702 14703 14704 14705 14706)
    for port in "${ports[@]}"; do
        if ss -tlnp | grep -q ":$port "; then
            log_success "Service on port $port is running"
        else
            log_warning "Service on port $port may not be ready yet"
        fi
    done

    log_success "Stoatchat services started"
}

# Test the installation
test_installation() {
    log_info "Testing installation..."

    # Test API endpoint
    if curl -s http://localhost:14702/0.8/ | jq -e '.revolt' > /dev/null; then
        log_success "API is responding correctly"
    else
        log_error "API is not responding"
        return 1
    fi

    # Test file service
    if curl -s http://localhost:14704/ | jq -e '.autumn' > /dev/null; then
        log_success "File service is responding correctly"
    else
        log_error "File service is not responding"
        return 1
    fi

    log_success "Installation test passed"
}

# Create systemd services
create_systemd_services() {
    log_info "Creating systemd services..."

    # Create stoatchat user service
    sudo tee /etc/systemd/system/stoatchat.service > /dev/null << EOF
[Unit]
Description=Stoatchat (Revolt Chat Backend)
After=network.target docker.service
Requires=docker.service

[Service]
Type=forking
User=$USER
WorkingDirectory=$STOATCHAT_DIR
Environment=PATH=$HOME/.local/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=$STOATCHAT_DIR/scripts/start-services.sh
ExecStop=$STOATCHAT_DIR/scripts/stop-services.sh
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

    # Create start script
    cat > $STOATCHAT_DIR/scripts/start-services.sh << 'EOF'
#!/bin/bash
cd /opt/stoatchat
export PATH="$HOME/.local/bin:$PATH"
eval "$(mise activate bash)"

# Start infrastructure
docker-compose up -d

# Wait for infrastructure
sleep 30

# Start stoatchat services
mkdir -p logs
mise service:api > logs/api.log 2>&1 &
echo $! > logs/api.pid
mise service:events > logs/events.log 2>&1 &
echo $! > logs/events.pid
mise service:files > logs/files.log 2>&1 &
echo $! > logs/files.pid
mise service:proxy > logs/proxy.log 2>&1 &
echo $! > logs/proxy.pid
mise service:gifbox > logs/gifbox.log 2>&1 &
echo $! > logs/gifbox.pid
mise service:pushd > logs/pushd.log 2>&1 &
echo $! > logs/pushd.pid
mise service:crond > logs/crond.log 2>&1 &
echo $! > logs/crond.pid
EOF

    # Create stop script
    cat > $STOATCHAT_DIR/scripts/stop-services.sh << 'EOF'
#!/bin/bash
cd /opt/stoatchat

# Stop stoatchat services
if [[ -f logs/api.pid ]]; then kill $(cat logs/api.pid) 2>/dev/null || true; fi
if [[ -f logs/events.pid ]]; then kill $(cat logs/events.pid) 2>/dev/null || true; fi
if [[ -f logs/files.pid ]]; then kill $(cat logs/files.pid) 2>/dev/null || true; fi
if [[ -f logs/proxy.pid ]]; then kill $(cat logs/proxy.pid) 2>/dev/null || true; fi
if [[ -f logs/gifbox.pid ]]; then kill $(cat logs/gifbox.pid) 2>/dev/null || true; fi
if [[ -f logs/pushd.pid ]]; then kill $(cat logs/pushd.pid) 2>/dev/null || true; fi
if [[ -f logs/crond.pid ]]; then kill $(cat logs/crond.pid) 2>/dev/null || true; fi

# Stop infrastructure
docker-compose down
EOF

    # Make scripts executable
    chmod +x $STOATCHAT_DIR/scripts/*.sh

    # Enable service
    sudo systemctl daemon-reload
    sudo systemctl enable stoatchat.service

    log_success "Systemd services created"
}

# Print final instructions
print_final_instructions() {
    log_success "Stoatchat installation completed!"

    echo ""
    echo "🎉 Installation Summary:"
    echo "  • Stoatchat installed in: $STOATCHAT_DIR"
    echo "  • Domain configured for: $DOMAIN"
    echo "  • Services running on ports: 14702-14706"
    echo ""
    echo "🔧 Next Steps:"
    echo "  1. Set up Gmail App Password:"
    echo "     - Go to Google Account settings"
    echo "     - Enable 2-Factor Authentication"
    echo "     - Generate App Password for 'Mail'"
    echo "     - Update GMAIL_APP_PASSWORD_REQUIRED in Revolt.overrides.toml"
    echo ""
    echo "  2. Configure Cloudflare Tunnel for external access:"
    echo "     - api.$DOMAIN → localhost:14702"
    echo "     - events.$DOMAIN → localhost:14703"
    echo "     - files.$DOMAIN → localhost:14704"
    echo "     - proxy.$DOMAIN → localhost:14705"
    echo ""
    echo "  3. Set up the web client at $DOMAIN"
    echo ""
    echo "  4. Configure LiveKit for voice chat (optional)"
    echo ""
    echo "📊 Service Management:"
    echo "  • Start: sudo systemctl start stoatchat"
    echo "  • Stop: sudo systemctl stop stoatchat"
    echo "  • Status: sudo systemctl status stoatchat"
    echo "  • Logs: journalctl -u stoatchat -f"
    echo ""
    echo "🔍 Manual Service Management:"
    echo "  • View logs: tail -f $STOATCHAT_DIR/logs/*.log"
    echo "  • Test API: curl http://localhost:14702/0.8/"
    echo "  • Check ports: ss -tlnp | grep revolt"
    echo ""
    echo "📚 Documentation: $STOATCHAT_DIR/README.md"
    echo ""
}

# Main execution
main() {
    log_info "Starting Stoatchat installation for $DOMAIN"

    check_root
    check_requirements
    install_dependencies
    setup_stoatchat
    start_infrastructure
    build_stoatchat
    start_stoatchat_services

    if test_installation; then
        create_systemd_services
        print_final_instructions
    else
        log_error "Installation test failed. Please check the logs."
        exit 1
    fi
}

# Run main function
main "$@"
