---
# Deploy Veza V5 Ultra applications in containers
# Builds and runs backend, chat, stream, and web services

- name: Deploy Veza V5 Ultra applications
  hosts: edge
  become: true
  gather_facts: true

  vars:
    domain: "{{ domain | default('veza.talas.fr') }}"
    backend_container: "veza-backend"
    chat_container: "veza-chat"
    stream_container: "veza-stream"
    web_container: "veza-web"

  tasks:
    - name: Deploy Go Backend API
      block:
        - name: Install Go in backend container
          command: |
            incus exec {{ backend_container }} -- apt update
            incus exec {{ backend_container }} -- apt install -y wget git
            incus exec {{ backend_container }} -- wget https://go.dev/dl/go1.21.5.linux-amd64.tar.gz
            incus exec {{ backend_container }} -- tar -C /usr/local -xzf go1.21.5.linux-amd64.tar.gz
            incus exec {{ backend_container }} -- echo 'export PATH=$PATH:/usr/local/go/bin' >> /root/.bashrc
          register: go_install_result
          failed_when: false

        - name: Display Go installation result
          debug:
            var: go_install_result.stdout_lines

        - name: Create backend application directory
          command: |
            incus exec {{ backend_container }} -- mkdir -p /opt/veza-backend
          register: backend_dir_result
          failed_when: false

        - name: Copy backend source code (placeholder)
          command: |
            incus exec {{ backend_container }} -- bash -c 'cat > /opt/veza-backend/main.go << "EOF"
        package main

        import (
            "fmt"
            "log"
            "net/http"
            "os"
        )

        func main() {
            port := os.Getenv("PORT")
            if port == "" {
                port = "8080"
            }

            http.HandleFunc("/api/health", func(w http.ResponseWriter, r *http.Request) {
                w.Header().Set("Content-Type", "application/json")
                w.WriteHeader(http.StatusOK)
                fmt.Fprintf(w, `{"status":"ok","service":"veza-backend"}`)
            })

            http.HandleFunc("/api/", func(w http.ResponseWriter, r *http.Request) {
                w.Header().Set("Content-Type", "application/json")
                w.WriteHeader(http.StatusOK)
                fmt.Fprintf(w, `{"message":"Veza V5 Ultra Backend API","version":"1.0.0"}`)
            })

            log.Printf("Backend API server starting on port %s", port)
            log.Fatal(http.ListenAndServe(":"+port, nil))
        }
        EOF'
          register: backend_code_result
          failed_when: false

        - name: Build backend application
          command: |
            incus exec {{ backend_container }} -- bash -c "cd /opt/veza-backend && /usr/local/go/bin/go mod init veza-backend && /usr/local/go/bin/go build -ldflags '-s -w' -o veza-backend main.go"
          register: backend_build_result
          failed_when: false

        - name: Create backend systemd service
          command: |
            incus exec {{ backend_container }} -- bash -c 'cat > /etc/systemd/system/veza-backend.service << "EOF"
        [Unit]
        Description=Veza V5 Ultra Backend API
        After=network.target

        [Service]
        Type=simple
        User=root
        WorkingDirectory=/opt/veza-backend
        ExecStart=/opt/veza-backend/veza-backend
        Restart=always
        RestartSec=5
        Environment=PORT=8080
        Environment=DATABASE_URL=postgresql://veza:password@localhost:5432/veza_db
        Environment=REDIS_URL=redis://localhost:6379
        Environment=JWT_SECRET=super-secret-jwt-key
        Environment=JWT_REFRESH_SECRET=super-secret-refresh-key

        [Install]
        WantedBy=multi-user.target
        EOF'
          register: backend_service_result
          failed_when: false

        - name: Start backend service
          command: |
            incus exec {{ backend_container }} -- systemctl daemon-reload
            incus exec {{ backend_container }} -- systemctl enable veza-backend
            incus exec {{ backend_container }} -- systemctl start veza-backend
          register: backend_start_result
          failed_when: false

        - name: Check backend service status
          command: |
            incus exec {{ backend_container }} -- systemctl status veza-backend
          register: backend_status
          failed_when: false

        - name: Display backend status
          debug:
            var: backend_status.stdout_lines

      rescue:
        - name: Backend deployment failed
          debug:
            msg: "Backend deployment failed, continuing with other services"

    - name: Deploy Rust Chat Server
      block:
        - name: Install Rust in chat container
          command: |
            incus exec {{ chat_container }} -- apt update
            incus exec {{ chat_container }} -- apt install -y curl git
            incus exec {{ chat_container }} -- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
            incus exec {{ chat_container }} -- bash -c "source /root/.cargo/env && cargo --version"
          register: rust_install_result
          failed_when: false

        - name: Display Rust installation result
          debug:
            var: rust_install_result.stdout_lines

        - name: Create chat application directory
          command: |
            incus exec {{ chat_container }} -- mkdir -p /opt/veza-chat
          register: chat_dir_result
          failed_when: false

        - name: Copy chat source code (placeholder)
          command: |
            incus exec {{ chat_container }} -- bash -c 'cat > /opt/veza-chat/Cargo.toml << "EOF"
        [package]
        name = "veza-chat"
        version = "0.1.0"
        edition = "2021"

        [dependencies]
        tokio = { version = "1.0", features = ["full"] }
        axum = "0.7"
        tower = "0.4"
        tower-http = { version = "0.5", features = ["cors"] }
        serde = { version = "1.0", features = ["derive"] }
        serde_json = "1.0"
        uuid = { version = "1.0", features = ["v4"] }
        tracing = "0.1"
        tracing-subscriber = "0.3"
        EOF'
          register: chat_cargo_result
          failed_when: false

        - name: Create chat main.rs
          command: |
            incus exec {{ chat_container }} -- tee /opt/veza-chat/src/main.rs << 'EOF'
        use axum::{
            extract::ws::{Message, WebSocket, WebSocketUpgrade},
            response::Response,
            routing::get,
            Router,
        };
        use std::net::SocketAddr;
        use tokio::net::TcpListener;
        use tracing::{info, warn};

        #[tokio::main]
        async fn main() {
            tracing_subscriber::init();
            
            let app = Router::new()
                .route("/ws", get(websocket_handler))
                .route("/health", get(health_handler));

            let addr = SocketAddr::from(([0, 0, 0, 0], 8081));
            info!("Chat server starting on {}", addr);

            let listener = TcpListener::bind(addr).await.unwrap();
            axum::serve(listener, app).await.unwrap();
        }

        async fn websocket_handler(ws: WebSocketUpgrade) -> Response {
            ws.on_upgrade(handle_websocket)
        }

        async fn handle_websocket(socket: WebSocket) {
            info!("New WebSocket connection");
            
            // Simple echo server for now
            let (mut sender, mut receiver) = socket.split();
            
            while let Some(msg) = receiver.recv().await {
                match msg {
                    Ok(Message::Text(text)) => {
                        info!("Received: {}", text);
                        if sender.send(Message::Text(format!("Echo: {}", text))).await.is_err() {
                            break;
                        }
                    }
                    Ok(Message::Close(_)) => break,
                    Err(e) => {
                        warn!("WebSocket error: {}", e);
                        break;
                    }
                    _ => {}
                }
            }
            
            info!("WebSocket connection closed");
        }

        async fn health_handler() -> &'static str {
            "OK"
        }
        EOF
          register: chat_main_result
          failed_when: false

        - name: Build chat application
          command: |
            incus exec {{ chat_container }} -- bash -c "cd /opt/veza-chat && source /root/.cargo/env && cargo build --release"
          register: chat_build_result
          failed_when: false

        - name: Create chat systemd service
          command: |
            incus exec {{ chat_container }} -- tee /etc/systemd/system/veza-chat.service << 'EOF'
        [Unit]
        Description=Veza V5 Ultra Chat Server
        After=network.target

        [Service]
        Type=simple
        User=root
        WorkingDirectory=/opt/veza-chat
        ExecStart=/opt/veza-chat/target/release/veza-chat
        Restart=always
        RestartSec=5
        Environment=SQLX_OFFLINE=true

        [Install]
        WantedBy=multi-user.target
        EOF
          register: chat_service_result
          failed_when: false

        - name: Start chat service
          command: |
            incus exec {{ chat_container }} -- systemctl daemon-reload
            incus exec {{ chat_container }} -- systemctl enable veza-chat
            incus exec {{ chat_container }} -- systemctl start veza-chat
          register: chat_start_result
          failed_when: false

        - name: Check chat service status
          command: |
            incus exec {{ chat_container }} -- systemctl status veza-chat
          register: chat_status
          failed_when: false

        - name: Display chat status
          debug:
            var: chat_status.stdout_lines

      rescue:
        - name: Chat deployment failed
          debug:
            msg: "Chat deployment failed, continuing with other services"

    - name: Deploy Rust Stream Server
      block:
        - name: Install Rust in stream container
          command: |
            incus exec {{ stream_container }} -- apt update
            incus exec {{ stream_container }} -- apt install -y curl git
            incus exec {{ stream_container }} -- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
          register: stream_rust_install_result
          failed_when: false

        - name: Create stream application directory
          command: |
            incus exec {{ stream_container }} -- mkdir -p /opt/veza-stream
          register: stream_dir_result
          failed_when: false

        - name: Copy stream source code (placeholder)
          command: |
            incus exec {{ stream_container }} -- tee /opt/veza-stream/Cargo.toml << 'EOF'
        [package]
        name = "veza-stream"
        version = "0.1.0"
        edition = "2021"

        [dependencies]
        tokio = { version = "1.0", features = ["full"] }
        axum = "0.7"
        tower = "0.4"
        tower-http = { version = "0.5", features = ["cors", "fs"] }
        serde = { version = "1.0", features = ["derive"] }
        serde_json = "1.0"
        tracing = "0.1"
        tracing-subscriber = "0.3"
        EOF
          register: stream_cargo_result
          failed_when: false

        - name: Create stream main.rs
          command: |
            incus exec {{ stream_container }} -- tee /opt/veza-stream/src/main.rs << 'EOF'
        use axum::{
            extract::Path,
            http::StatusCode,
            response::Response,
            routing::get,
            Router,
        };
        use std::net::SocketAddr;
        use tokio::net::TcpListener;
        use tracing::{info, warn};

        #[tokio::main]
        async fn main() {
            tracing_subscriber::init();
            
            let app = Router::new()
                .route("/stream/health", get(health_handler))
                .route("/stream/:file", get(stream_handler));

            let addr = SocketAddr::from(([0, 0, 0, 0], 8082));
            info!("Stream server starting on {}", addr);

            let listener = TcpListener::bind(addr).await.unwrap();
            axum::serve(listener, app).await.unwrap();
        }

        async fn health_handler() -> &'static str {
            "OK"
        }

        async fn stream_handler(Path(file): Path<String>) -> Result<Response, StatusCode> {
            info!("Stream request for: {}", file);
            
            // Simple file serving for now
            if file.ends_with(".m3u8") {
                Ok(Response::builder()
                    .status(200)
                    .header("Content-Type", "application/vnd.apple.mpegurl")
                    .body(format!("#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-TARGETDURATION:10\n#EXTINF:10.0,\n{}.ts\n#EXT-X-ENDLIST\n", file.replace(".m3u8", "")))
                    .unwrap())
            } else {
                Err(StatusCode::NOT_FOUND)
            }
        }
        EOF
          register: stream_main_result
          failed_when: false

        - name: Build stream application
          command: |
            incus exec {{ stream_container }} -- bash -c "cd /opt/veza-stream && source /root/.cargo/env && cargo build --release"
          register: stream_build_result
          failed_when: false

        - name: Create stream systemd service
          command: |
            incus exec {{ stream_container }} -- tee /etc/systemd/system/veza-stream.service << 'EOF'
        [Unit]
        Description=Veza V5 Ultra Stream Server
        After=network.target

        [Service]
        Type=simple
        User=root
        WorkingDirectory=/opt/veza-stream
        ExecStart=/opt/veza-stream/target/release/veza-stream
        Restart=always
        RestartSec=5

        [Install]
        WantedBy=multi-user.target
        EOF
          register: stream_service_result
          failed_when: false

        - name: Start stream service
          command: |
            incus exec {{ stream_container }} -- systemctl daemon-reload
            incus exec {{ stream_container }} -- systemctl enable veza-stream
            incus exec {{ stream_container }} -- systemctl start veza-stream
          register: stream_start_result
          failed_when: false

        - name: Check stream service status
          command: |
            incus exec {{ stream_container }} -- systemctl status veza-stream
          register: stream_status
          failed_when: false

        - name: Display stream status
          debug:
            var: stream_status.stdout_lines

      rescue:
        - name: Stream deployment failed
          debug:
            msg: "Stream deployment failed, continuing with web service"

    - name: Deploy React Web Application
      block:
        - name: Install Node.js in web container
          command: |
            incus exec {{ web_container }} -- apt update
            incus exec {{ web_container }} -- apt install -y curl
            incus exec {{ web_container }} -- curl -fsSL https://deb.nodesource.com/setup_18.x | bash -
            incus exec {{ web_container }} -- apt install -y nodejs nginx
          register: node_install_result
          failed_when: false

        - name: Display Node.js installation result
          debug:
            var: node_install_result.stdout_lines

        - name: Create web application directory
          command: |
            incus exec {{ web_container }} -- mkdir -p /opt/veza-web
          register: web_dir_result
          failed_when: false

        - name: Create simple React app (placeholder)
          command: |
            incus exec {{ web_container }} -- tee /opt/veza-web/package.json << 'EOF'
        {
          "name": "veza-web",
          "version": "1.0.0",
          "description": "Veza V5 Ultra Web Application",
          "main": "index.js",
          "scripts": {
            "start": "node server.js",
            "build": "echo 'Build completed'"
          },
          "dependencies": {
            "express": "^4.18.2"
          }
        }
        EOF
          register: web_package_result
          failed_when: false

        - name: Create simple web server
          command: |
            incus exec {{ web_container }} -- tee /opt/veza-web/server.js << 'EOF'
        const express = require('express');
        const app = express();
        const port = process.env.PORT || 3000;

        app.use(express.static('public'));

        app.get('/', (req, res) => {
            res.send(`
                <!DOCTYPE html>
                <html>
                <head>
                    <title>Veza V5 Ultra</title>
                    <style>
                        body { font-family: Arial, sans-serif; margin: 40px; }
                        .container { max-width: 800px; margin: 0 auto; }
                        .header { background: #2c3e50; color: white; padding: 20px; border-radius: 5px; }
                        .content { padding: 20px; }
                        .status { background: #27ae60; color: white; padding: 10px; border-radius: 3px; margin: 10px 0; }
                    </style>
                </head>
                <body>
                    <div class="container">
                        <div class="header">
                            <h1>🎵 Veza V5 Ultra</h1>
                            <p>Collaborative Audio Streaming Platform</p>
                        </div>
                        <div class="content">
                            <div class="status">✅ System Online</div>
                            <h2>Services Status</h2>
                            <ul>
                                <li>Backend API: <span id="api-status">Checking...</span></li>
                                <li>Chat WebSocket: <span id="chat-status">Checking...</span></li>
                                <li>Stream HLS: <span id="stream-status">Checking...</span></li>
                            </ul>
                            <h2>Features</h2>
                            <ul>
                                <li>Real-time collaborative audio streaming</li>
                                <li>WebSocket chat integration</li>
                                <li>HLS video streaming</li>
                                <li>Modern React frontend</li>
                            </ul>
                        </div>
                    </div>
                    <script>
                        // Simple health checks
                        fetch('/api/health').then(r => r.json()).then(d => {
                            document.getElementById('api-status').textContent = '✅ Online';
                        }).catch(() => {
                            document.getElementById('api-status').textContent = '❌ Offline';
                        });
                    </script>
                </body>
                </html>
            `);
        });

        app.listen(port, '0.0.0.0', () => {
            console.log(`Veza V5 Ultra web server running on port ${port}`);
        });
        EOF
          register: web_server_result
          failed_when: false

        - name: Install web dependencies
          command: |
            incus exec {{ web_container }} -- bash -c "cd /opt/veza-web && npm install"
          register: web_install_result
          failed_when: false

        - name: Create web systemd service
          command: |
            incus exec {{ web_container }} -- tee /etc/systemd/system/veza-web.service << 'EOF'
        [Unit]
        Description=Veza V5 Ultra Web Application
        After=network.target

        [Service]
        Type=simple
        User=root
        WorkingDirectory=/opt/veza-web
        ExecStart=/usr/bin/node server.js
        Restart=always
        RestartSec=5
        Environment=PORT=3000

        [Install]
        WantedBy=multi-user.target
        EOF
          register: web_service_result
          failed_when: false

        - name: Start web service
          command: |
            incus exec {{ web_container }} -- systemctl daemon-reload
            incus exec {{ web_container }} -- systemctl enable veza-web
            incus exec {{ web_container }} -- systemctl start veza-web
          register: web_start_result
          failed_when: false

        - name: Check web service status
          command: |
            incus exec {{ web_container }} -- systemctl status veza-web
          register: web_status
          failed_when: false

        - name: Display web status
          debug:
            var: web_status.stdout_lines

      rescue:
        - name: Web deployment failed
          debug:
            msg: "Web deployment failed"

  post_tasks:
    - name: Show all running services
      command: |
        incus exec {{ backend_container }} -- systemctl list-units --type=service --state=running | grep veza || true
        incus exec {{ chat_container }} -- systemctl list-units --type=service --state=running | grep veza || true
        incus exec {{ stream_container }} -- systemctl list-units --type=service --state=running | grep veza || true
        incus exec {{ web_container }} -- systemctl list-units --type=service --state=running | grep veza || true
      register: all_services
      failed_when: false

    - name: Display all services
      debug:
        var: all_services.stdout_lines