# GameForge Integration - Implementation Examples

This document provides practical examples for integrating AeThex Connect with GameForge.

---

## Example 1: Complete Project Lifecycle

### Step 1: Create Project in GameForge

```javascript
// GameForge: src/services/projectService.js

const crypto = require('crypto');

function generateSignature(payload, secret) {
  const timestamp = Date.now().toString();
  const data = JSON.stringify(payload);
  return {
    signature: crypto
      .createHmac('sha256', secret)
      .update(`${timestamp}.${data}`)
      .digest('hex'),
    timestamp
  };
}

async function createProject(projectData, userId) {
  // 1. Create project in GameForge database
  const project = await db.projects.create({
    name: projectData.name,
    description: projectData.description,
    owner_id: userId,
    created_at: new Date()
  });

  // 2. Get owner's AeThex identifier
  const owner = await db.users.findById(userId);
  const ownerIdentifier = `${owner.username}@dev.aethex.dev`;

  // 3. Provision AeThex Connect channels
  const connectPayload = {
    projectId: project.id,
    name: project.name,
    ownerId: userId,
    ownerIdentifier: ownerIdentifier,
    teamMembers: [],
    settings: {
      autoProvisionChannels: true,
      defaultChannels: ['general', 'dev', 'art', 'design'],
      customChannels: []
    }
  };

  const { signature, timestamp } = generateSignature(
    connectPayload,
    process.env.AETHEX_CONNECT_API_SECRET
  );

  try {
    const response = await fetch('https://connect.aethex.app/api/gameforge/projects', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-GameForge-API-Key': process.env.AETHEX_CONNECT_API_KEY,
        'X-GameForge-Signature': signature,
        'X-GameForge-Timestamp': timestamp
      },
      body: JSON.stringify(connectPayload)
    });

    const connectData = await response.json();

    if (connectData.success) {
      // Store integration data
      await db.projects.update(project.id, {
        connect_domain: connectData.integration.domain,
        connect_channels: connectData.integration.channels
      });

      console.log(`✅ Provisioned ${connectData.integration.channels.length} channels`);
    } else {
      console.error('Failed to provision AeThex Connect:', connectData.error);
    }

  } catch (error) {
    console.error('AeThex Connect provisioning error:', error);
    // Non-critical - project still created
  }

  return project;
}
```

### Step 2: Add Team Members

```javascript
// GameForge: src/services/teamService.js

async function addTeamMember(projectId, userId, role) {
  // 1. Add to GameForge team
  const teamMember = await db.projectTeams.create({
    project_id: projectId,
    user_id: userId,
    role: role,
    joined_at: new Date()
  });

  // 2. Get user's AeThex identifier
  const user = await db.users.findById(userId);
  const identifier = `${user.username}@dev.aethex.dev`;

  // 3. Update AeThex Connect
  const payload = {
    action: 'add',
    members: [{
      userId: userId,
      identifier: identifier,
      role: role
    }]
  };

  const { signature, timestamp } = generateSignature(
    payload,
    process.env.AETHEX_CONNECT_API_SECRET
  );

  try {
    const response = await fetch(
      `https://connect.aethex.app/api/gameforge/projects/${projectId}/team`,
      {
        method: 'PATCH',
        headers: {
          'Content-Type': 'application/json',
          'X-GameForge-API-Key': process.env.AETHEX_CONNECT_API_KEY,
          'X-GameForge-Signature': signature,
          'X-GameForge-Timestamp': timestamp
        },
        body: JSON.stringify(payload)
      }
    );

    const data = await response.json();
    console.log(`✅ Added to ${data.updated[0].addedToChannels.length} channels`);

  } catch (error) {
    console.error('Failed to update AeThex Connect team:', error);
  }

  return teamMember;
}

async function removeTeamMember(projectId, userId) {
  // 1. Remove from GameForge team
  await db.projectTeams.delete({
    project_id: projectId,
    user_id: userId
  });

  // 2. Remove from AeThex Connect
  const payload = {
    action: 'remove',
    members: [{ userId: userId }]
  };

  const { signature, timestamp } = generateSignature(
    payload,
    process.env.AETHEX_CONNECT_API_SECRET
  );

  await fetch(
    `https://connect.aethex.app/api/gameforge/projects/${projectId}/team`,
    {
      method: 'PATCH',
      headers: {
        'Content-Type': 'application/json',
        'X-GameForge-API-Key': process.env.AETHEX_CONNECT_API_KEY,
        'X-GameForge-Signature': signature,
        'X-GameForge-Timestamp': timestamp
      },
      body: JSON.stringify(payload)
    }
  );
}

