#!/bin/bash
# scripts/ci/deploy-staging.sh - Деплой на staging окружение

set -e

echo "🚀 Deploying to staging environment..."

# Переменные
REGISTRY=${DOCKER_REGISTRY:-"registry.hub.docker.com"}
PROJECT_NAME="catlink"
VERSION=${DRONE_TAG:-${DRONE_COMMIT_SHA:0:8}}
STAGING_HOST=${STAGING_HOST:-"staging.catlink.dev"}
STAGING_USER=${STAGING_USER:-"deploy"}
STAGING_PORT=${STAGING_PORT:-"22"}

echo "📋 Deployment information:"
echo "  • Registry: $REGISTRY"
echo "  • Project: $PROJECT_NAME"
echo "  • Version: $VERSION"
echo "  • Host: $STAGING_HOST"
echo "  • User: $STAGING_USER"

# Проверка обязательных переменных
if [ -z "$STAGING_HOST" ] || [ -z "$STAGING_SSH_KEY" ]; then
    echo "❌ Staging deployment credentials not found!"
    echo "Please set STAGING_HOST and STAGING_SSH_KEY environment variables"
    exit 1
fi

# Настройка SSH
echo "🔐 Setting up SSH connection..."
mkdir -p ~/.ssh
chmod 700 ~/.ssh

# Создание SSH ключа
echo "$STAGING_SSH_KEY" | base64 -d > ~/.ssh/id_staging
chmod 600 ~/.ssh/id_staging

# Добавление хоста в known_hosts
ssh-keyscan -p "$STAGING_PORT" "$STAGING_HOST" >> ~/.ssh/known_hosts 2>/dev/null || true

# SSH конфигурация
cat > ~/.ssh/config << EOF
Host staging
    HostName $STAGING_HOST
    User $STAGING_USER
    Port $STAGING_PORT
    IdentityFile ~/.ssh/id_staging
    StrictHostKeyChecking no
    UserKnownHostsFile ~/.ssh/known_hosts
EOF

# Проверка подключения к staging серверу
echo "🔗 Testing staging server connection..."
if ! ssh staging "echo 'Connection successful'" > /dev/null 2>&1; then
    echo "❌ Failed to connect to staging server"
    exit 1
fi

echo "✅ Successfully connected to staging server"

# Подготовка файлов для деплоя
echo "📦 Preparing deployment files..."
mkdir -p /tmp/staging-deploy

# Создание staging docker-compose
cat > /tmp/staging-deploy/docker-compose.staging.yml << EOF
version: '3.8'

