import { v4 as uuidv4 } from "uuid";
import OpenAI from "openai";
import dotenv from "dotenv";

dotenv.config();

const API_BASE = (process.env.VIBEWORK_API_BASE || process.env.VIBEWORK_API_URL || "http://192.168.0.188:3004/api").replace(/\/$/, "");
const MCP_API_BASE = (process.env.VIBEWORK_MCP_BASE || process.env.VIBEWORK_MCP_URL || "http://192.168.0.188:3004/api/mcp").replace(/\/$/, "");
const MCP_API_KEY = process.env.MCP_API_KEY?.trim();

// By default use OpenRouter as it aggregates all the best open-source models
const LLM_API_KEY = process.env.OPENROUTER_API_KEY || process.env.OPENAI_API_KEY;
const LLM_BASE_URL = process.env.OPENROUTER_API_KEY ? "https://openrouter.ai/api/v1" : "https://api.openai.com/v1";

if (!LLM_API_KEY) {
  console.error("❌ Please provide an OPENROUTER_API_KEY (or OPENAI_API_KEY) in your .env file.");
  process.exit(1);
}

if (!MCP_API_KEY) {
  console.error("[outbound-dispatcher] MCP_API_KEY is required.");
  process.exit(1);
}

const openai = new OpenAI({
  baseURL: LLM_BASE_URL,
  apiKey: LLM_API_KEY,
  defaultHeaders: process.env.OPENROUTER_API_KEY ? {
    "HTTP-Referer": "https://agent.wooo.work",
    "X-Title": "VibeWork Outbound Dispatcher",
  } : undefined
});

// The list of "Mercenary" agents we can hire from the open-source market
const TARGET_AGENTS = [
  "nvidia/nemotron-4-340b-instruct",
  "nousresearch/nous-hermes-2-mixtral-8x7b-dpo",
  "openchat/openchat-7b:free",
  "meta-llama/llama-3-70b-instruct"
];

async function callMcpTool(tool: string, payload: unknown) {
  const res = await fetch(`${MCP_API_BASE}/${tool}`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${MCP_API_KEY}`
    },
    body: JSON.stringify(payload)
  });
  const data = await res.json();
  if (!res.ok) {
    console.error(`Tool ${tool} failed with status ${res.status}:`, JSON.stringify(data, null, 2));
    throw new Error(`Tool ${tool} failed.`);
  }
  return data;
}

async function main() {
  console.log("🚀 [VibeWork Headhunter] Starting outbound dispatch sweep...");

  // 1. Find Open Bounties
  console.log("🔍 Scanning for OPEN tasks on VibeWork...");
  const openTasksRes = await fetch(`${API_BASE}/open-tasks`);
  const openTasks = await openTasksRes.json();

  if (!openTasks || !openTasks.tasks || openTasks.tasks.length === 0) {
    console.log("✅ No open tasks available for dispatch. Resting.");
    return;
  }

  const task = openTasks.tasks[0];
  console.log(`🎯 Found Task: "${task.title}" (Reward: ${task.reward_display})`);

  // 2. Assign to an external agent
  const selectedModel = TARGET_AGENTS[Math.floor(Math.random() * TARGET_AGENTS.length)];
  const agentId = `outbound-${selectedModel.split("/").pop()}-${Math.floor(Math.random() * 1000)}`;
  console.log(`🤖 Dispatching to external agent: ${selectedModel} (Agent ID: ${agentId})`);

  // 3. Claim the task on VibeWork
  console.log("\n💰 Claiming Task on behalf of the agent...");
  const claimRes = await callMcpTool("claim_task", {
    task_id: task.task_id,
    agent_id: agentId,
    // We provide a mock Stripe Connect Account or real one if configured
    developer_wallet: "acct_1MockStripeOutboundAgent"
  });
  console.log("✅ Claimed successfully. Token:", claimRes.claim_token);

  // 4. Prompt the Model to solve it
  console.log(`\n🧠 Consulting ${selectedModel} for the solution...`);
  const systemPrompt = `You are an elite autonomous AI developer. 
You have just accepted a bounty on VibeWork.
You must solve the task by writing the necessary code.
Return ONLY valid JSON in the following format, with no markdown formatting outside the JSON block:
{
  "deliverables": {
    "filename1.ts": "code content here",
    "filename2.md": "documentation here"
  }
}
Do not return any explanations, just the JSON string.`;

  const userPrompt = `TASK TITLE: ${task.title}
TASK DESCRIPTION: ${task.description_preview}

Please provide the solution.`;

  try {
    const completion = await openai.chat.completions.create({
      model: selectedModel,
      messages: [
        { role: "system", content: systemPrompt },
        { role: "user", content: userPrompt }
      ],
      temperature: 0.2,
      response_format: { type: "json_object" }
    });

    const outputContent = completion.choices[0].message.content || "{}";
    let solutionObj;
    try {
      solutionObj = JSON.parse(outputContent);
    } catch (e) {
      console.warn("⚠️ Failed to parse LLM JSON output. Falling back to raw text mapping.", outputContent);
      solutionObj = {
        deliverables: {
          "solution.txt": outputContent
        }
      };
    }

    if (!solutionObj.deliverables) {
        solutionObj.deliverables = { "solution.txt": outputContent };
    }

    console.log("✅ Model generated the solution deliverables:", Object.keys(solutionObj.deliverables));

    // 5. Auto-Submit the Solution
    console.log("\n🚀 Submitting the solution back to VibeWork...");
    const fakePrUrl = `https://github.com/agent-bounty/external-agents/pull/${Math.floor(Math.random() * 10000)}`;
    const solutionRes = await callMcpTool("submit_solution", {
      task_id: task.task_id,
      claim_token: claimRes.claim_token,
      deliverables: solutionObj.deliverables,
      github_pr_url: fakePrUrl
    });

    console.log(`🎉 Success! Solution submitted. Submission ID: ${solutionRes.submission_id}`);

  } catch (err) {
    console.error("❌ LLM API Error during dispatch:", err);
  }
}

main().catch(console.error);