async function updateMemberRole(projectId, userId, newRole) {
  // 1. Update in GameForge
  await db.projectTeams.update({
    project_id: projectId,
    user_id: userId
  }, {
    role: newRole
  });

  // 2. Update in AeThex Connect
  const user = await db.users.findById(userId);
  const payload = {
    action: 'update_role',
    members: [{
      userId: userId,
      identifier: `${user.username}@dev.aethex.dev`,
      role: newRole
    }]
  };

  const { signature, timestamp } = generateSignature(
    payload,
    process.env.AETHEX_CONNECT_API_SECRET
  );

  await fetch(
    `https://connect.aethex.app/api/gameforge/projects/${projectId}/team`,
    {
      method: 'PATCH',
      headers: {
        'Content-Type': 'application/json',
        'X-GameForge-API-Key': process.env.AETHEX_CONNECT_API_KEY,
        'X-GameForge-Signature': signature,
        'X-GameForge-Timestamp': timestamp
      },
      body: JSON.stringify(payload)
    }
  );
}
```

### Step 3: Send Notifications

```javascript
// GameForge: src/services/buildService.js

async function onBuildComplete(buildId, projectId, status) {
  const build = await db.builds.findById(buildId);

  const notification = {
    channelName: 'dev',
    type: 'build',
    title: `Build #${build.number} ${status === 'success' ? 'Completed' : 'Failed'}`,
    message: status === 'success'
      ? `Build completed successfully in ${formatDuration(build.duration)}`
      : `Build failed: ${build.error}`,
    metadata: {
      buildNumber: build.number,
      status: status,
      duration: build.duration,
      commitHash: build.commit_hash.substring(0, 7),
      branch: build.branch
    },
    actions: [
      {
        label: 'View Build',
        url: `https://gameforge.aethex.dev/projects/${projectId}/builds/${buildId}`
      },
      {
        label: 'View Logs',
        url: `https://gameforge.aethex.dev/projects/${projectId}/builds/${buildId}/logs`
      }
    ]
  };

  const { signature, timestamp } = generateSignature(
    notification,
    process.env.AETHEX_CONNECT_API_SECRET
  );

  await fetch(
    `https://connect.aethex.app/api/gameforge/projects/${projectId}/notify`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-GameForge-API-Key': process.env.AETHEX_CONNECT_API_KEY,
        'X-GameForge-Signature': signature,
        'X-GameForge-Timestamp': timestamp
      },
      body: JSON.stringify(notification)
    }
  );
}

// GameForge: src/services/gitService.js

async function onCommitPushed(commitData, projectId) {
  const notification = {
    channelName: 'dev',
    type: 'commit',
    title: 'New Commit Pushed',
    message: commitData.message,
    metadata: {
      author: commitData.author,
      hash: commitData.hash.substring(0, 7),
      branch: commitData.branch,
      filesChanged: commitData.stats.filesChanged
    },
    actions: [
      {
        label: 'View Commit',
        url: `https://gameforge.aethex.dev/projects/${projectId}/commits/${commitData.hash}`
      }
    ]
  };

  const { signature, timestamp } = generateSignature(
    notification,
    process.env.AETHEX_CONNECT_API_SECRET
  );

  await fetch(
    `https://connect.aethex.app/api/gameforge/projects/${projectId}/notify`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-GameForge-API-Key': process.env.AETHEX_CONNECT_API_KEY,
        'X-GameForge-Signature': signature,
        'X-GameForge-Timestamp': timestamp
      },
      body: JSON.stringify(notification)
    }
  );
}

// GameForge: src/services/deploymentService.js

async function onDeploymentComplete(deploymentId, projectId, status) {
  const deployment = await db.deployments.findById(deploymentId);

  const notification = {
    channelName: 'general',
    type: 'deployment',
    title: `Deployment ${status === 'success' ? 'Successful' : 'Failed'}`,
    message: status === 'success'
      ? `Successfully deployed to ${deployment.environment}`
      : `Deployment to ${deployment.environment} failed`,
    metadata: {
      environment: deployment.environment,
      version: deployment.version,
      status: status
    },
    actions: [
      {
        label: 'View Deployment',
        url: `https://gameforge.aethex.dev/projects/${projectId}/deployments/${deploymentId}`
      }
    ]
  };

  const { signature, timestamp } = generateSignature(
    notification,
    process.env.AETHEX_CONNECT_API_SECRET
  );

  await fetch(
    `https://connect.aethex.app/api/gameforge/projects/${projectId}/notify`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-GameForge-API-Key': process.env.AETHEX_CONNECT_API_KEY,
        'X-GameForge-Signature': signature,
        'X-GameForge-Timestamp': timestamp
      },
      body: JSON.stringify(notification)
    }
  );
}
```

### Step 4: Archive Project

```javascript
// GameForge: src/services/projectService.js

