#!/usr/bin/env bash
# AI Influencer Factory - Empty Client Install
# Ubuntu 22.04 / 24.04 LTS
set -euo pipefail

RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'

log()  { echo -e "${GREEN}[OK]${NC} $*"; }
info() { echo -e "${CYAN}[..]${NC} $*"; }
warn() { echo -e "${YELLOW}[!!]${NC} $*"; }
die()  { echo -e "${RED}[ERR] $*${NC}"; exit 1; }
sep()  { echo -e "${BOLD}----------------------------------------${NC}"; }

AIF_LICENSE_KEY="${AIF_LICENSE_KEY:-}"
AIF_DOMAIN="${AIF_DOMAIN:-}"
AIF_PUBLIC_IP="${AIF_PUBLIC_IP:-}"
AIF_PROVISIONED_DOMAIN="${AIF_PROVISIONED_DOMAIN:-}"
AIF_LICENSE_URL="${AIF_LICENSE_URL:-https://genspirit.online/lic/api/license/validate}"
AIF_PROVISION_URL="${AIF_PROVISION_URL:-https://genspirit.online/lic/api/provision}"
AIF_RELEASE_URL="${AIF_RELEASE_URL:-https://genspirit.online/releases/aif-code-v1.tar.gz}"
RUNPOD_REF_URL="${RUNPOD_REF_URL:-https://runpod.io?ref=0velnjr9}"

AIF_ADMIN_TG_ID="${AIF_ADMIN_TG_ID:-}"
AIF_CLAUDE_KEY="${AIF_CLAUDE_KEY:-}"
AIF_AI_PROXY_URL="${AIF_AI_PROXY_URL:-https://genspirit.online/proxy/chat}"
AIF_DASH_PASSWORD="${AIF_DASH_PASSWORD:-}"
AIF_MEM_PASSWORD="${AIF_MEM_PASSWORD:-}"
AIF_TZ="${AIF_TZ:-Europe/Kyiv}"
SKIP_SSL="${SKIP_SSL:-0}"

RUNPOD_API_KEY="${RUNPOD_API_KEY:-}"
RUNPOD_SSH_KEY="${RUNPOD_SSH_KEY:-/root/.ssh/id_runpod}"
RUNPOD_GPU_BUDGET_USD="${RUNPOD_GPU_BUDGET_USD:-25}"
RUNPOD_GPU_TIER="${RUNPOD_GPU_TIER:-dev}"

banner() {
cat <<'EOF'
AI Influencer Factory - Empty Install
EOF
}

prompt_config() {
    sep
    echo "Base configuration"
    sep
    [[ -z "$AIF_LICENSE_KEY" ]] && read -rp "AIF License Key: " AIF_LICENSE_KEY
    [[ -z "$AIF_DOMAIN" ]] && read -rp "Domain (empty = auto clientN.genspirit.online): " AIF_DOMAIN
    [[ -z "$AIF_ADMIN_TG_ID" ]] && read -rp "Admin Telegram ID: " AIF_ADMIN_TG_ID
    [[ -z "$AIF_CLAUDE_KEY" ]] && read -rp "Claude API Key for local fallback (optional, leave empty): " AIF_CLAUDE_KEY
    [[ -z "$AIF_DASH_PASSWORD" ]] && read -rsp "Dashboard password: " AIF_DASH_PASSWORD && echo
    [[ -z "$AIF_MEM_PASSWORD" ]] && AIF_MEM_PASSWORD="aif_mem_$(openssl rand -hex 8)"
}

install_system() {
    info "Installing system packages"
    apt-get update -qq
    apt-get install -y -qq \
        python3 python3-pip python3-venv \
        nginx certbot python3-certbot-nginx \
        curl wget git jq sqlite3 openssl \
        ca-certificates gnupg lsb-release cron

    if ! command -v docker >/dev/null 2>&1; then
        info "Installing Docker"
        curl -fsSL https://get.docker.com | sh
        systemctl enable --now docker
    fi
    docker compose version >/dev/null 2>&1 || apt-get install -y -qq docker-compose-plugin
    log "System packages ready"
}

machine_id() {
    local mid host first_ip
    mid="$(cat /etc/machine-id 2>/dev/null || true)"
    first_ip="$(hostname -I 2>/dev/null | awk '{print $1}')"
    host="${HOSTNAME:-$(hostname)}"
    echo -n "${mid}${first_ip}${host}" | sha256sum | cut -c1-32
}

validate_license() {
    [[ -z "$AIF_LICENSE_KEY" ]] && die "License key is required"
    info "Validating license"
    local mid resp valid err
    mid="$(machine_id)"
    resp="$(curl -fsS -X POST "$AIF_LICENSE_URL" \
        -H "Content-Type: application/json" \
        -d "{\"key\":\"${AIF_LICENSE_KEY}\",\"machine_id\":\"${mid}\"}" || true)"
    valid="$(echo "$resp" | jq -r '.valid // false' 2>/dev/null || echo false)"
    if [[ "$valid" != "true" ]]; then
        err="$(echo "$resp" | jq -r '.error // empty' 2>/dev/null || true)"
        die "License validation failed${err:+: $err}"
    fi
    log "License valid"
}