services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: catlink_staging
      POSTGRES_USER: catlink_user
      POSTGRES_PASSWORD: \${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U catlink_user -d catlink_staging"]
      interval: 30s
      timeout: 10s
      retries: 3
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 30s
      timeout: 10s
      retries: 3
    restart: unless-stopped

  web:
    image: $REGISTRY/$PROJECT_NAME-backend:$VERSION
    environment:
      - DJANGO_ENV=staging
      - DEBUG=False
      - SECRET_KEY=\${SECRET_KEY}
      - DATABASE_URL=postgresql://catlink_user:\${POSTGRES_PASSWORD}@postgres:5432/catlink_staging
      - REDIS_URL=redis://redis:6379/0
      - ALLOWED_HOSTS=$STAGING_HOST,localhost,127.0.0.1
      - CORS_ALLOWED_ORIGINS=https://$STAGING_HOST,http://localhost:3000
      - EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend
    volumes:
      - media_data:/app/media
      - static_data:/app/staticfiles
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/api/"]
      interval: 30s
      timeout: 10s
      retries: 3
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.catlink-staging-api.rule=Host(\`$STAGING_HOST\`) && PathPrefix(\`/api\`)"
      - "traefik.http.routers.catlink-staging-api.tls=true"
      - "traefik.http.routers.catlink-staging-api.tls.certresolver=letsencrypt"
      - "traefik.http.services.catlink-staging-api.loadbalancer.server.port=8000"

  frontend:
    image: $REGISTRY/$PROJECT_NAME-frontend:$VERSION
    environment:
      - NODE_ENV=production
      - NEXT_PUBLIC_API_URL=https://$STAGING_HOST/api
      - NEXT_PUBLIC_APP_ENV=staging
    depends_on:
      web:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000"]
      interval: 30s
      timeout: 10s
      retries: 3
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.catlink-staging.rule=Host(\`$STAGING_HOST\`)"
      - "traefik.http.routers.catlink-staging.tls=true"
      - "traefik.http.routers.catlink-staging.tls.certresolver=letsencrypt"
      - "traefik.http.services.catlink-staging.loadbalancer.server.port=3000"

volumes:
  postgres_data:
  redis_data:
  media_data:
  static_data:

networks:
  default:
    external:
      name: traefik_default
EOF

# Создание скрипта инициализации БД
cat > /tmp/staging-deploy/init.sql << 'EOF'
-- Staging database initialization
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";

-- Create indexes for performance
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_links_created_at ON links_link(created_at);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_linkgroups_created_at ON links_linkgroup(created_at);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_users_email ON users_user(email);

-- Insert test data for staging
INSERT INTO users_user (id, email, username, first_name, last_name, is_active, date_joined, password) 
VALUES (
    uuid_generate_v4(),
    'staging@catlink.dev',
    'staging_user',
    'Staging',
    'User',
    true,
    NOW(),
    'pbkdf2_sha256$600000$test$staging'
) ON CONFLICT DO NOTHING;
EOF

# Создание файла окружения для staging
cat > /tmp/staging-deploy/.env.staging << EOF
# Staging Environment Variables
COMPOSE_PROJECT_NAME=catlink-staging
POSTGRES_PASSWORD=\${POSTGRES_PASSWORD}
SECRET_KEY=\${SECRET_KEY}

# Application settings
APP_VERSION=$VERSION
DEPLOY_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
COMMIT_SHA=${DRONE_COMMIT_SHA:-$(git rev-parse HEAD 2>/dev/null || echo "unknown")}

# Monitoring
ENABLE_DEBUG_TOOLBAR=false
LOG_LEVEL=INFO

# Backup settings
BACKUP_SCHEDULE=0 2 * * *
BACKUP_RETENTION_DAYS=7
EOF

# Создание скрипта для управления staging
cat > /tmp/staging-deploy/manage-staging.sh << 'EOF'
#!/bin/bash
# Staging management script

set -e

COMPOSE_FILE="docker-compose.staging.yml"
PROJECT_NAME="catlink-staging"

case "$1" in
    "start")
        echo "🚀 Starting staging environment..."
        docker-compose -f $COMPOSE_FILE -p $PROJECT_NAME up -d
        echo "✅ Staging environment started"
        ;;
    "stop")
        echo "🛑 Stopping staging environment..."
        docker-compose -f $COMPOSE_FILE -p $PROJECT_NAME down
        echo "✅ Staging environment stopped"
        ;;
    "restart")
        echo "🔄 Restarting staging environment..."
        docker-compose -f $COMPOSE_FILE -p $PROJECT_NAME restart
        echo "✅ Staging environment restarted"
        ;;
    "logs")
        docker-compose -f $COMPOSE_FILE -p $PROJECT_NAME logs -f ${2:-}
        ;;
    "status")
        docker-compose -f $COMPOSE_FILE -p $PROJECT_NAME ps
        ;;
    "update")
        echo "📦 Updating staging environment..."
        docker-compose -f $COMPOSE_FILE -p $PROJECT_NAME pull
        docker-compose -f $COMPOSE_FILE -p $PROJECT_NAME up -d
        echo "✅ Staging environment updated"
        ;;
    "backup")
        echo "💾 Creating staging backup..."
        docker-compose -f $COMPOSE_FILE -p $PROJECT_NAME exec postgres pg_dump -U catlink_user catlink_staging > "backup-staging-$(date +%Y%m%d-%H%M%S).sql"
        echo "✅ Backup created"
        ;;
    "migrate")
        echo "🔄 Running database migrations..."
        docker-compose -f $COMPOSE_FILE -p $PROJECT_NAME exec web python manage.py migrate
        echo "✅ Migrations completed"
        ;;
    "shell")
        docker-compose -f $COMPOSE_FILE -p $PROJECT_NAME exec web python manage.py shell
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|logs|status|update|backup|migrate|shell}"
        echo ""
        echo "Commands:"
        echo "  start   - Start staging environment"
        echo "  stop    - Stop staging environment"
        echo "  restart - Restart staging environment"
        echo "  logs    - Show logs (optionally specify service)"
        echo "  status  - Show containers status"
        echo "  update  - Update images and restart"
        echo "  backup  - Create database backup"
        echo "  migrate - Run database migrations"
        echo "  shell   - Open Django shell"
        exit 1
        ;;
esac
EOF

chmod +x /tmp/staging-deploy/manage-staging.sh

# Создание скрипта мониторинга
cat > /tmp/staging-deploy/monitor-staging.sh << 'EOF'
#!/bin/bash
# Staging monitoring script

set -e

PROJECT_NAME="catlink-staging"
HEALTH_CHECK_URL="https://staging.catlink.dev/api/"
FRONTEND_URL="https://staging.catlink.dev/"

echo "🔍 Monitoring staging environment..."

# Проверка контейнеров
echo "📦 Container status:"
docker-compose -p $PROJECT_NAME ps

# Проверка здоровья сервисов
echo ""
echo "🏥 Health checks:"

# Backend
backend_status=$(curl -s -o /dev/null -w "%{http_code}" "$HEALTH_CHECK_URL" || echo "000")
if [ "$backend_status" = "200" ]; then
    echo "  ✅ Backend: OK ($backend_status)"
else
    echo "  ❌ Backend: FAILED ($backend_status)"
fi

# Frontend
frontend_status=$(curl -s -o /dev/null -w "%{http_code}" "$FRONTEND_URL" || echo "000")
if [ "$frontend_status" = "200" ]; then
    echo "  ✅ Frontend: OK ($frontend_status)"
else
    echo "  ❌ Frontend: FAILED ($frontend_status)"
fi

# Проверка ресурсов
echo ""
echo "📊 Resource usage:"
docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}" | grep $PROJECT_NAME || echo "No containers running"

# Проверка логов на ошибки
echo ""
echo "🔍 Recent errors:"
docker-compose -p $PROJECT_NAME logs --tail=50 2>&1 | grep -i error | tail -5 || echo "No recent errors found"
EOF

chmod +x /tmp/staging-deploy/monitor-staging.sh

# Копирование файлов на staging сервер
echo "📤 Copying deployment files to staging server..."
scp -r /tmp/staging-deploy/* staging:/opt/catlink-staging/

# Деплой на staging сервер
echo "🚀 Deploying to staging server..."

ssh staging << 'EOF'
cd /opt/catlink-staging

# Создание резервной копии текущей версии
if [ -f docker-compose.staging.yml ]; then
    echo "💾 Creating backup of current deployment..."
    cp docker-compose.staging.yml docker-compose.staging.yml.backup
    ./manage-staging.sh backup || echo "Backup failed, continuing..."
fi

# Загрузка переменных окружения
source .env.staging 2>/dev/null || echo "No existing .env.staging found"

# Остановка текущих контейнеров
echo "🛑 Stopping current containers..."
./manage-staging.sh stop || echo "No containers to stop"

# Удаление старых образов
echo "🧹 Cleaning up old images..."
docker image prune -f || true

# Запуск новой версии
echo "🚀 Starting new version..."
./manage-staging.sh start

# Ожидание запуска сервисов
echo "⏳ Waiting for services to start..."
sleep 30

# Выполнение миграций
echo "🔄 Running database migrations..."
./manage-staging.sh migrate

# Проверка здоровья
echo "🏥 Checking deployment health..."
./monitor-staging.sh

echo "✅ Staging deployment completed!"
EOF

# Проверка деплоя
echo "🔍 Verifying staging deployment..."
sleep 10

# Проверка доступности API
api_status=$(curl -s -o /dev/null -w "%{http_code}" "https://$STAGING_HOST/api/" || echo "000")
frontend_status=$(curl -s -o /dev/null -w "%{http_code}" "https://$STAGING_HOST/" || echo "000")

echo "📊 Deployment verification:"
echo "  • API Status: $api_status"
echo "  • Frontend Status: $frontend_status"

if [ "$api_status" = "200" ] && [ "$frontend_status" = "200" ]; then
    echo "✅ Staging deployment verified successfully!"
else
    echo "❌ Staging deployment verification failed"
    
    # Получение логов для диагностики
    echo "📋 Getting deployment logs for diagnosis..."
    ssh staging "cd /opt/catlink-staging && ./manage-staging.sh logs --tail=50"
    
    exit 1
fi

# Уведомления о деплое
echo "📢 Sending deployment notifications..."

# Slack уведомление
if [ -n "$SLACK_WEBHOOK_URL" ]; then
    curl -X POST -H 'Content-type: application/json' \
        --data "{
            \"text\": \"🚀 *CatLink $VERSION* deployed to staging!\",
            \"attachments\": [
                {
                    \"color\": \"good\",
                    \"fields\": [
                        {
                            \"title\": \"Environment\",
                            \"value\": \"Staging\",
                            \"short\": true
                        },
                        {
                            \"title\": \"URL\",
                            \"value\": \"https://$STAGING_HOST\",
                            \"short\": true
                        },
                        {
                            \"title\": \"Version\",
                            \"value\": \"$VERSION\",
                            \"short\": true
                        },
                        {
                            \"title\": \"Status\",
                            \"value\": \"✅ Healthy\",
                            \"short\": true
                        }
                    ]
                }
            ]
        }" \
        "$SLACK_WEBHOOK_URL" || echo "Failed to send Slack notification"
fi

# Создание отчета о деплое
cat > /tmp/staging-deploy-report.md << EOF
# Staging Deployment Report

## 📋 Deployment Information
- **Version**: $VERSION
- **Environment**: Staging
- **URL**: https://$STAGING_HOST
- **Deployed At**: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
- **Deployed By**: ${DRONE_COMMIT_AUTHOR:-"CI/CD Pipeline"}

## ✅ Verification Results
- **API Status**: $api_status
- **Frontend Status**: $frontend_status
- **Database**: Migrations applied successfully
- **Health Checks**: All services healthy

## 🔗 Quick Links
- [Staging Application](https://$STAGING_HOST)
- [API Documentation](https://$STAGING_HOST/api/docs/)
- [Admin Panel](https://$STAGING_HOST/admin/)

## 🛠️ Management Commands
\`\`\`bash
# SSH to staging server
ssh staging

# View logs
./manage-staging.sh logs

# Check status
./manage-staging.sh status

# Create backup
./manage-staging.sh backup

# Update deployment
./manage-staging.sh update
\`\`\`

## 📊 Next Steps
- [ ] Perform manual testing
- [ ] Validate new features
- [ ] Check performance metrics
- [ ] Prepare for production deployment
EOF

echo "✅ Staging deployment completed successfully!"
echo ""
echo "🔗 Staging URLs:"
echo "  🌐 Application: https://$STAGING_HOST"
echo "  📚 API Docs:    https://$STAGING_HOST/api/docs/"
echo "  🔧 Admin:       https://$STAGING_HOST/admin/"
echo ""
echo "📄 Deployment report: /tmp/staging-deploy-report.md"