async function archiveProject(projectId) {
  // 1. Archive in GameForge
  await db.projects.update(projectId, {
    is_archived: true,
    archived_at: new Date()
  });

  // 2. Archive AeThex Connect channels
  const { signature, timestamp } = generateSignature(
    {},
    process.env.AETHEX_CONNECT_API_SECRET
  );

  await fetch(
    `https://connect.aethex.app/api/gameforge/projects/${projectId}`,
    {
      method: 'DELETE',
      headers: {
        'Content-Type': 'application/json',
        'X-GameForge-API-Key': process.env.AETHEX_CONNECT_API_KEY,
        'X-GameForge-Signature': signature,
        'X-GameForge-Timestamp': timestamp
      }
    }
  );
}
```

---

## Example 2: Embedded Chat Component

### React Integration

```javascript
// GameForge: src/pages/ProjectPage.jsx

import React from 'react';
import { useParams } from 'react-router-dom';
import GameForgeChat from '@aethex/connect/components/GameForgeChat';

export default function ProjectPage() {
  const { projectId } = useParams();

  return (
    <div className="project-page">
      <div className="project-header">
        <h1>My Game Project</h1>
        <ProjectMenu />
      </div>

      <div className="project-content">
        <div className="project-main">
          <ProjectDashboard />
        </div>

        <div className="project-chat">
          <GameForgeChat 
            projectId={projectId} 
            embedded={true}
          />
        </div>
      </div>
    </div>
  );
}
```

### Iframe Integration

```html
<!-- GameForge: templates/project.html -->

<!DOCTYPE html>
<html>
<head>
  <title>{{ project.name }} - GameForge</title>
  <style>
    .chat-container {
      height: 600px;
      border: 1px solid #e0e0e0;
      border-radius: 8px;
      overflow: hidden;
    }
  </style>
</head>
<body>
  <div class="project-layout">
    <div class="project-main">
      <!-- Project content -->
    </div>

    <div class="project-sidebar">
      <h3>Team Chat</h3>
      <div class="chat-container">
        <iframe 
          src="https://connect.aethex.app/gameforge/project/{{ project.id }}/chat"
          width="100%"
          height="100%"
          frameborder="0"
          allow="microphone; camera"
        ></iframe>
      </div>
    </div>
  </div>
</body>
</html>
```

---

## Example 3: Testing Integration

### Integration Test Suite

```javascript
// GameForge: tests/aethex-connect.test.js

const { generateSignature } = require('../utils/signature');

describe('AeThex Connect Integration', () => {
  let testProjectId;

  beforeAll(async () => {
    // Setup test environment
  });

  test('should provision project with channels', async () => {
    const payload = {
      projectId: 'test-project-1',
      name: 'Test Game',
      ownerId: 'test-user-1',
      ownerIdentifier: 'testuser@dev.aethex.dev',
      teamMembers: [],
      settings: {
        autoProvisionChannels: true,
        defaultChannels: ['general', 'dev']
      }
    };

    const { signature, timestamp } = generateSignature(
      payload,
      process.env.AETHEX_CONNECT_API_SECRET
    );

    const response = await fetch('https://connect.aethex.app/api/gameforge/projects', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-GameForge-API-Key': process.env.AETHEX_CONNECT_API_KEY,
        'X-GameForge-Signature': signature,
        'X-GameForge-Timestamp': timestamp
      },
      body: JSON.stringify(payload)
    });

    const data = await response.json();

    expect(data.success).toBe(true);
    expect(data.integration.channels).toHaveLength(2);
    expect(data.integration.domain).toBe('test-game@forge.aethex.dev');

    testProjectId = 'test-project-1';
  });

  test('should add team member to appropriate channels', async () => {
    const payload = {
      action: 'add',
      members: [{
        userId: 'test-user-2',
        identifier: 'developer@dev.aethex.dev',
        role: 'developer'
      }]
    };

    const { signature, timestamp } = generateSignature(
      payload,
      process.env.AETHEX_CONNECT_API_SECRET
    );

    const response = await fetch(
      `https://connect.aethex.app/api/gameforge/projects/${testProjectId}/team`,
      {
        method: 'PATCH',
        headers: {
          'Content-Type': 'application/json',
          'X-GameForge-API-Key': process.env.AETHEX_CONNECT_API_KEY,
          'X-GameForge-Signature': signature,
          'X-GameForge-Timestamp': timestamp
        },
        body: JSON.stringify(payload)
      }
    );

    const data = await response.json();

    expect(data.success).toBe(true);
    expect(data.updated[0].addedToChannels.length).toBeGreaterThan(0);
  });

  test('should send system notification', async () => {
    const notification = {
      channelName: 'dev',
      type: 'build',
      title: 'Build #1 Completed',
      message: 'Test build completed successfully',
      metadata: {
        buildNumber: 1,
        status: 'success'
      }
    };

    const { signature, timestamp } = generateSignature(
      notification,
      process.env.AETHEX_CONNECT_API_SECRET
    );

    const response = await fetch(
      `https://connect.aethex.app/api/gameforge/projects/${testProjectId}/notify`,
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-GameForge-API-Key': process.env.AETHEX_CONNECT_API_KEY,
          'X-GameForge-Signature': signature,
          'X-GameForge-Timestamp': timestamp
        },
        body: JSON.stringify(notification)
      }
    );

    const data = await response.json();

    expect(data.success).toBe(true);
    expect(data.messageId).toBeDefined();
    expect(data.channelId).toBeDefined();
  });

  afterAll(async () => {
    // Cleanup test data
  });
});
```

---

## Example 4: Error Handling

```javascript
// GameForge: src/utils/aethexConnect.js