provision_domain() {
    info "Detecting public server IP"
    AIF_PUBLIC_IP="${AIF_PUBLIC_IP:-$(curl -fsS https://api.ipify.org || true)}"
    [[ "$AIF_PUBLIC_IP" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || die "Could not detect public IPv4"

    info "Provisioning licensed DNS record"
    local resp subdomain err
    resp="$(curl -fsS -X POST "$AIF_PROVISION_URL" \
        -H "Content-Type: application/json" \
        -d "{\"key\":\"${AIF_LICENSE_KEY}\",\"ip\":\"${AIF_PUBLIC_IP}\"}" || true)"
    subdomain="$(echo "$resp" | jq -r '.subdomain // empty' 2>/dev/null || true)"
    if [[ -z "$subdomain" ]]; then
        err="$(echo "$resp" | jq -r '.error // .detail // empty' 2>/dev/null || true)"
        die "DNS provisioning failed${err:+: $err}"
    fi
    AIF_PROVISIONED_DOMAIN="$subdomain"
    if [[ -z "$AIF_DOMAIN" ]]; then
        AIF_DOMAIN="$AIF_PROVISIONED_DOMAIN"
    fi
    log "DNS ready: ${AIF_PROVISIONED_DOMAIN} -> ${AIF_PUBLIC_IP}"
}

download_code() {
    info "Downloading AIF release"
    local tmp=/tmp/aif-code.tar.gz
    curl -fsSL "$AIF_RELEASE_URL" -o "$tmp"
    tar xzf "$tmp" -C / --overwrite
    rm -f "$tmp"
    mkdir -p /opt/aif-dashboard /opt/aif-memory-svc /opt/aif-gen /opt/aif /opt/face-studio
    log "Code extracted"
}

setup_venvs() {
    info "Creating Python virtual environments"
    python3 -m venv /opt/aif/venv
    /opt/aif/venv/bin/pip install -q --upgrade pip
    /opt/aif/venv/bin/pip install -q \
        fastapi==0.136.1 uvicorn==0.46.0 httpx==0.28.1 \
        pydantic==2.8.2 pydantic-settings==2.14.0 python-dotenv==1.2.2 \
        requests==2.33.1 aiogram==3.13.0 aiofiles pillow

    python3 -m venv /opt/aif-memory-svc/venv
    /opt/aif-memory-svc/venv/bin/pip install -q --upgrade pip
    /opt/aif-memory-svc/venv/bin/pip install -q \
        fastapi==0.136.1 uvicorn==0.46.0 httpx==0.28.1 python-dotenv==1.2.2 \
        qdrant-client==1.17.1 fastembed==0.8.0
    log "Python environments ready"
}

setup_docker_services() {
    info "Starting Qdrant"
    mkdir -p /opt/qdrant-data
    docker run -d --name qdrant \
        --restart unless-stopped \
        -p 127.0.0.1:6333:6333 \
        -v /opt/qdrant-data:/qdrant/storage \
        qdrant/qdrant:v1.12.4 >/dev/null 2>&1 || docker start qdrant >/dev/null

    info "Starting n8n"
    mkdir -p /opt/n8n
    cat > /opt/n8n/docker-compose.yml <<EOF
services:
  n8n:
    image: n8nio/n8n:latest
    restart: unless-stopped
    ports:
      - "127.0.0.1:5678:5678"
    environment:
      - N8N_HOST=${AIF_DOMAIN}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - N8N_PATH=/n8n/
      - WEBHOOK_URL=https://${AIF_DOMAIN}/n8n/
      - N8N_EDITOR_BASE_URL=https://${AIF_DOMAIN}/n8n/
      - N8N_SECURE_COOKIE=true
      - GENERIC_TIMEZONE=${AIF_TZ}
      - TZ=${AIF_TZ}
      - N8N_ENCRYPTION_KEY=aif_enc_$(openssl rand -hex 16)
    volumes:
      - n8n_data:/home/node/.n8n
    user: "0:0"
volumes:
  n8n_data:
EOF
    (cd /opt/n8n && docker compose up -d)
    log "Docker services ready"
}

write_envs() {
    info "Writing empty-instance environment"
    local secret service_key license_base
    secret="$(openssl rand -hex 32)"
    service_key="$(python3 - <<PY
import hashlib
print(hashlib.sha256("${secret}".encode()).hexdigest()[:16])
PY
)"
    license_base="${AIF_LICENSE_URL%/api/license/validate}"

    cat > /opt/aif-dashboard/.env <<EOF
DASH_PASSWORD=${AIF_DASH_PASSWORD}
DASH_SECRET_KEY=${secret}
AIF_SEED_DEFAULT_PERSONA=0
AI_PROVIDER=groq
GROQ_API_KEY=
GROQ_MODEL=llama-3.3-70b-versatile
GROQ_INPUT_COST=0.00
GROQ_OUTPUT_COST=0.00
CLAUDE_API_KEY=${AIF_CLAUDE_KEY}
CLAUDE_MODEL=claude-haiku-4-5-20251001
CLAUDE_INPUT_COST=0.80
CLAUDE_OUTPUT_COST=4.00
TELEGRAM_ADMIN_CHAT_ID=${AIF_ADMIN_TG_ID}
AIF_LICENSE_KEY=${AIF_LICENSE_KEY}
AIF_AI_PROXY_URL=${AIF_AI_PROXY_URL}
LICENSE_SERVER_URL=${license_base}
LICENSE_ADMIN_TOKEN=
NOWPAYMENTS_API_KEY=
NOWPAYMENTS_IPN_SECRET=
ANALYTICS_DB=/opt/aif-dashboard/analytics.db
APPROVED_CONTENT_DIR=/opt/_empty-poster/approved
INFLUENCERS_DIR=/opt/aif/influencers
ENABLE_VIDEO=true
TZ=${AIF_TZ}
EOF

    cat > /opt/aif-memory-svc/.env <<EOF
AIF_LICENSE_KEY=${AIF_LICENSE_KEY}
AIF_AI_PROXY_URL=${AIF_AI_PROXY_URL}
GROQ_API_KEY=
GROQ_MODEL=llama-3.3-70b-versatile
CLAUDE_API_KEY=${AIF_CLAUDE_KEY}
CLAUDE_MODEL=claude-haiku-4-5-20251001
EOF

    mkdir -p /opt/aif-gen/logs /opt/aif-gen/loras /opt/aif-gen/refs /opt/_empty-poster/approved
    cat > /opt/aif-gen/.env <<EOF
RUNPOD_API_KEY=${RUNPOD_API_KEY}
RUNPOD_SSH_KEY=${RUNPOD_SSH_KEY}
RUNPOD_GPU_BUDGET_USD=${RUNPOD_GPU_BUDGET_USD}
RUNPOD_GPU_TIER=${RUNPOD_GPU_TIER}
COMFYUI_URL=http://127.0.0.1:18188
EOF

    cat > /opt/aif/service_key.txt <<EOF
${service_key}
EOF
    chmod 600 /opt/aif-dashboard/.env /opt/aif-memory-svc/.env /opt/aif-gen/.env /opt/aif/service_key.txt
    log "Environment files ready"
}

setup_systemd() {
    info "Writing systemd units"
    cat > /etc/systemd/system/aif-dashboard.service <<'EOF'
[Unit]
Description=AIF Dashboard + AI Proxy
After=network.target

[Service]
User=root
WorkingDirectory=/opt/aif-dashboard
EnvironmentFile=/opt/aif-dashboard/.env
ExecStart=/opt/aif/venv/bin/python3 /opt/aif-dashboard/dashboard_app.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

    cat > /etc/systemd/system/aif-memory-svc.service <<'EOF'
[Unit]
Description=AIF Memory Service
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
WorkingDirectory=/opt/aif-memory-svc
Environment="QDRANT_URL=http://127.0.0.1:6333"
Environment="EMBED_MODEL=intfloat/multilingual-e5-large"
Environment="HF_HOME=/opt/aif-memory-svc/.hf"
EnvironmentFile=/opt/aif-memory-svc/.env
ExecStart=/opt/aif-memory-svc/venv/bin/uvicorn app:app --host 127.0.0.1 --port 5013 --workers 1
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

    systemctl daemon-reload
    systemctl enable aif-dashboard aif-memory-svc
    log "Systemd units ready"
}

setup_nginx() {
    info "Configuring nginx for ${AIF_DOMAIN}"
    cat > "/etc/nginx/sites-available/${AIF_DOMAIN}" <<EOF
server {
    listen 80;
    server_name ${AIF_DOMAIN};

    location /dashboard/ {
        proxy_pass http://127.0.0.1:5012/dashboard/;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-Proto \$scheme;
    }

    location /proxy/ {
        proxy_pass http://127.0.0.1:5012/proxy/;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
    }

    location /api/ {
        proxy_pass http://127.0.0.1:5012/api/;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
    }

    location /payment/ {
        proxy_pass http://127.0.0.1:5012/payment/;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
    }

    location /mem/ {
        auth_basic "AIF Memory";
        auth_basic_user_file /etc/nginx/.aif_mem_htpasswd;
        proxy_pass http://127.0.0.1:5013/;
        proxy_set_header Host \$host;
    }

    location /n8n/ {
        proxy_pass http://127.0.0.1:5678/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host \$host;
        proxy_read_timeout 86400;
    }

    location / {
        root /var/www/${AIF_DOMAIN};
        index index.html;
        try_files \$uri \$uri/ /index.html;
    }
}
EOF

    printf "aif:%s\n" "$(openssl passwd -apr1 "$AIF_MEM_PASSWORD")" > /etc/nginx/.aif_mem_htpasswd
    ln -sf "/etc/nginx/sites-available/${AIF_DOMAIN}" "/etc/nginx/sites-enabled/${AIF_DOMAIN}"
    rm -f /etc/nginx/sites-enabled/default
    mkdir -p "/var/www/${AIF_DOMAIN}"
    cat > "/var/www/${AIF_DOMAIN}/index.html" <<EOF
<!doctype html><html><head><meta charset="utf-8"><title>AIF</title></head>
<body style="font-family:system-ui;background:#0a0a0f;color:#eee;padding:40px">
<h1>AI Influencer Factory</h1><p>Open <a href="/dashboard/">dashboard</a>.</p>
</body></html>
EOF
    nginx -t
    systemctl reload nginx
    log "Nginx ready"
}

setup_ssl() {
    if [[ "$SKIP_SSL" == "1" ]]; then
        warn "Skipping SSL"
        return
    fi
    info "Requesting SSL certificate"
    certbot --nginx -d "$AIF_DOMAIN" --non-interactive --agree-tos \
        -m "admin@${AIF_DOMAIN}" --redirect || warn "SSL failed; run certbot manually after DNS propagates"
}

prompt_runpod() {
    sep
    echo "RunPod configuration"
    sep
    local has_runpod tmp
    read -rp "Do you already have a RunPod account? [y/N]: " has_runpod
    if [[ ! "$has_runpod" =~ ^[Yy]$ ]]; then
        echo "Create RunPod account here: ${RUNPOD_REF_URL}"
    fi
    [[ -z "$RUNPOD_API_KEY" ]] && read -rp "RunPod API Key: " RUNPOD_API_KEY
    read -rp "RunPod SSH private key path [${RUNPOD_SSH_KEY}]: " tmp
    RUNPOD_SSH_KEY="${tmp:-$RUNPOD_SSH_KEY}"
    read -rp "RunPod GPU budget USD [${RUNPOD_GPU_BUDGET_USD}]: " tmp
    RUNPOD_GPU_BUDGET_USD="${tmp:-$RUNPOD_GPU_BUDGET_USD}"
    read -rp "RunPod GPU tier dev/pro/studio [${RUNPOD_GPU_TIER}]: " tmp
    RUNPOD_GPU_TIER="${tmp:-$RUNPOD_GPU_TIER}"

    cat > /opt/aif-gen/.env <<EOF
RUNPOD_API_KEY=${RUNPOD_API_KEY}
RUNPOD_SSH_KEY=${RUNPOD_SSH_KEY}
RUNPOD_GPU_BUDGET_USD=${RUNPOD_GPU_BUDGET_USD}
RUNPOD_GPU_TIER=${RUNPOD_GPU_TIER}
COMFYUI_URL=http://127.0.0.1:18188
EOF
    chmod 600 /opt/aif-gen/.env
    log "RunPod config saved"
}

start_services() {
    info "Starting AIF services"
    systemctl restart aif-memory-svc
    systemctl restart aif-dashboard
    log "Services started"
}

print_summary() {
    sep
    echo "AIF empty install complete"
    sep
    echo "Domain:    https://${AIF_DOMAIN}"
    echo "AIF DNS:   https://${AIF_PROVISIONED_DOMAIN} -> ${AIF_PUBLIC_IP}"
    echo "Dashboard: https://${AIF_DOMAIN}/dashboard/"
    echo "n8n:       https://${AIF_DOMAIN}/n8n/"
    echo "Memory:    https://${AIF_DOMAIN}/mem/ (user: aif, password: ${AIF_MEM_PASSWORD})"
    echo "RunPod ref: ${RUNPOD_REF_URL}"
    echo ""
    echo "Next:"
    echo "1. Log in to dashboard."
    echo "2. Create a new persona."
    echo "3. Click Provision for that persona."
    echo "4. Add DNA, generate faces, set primary face, then generate content."
}

main() {
    [[ $EUID -ne 0 ]] && die "Run as root: sudo bash install_empty.sh"
    banner
    prompt_config
    install_system
    validate_license
    provision_domain
    [[ -z "$AIF_DOMAIN" ]] && die "Domain is required"
    download_code
    setup_venvs
    setup_docker_services
    write_envs
    setup_systemd
    setup_nginx
    setup_ssl
    prompt_runpod
    start_services
    print_summary
}

main "$@"
