/**
 * Agents Council Integration for QwenClaw
 * 
 * Replaces Rig with Agents Council for multi-agent orchestration
 * while maintaining FULL RAG capabilities
 */

import { spawn } from "child_process";
import { join } from "path";
import { existsSync, readFileSync, writeFile } from "fs";

const COUNCIL_DIR = join(process.env.HOME || process.env.USERPROFILE || "", ".agents-council");
const QWENCLAW_DIR = process.env.QWENCLAW_DIR || join(process.env.HOME || process.env.USERPROFILE || "", "qwenclaw");
const STATE_FILE = join(COUNCIL_DIR, "state.json");

export interface CouncilConfig {
  autoStart: boolean;
  desktopApp: boolean;
  agents: Record<string, AgentConfig>;
  rag: RAGConfig;
}

export interface AgentConfig {
  enabled: boolean;
  model: string;
  autoSummon: boolean;
}

export interface RAGConfig {
  enabled: boolean;
  vectorStore: 'sqlite' | 'chroma' | 'pinecone';
  shareAcrossAgents: boolean;
  topK: number;
  threshold: number;
}

const DEFAULT_CONFIG: CouncilConfig = {
  autoStart: true,
  desktopApp: true,
  agents: {
    qwen: { enabled: true, model: 'qwen-plus', autoSummon: true },
    claude: { enabled: true, model: 'claude-sonnet-4-5-20250929', autoSummon: false },
    codex: { enabled: true, model: 'codex-latest', autoSummon: false },
  },
  rag: {
    enabled: true,
    vectorStore: 'sqlite',
    shareAcrossAgents: true,
    topK: 5,
    threshold: 0.7,
  },
};

/**
 * Agents Council Client
 */
export class AgentsCouncilClient {
  private config: CouncilConfig;
  private running: boolean = false;

  constructor(config: Partial<CouncilConfig> = {}) {
    this.config = { ...DEFAULT_CONFIG, ...config };
  }

  /**
   * Start Agents Council MCP server
   */
  async start(): Promise<void> {
    if (this.running) {
      console.log("[Council] Already running");
      return;
    }

    console.log("[Council] Starting Agents Council...");

    const councilProcess = spawn("npx", ["agents-council@latest", "mcp"], {
      stdio: ["pipe", "pipe", "pipe"],
      detached: false,
    });

    councilProcess.stdout?.on("data", (data) => {
      console.log(`[Council] ${data.toString().trim()}`);
    });

    councilProcess.stderr?.on("data", (data) => {
      console.error(`[Council Error] ${data.toString().trim()}`);
    });

    this.running = true;

    // Wait for council to start
    await new Promise((resolve) => setTimeout(resolve, 3000));
    console.log("[Council] ✅ Started");
  }

  /**
   * Stop council
   */
  async stop(): Promise<void> {
    this.running = false;
    console.log("[Council] Stopped");
  }

  /**
   * Summon agent to council
   */
  async summon(agent: string): Promise<void> {
    console.log(`[Council] Summoning ${agent}...`);
    
    return new Promise((resolve, reject) => {
      const proc = spawn("npx", ["agents-council@latest", "summon", agent], {
        stdio: "inherit",
      });

      proc.on("close", (code) => {
        if (code === 0) {
          console.log(`[Council] ✅ ${agent} summoned`);
          resolve();
        } else {
          reject(new Error(`Failed to summon ${agent}`));
        }
      });
    });
  }

  /**
   * Start multi-agent discussion
   */
  async discuss(options: DiscussionOptions): Promise<DiscussionResult> {
    console.log(`[Council] Starting discussion: ${options.topic}`);

    const args = [
      "agents-council@latest",
      "discuss",
      "--topic", options.topic,
      "--agents", options.agents.join(","),
    ];

    if (options.context) {
      args.push("--context", options.context);
    }

    if (options.ragContext) {
      args.push("--rag");
    }

    return new Promise((resolve, reject) => {
      const proc = spawn("npx", args, {
        stdio: ["pipe", "pipe", "pipe"],
      });

      let output = "";
      proc.stdout?.on("data", (data) => {
        output += data.toString();
      });

      proc.on("close", (code) => {
        if (code === 0) {
          resolve({
            summary: output,
            agents: options.agents,
            topic: options.topic,
          });
        } else {
          reject(new Error("Discussion failed"));
        }
      });
    });
  }

  /**
   * Get council status
   */
  async getStatus(): Promise<CouncilStatus> {
    if (!existsSync(STATE_FILE)) {
      return { running: false, agents: [] };
    }

    try {
      const state = JSON.parse(readFileSync(STATE_FILE, "utf-8"));
      return {
        running: this.running,
        agents: state.agents || [],
        discussions: state.discussions || 0,
      };
    } catch {
      return { running: false, agents: [] };
    }
  }

  /**
   * Open Council Hall desktop app
   */
  async monitor(): Promise<void> {
    console.log("[Council] Opening Council Hall...");
    
    spawn("npx", ["agents-council@latest", "desktop"], {
      detached: true,
      stdio: "ignore",
    });
  }
}

interface DiscussionOptions {
  topic: string;
  context?: string;
  agents: string[];
  roles?: Record<string, string>;
  ragContext?: boolean | RAGOptions;
  output?: 'markdown' | 'json';
  timeout?: number;
}

interface RAGOptions {
  searchQuery?: string;
  documents?: string[];
  topK?: number;
  includeInContext?: boolean;
}

interface DiscussionResult {
  summary: string;
  agents: string[];
  topic: string;
  ragDocuments?: any[];
}

interface CouncilStatus {
  running: boolean;
  agents: string[];
  discussions?: number;
}

/**
 * Initialize Agents Council with RAG
 */
export async function initAgentsCouncil(): Promise<AgentsCouncilClient> {
  const client = new AgentsCouncilClient();
  
  // Auto-start if configured
  if (client['config'].autoStart) {
    await client.start();
  }

  // Summon auto-summon agents
  for (const [agent, config] of Object.entries(client['config'].agents)) {
    if (config.autoSummon) {
      await client.summon(agent);
    }
  }

  return client;
}

/**
 * CLI command for council
 */
export async function councilCommand(args: string[]): Promise<void> {
  console.log("🏛️  Agents Council for QwenClaw\n");

  if (args.length === 0) {
    console.log("Usage: qwenclaw council <command> [options]");
    console.log("");
    console.log("Commands:");
    console.log("  start           - Start council MCP server");
    console.log("  status          - Check council status");
    console.log("  summon <agent>  - Summon agent (claude/codex/qwen)");
    console.log("  discuss         - Start multi-agent discussion");
    console.log("  monitor         - Open Council Hall desktop");
    console.log("  config          - Edit configuration");
    console.log("");
    console.log("Examples:");
    console.log("  qwenclaw council start");
    console.log("  qwenclaw council summon claude");
    console.log("  qwenclaw council discuss --topic 'Code Review'");
    return;
  }

  const command = args[0];
  const client = new AgentsCouncilClient();

  switch (command) {
    case "start":
      await client.start();
      break;

    case "status":
      const status = await client.getStatus();
      console.log("Council Status:");
      console.log(`  Running: ${status.running ? '✅' : '❌'}`);
      console.log(`  Agents: ${status.agents.join(", ") || 'none'}`);
      console.log(`  Discussions: ${status.discussions || 0}`);
      break;

    case "summon":
      if (!args[1]) {
        console.log("[ERROR] Agent name required");
        return;
      }
      await client.summon(args[1]);
      break;

    case "monitor":
      await client.monitor();
      break;

    default:
      console.log(`[ERROR] Unknown command: ${command}`);
  }
}