class AeThexConnectClient {
  constructor(apiKey, apiSecret, baseUrl = 'https://connect.aethex.app') {
    this.apiKey = apiKey;
    this.apiSecret = apiSecret;
    this.baseUrl = baseUrl;
  }

  generateSignature(payload) {
    const crypto = require('crypto');
    const timestamp = Date.now().toString();
    const data = JSON.stringify(payload);
    const signature = crypto
      .createHmac('sha256', this.apiSecret)
      .update(`${timestamp}.${data}`)
      .digest('hex');
    return { signature, timestamp };
  }

  async request(endpoint, method, payload) {
    const { signature, timestamp } = this.generateSignature(payload);

    try {
      const response = await fetch(`${this.baseUrl}${endpoint}`, {
        method,
        headers: {
          'Content-Type': 'application/json',
          'X-GameForge-API-Key': this.apiKey,
          'X-GameForge-Signature': signature,
          'X-GameForge-Timestamp': timestamp
        },
        body: method !== 'GET' ? JSON.stringify(payload) : undefined
      });

      const data = await response.json();

      if (!response.ok) {
        throw new Error(data.error || 'Request failed');
      }

      return data;

    } catch (error) {
      console.error(`AeThex Connect ${method} ${endpoint} failed:`, error);
      throw error;
    }
  }

  async provisionProject(projectData) {
    return this.request('/api/gameforge/projects', 'POST', projectData);
  }

  async updateTeam(projectId, action, members) {
    return this.request(
      `/api/gameforge/projects/${projectId}/team`,
      'PATCH',
      { action, members }
    );
  }

  async sendNotification(projectId, notification) {
    return this.request(
      `/api/gameforge/projects/${projectId}/notify`,
      'POST',
      notification
    );
  }

  async archiveProject(projectId) {
    return this.request(
      `/api/gameforge/projects/${projectId}`,
      'DELETE',
      {}
    );
  }
}

// Usage
const connectClient = new AeThexConnectClient(
  process.env.AETHEX_CONNECT_API_KEY,
  process.env.AETHEX_CONNECT_API_SECRET
);

// Provision with error handling
try {
  const result = await connectClient.provisionProject({
    projectId: project.id,
    name: project.name,
    ownerId: userId,
    ownerIdentifier: `${user.username}@dev.aethex.dev`,
    teamMembers: [],
    settings: {
      autoProvisionChannels: true,
      defaultChannels: ['general', 'dev']
    }
  });

  console.log('✅ Provisioned:', result.integration.domain);
} catch (error) {
  console.error('❌ Provisioning failed:', error.message);
  // Handle gracefully - project still usable without chat
}
```

---

## Utility Functions

```javascript
// GameForge: src/utils/helpers.js

function formatDuration(seconds) {
  const minutes = Math.floor(seconds / 60);
  const secs = seconds % 60;
  return minutes > 0 ? `${minutes}m ${secs}s` : `${secs}s`;
}

function getChannelForNotificationType(type) {
  const channelMap = {
    'build': 'dev',
    'commit': 'dev',
    'deployment': 'general',
    'issue': 'dev',
    'playtesting': 'playtesting',
    'announcement': 'announcements'
  };
  return channelMap[type] || 'general';
}

module.exports = {
  formatDuration,
  getChannelForNotificationType
};
```

---

These examples demonstrate complete integration patterns for GameForge projects with AeThex Connect.
