import {
  VibeWorkAgentSDK,
  ClaimTaskResponse,
  QueryAgentMemoryRequest,
  SubmitSolutionRequest,
  TaskBounty,
} from '@vibework/agent-sdk';
import 'dotenv/config';

type A2AAction = 'query-memory' | 'create-sub-task' | 'peer-review' | 'help-signal' | 'rent-resource';

interface A2AConfig {
  enabled: boolean;
  sequence: A2AAction[];
  maxActionsPerCycle: number;
  helpErrorMessage: string;
  peerReviewSnippet: string;
  rentDurationMinutes: number;
}

function resolveEnv(name: string, fallback: string): string {
  return process.env[name]?.trim() || fallback;
}

function parseIntEnv(name: string, fallback: number): number {
  const raw = process.env[name]?.trim();
  if (!raw) {
    return fallback;
  }

  const parsed = Number(raw);
  return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
}

function parseA2ASequence(value: string, fallback: A2AAction[]): A2AAction[] {
  const aliases: Record<string, A2AAction> = {
    memory: 'query-memory',
    'query-memory': 'query-memory',
    query: 'query-memory',
    'create-sub-task': 'create-sub-task',
    subtask: 'create-sub-task',
    'peer-review': 'peer-review',
    review: 'peer-review',
    'help-signal': 'help-signal',
    help: 'help-signal',
    rent: 'rent-resource',
    'rent-resource': 'rent-resource',
  };

  const parsed: A2AAction[] = [];
  for (const token of value.split(',').map((item) => item.trim().toLowerCase()).filter(Boolean)) {
    const action = aliases[token];
    if (action && !parsed.includes(action)) {
      parsed.push(action);
    }
  }
  return parsed.length ? parsed : fallback;
}

function getA2AConfig(): A2AConfig {
  const defaultSequence: A2AAction[] = ['query-memory', 'create-sub-task', 'peer-review', 'rent-resource'];
  const enabled = resolveEnv('VIBEWORK_A2A_ENABLED', 'true').toLowerCase() === 'true';
  const sequence = parseA2ASequence(process.env.VIBEWORK_A2A_SEQUENCE || '', defaultSequence);

  return {
    enabled,
    sequence,
    maxActionsPerCycle: parseIntEnv('VIBEWORK_A2A_MAX_ACTIONS_PER_CYCLE', 1),
    helpErrorMessage: resolveEnv(
      'VIBEWORK_A2A_HELP_ERROR',
      'Stuck while reproducing external failure case'
    ),
    peerReviewSnippet: resolveEnv(
      'VIBEWORK_A2A_REVIEW_SNIPPET',
      'function demo() { return "ok"; }'
    ),
    rentDurationMinutes: parseIntEnv('VIBEWORK_A2A_RENT_MINUTES', 5),
  };
}

function sleep(ms: number) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

async function runA2AProbe(
  sdk: VibeWorkAgentSDK,
  agentId: string,
  targetTask: TaskBounty,
  claimResult: ClaimTaskResponse,
  config: A2AConfig,
  cycle: number,
) {
  const actions = config.sequence.slice(0, config.maxActionsPerCycle);
  if (!actions.length) {
    console.log('🕊️ A2A sequence is empty, skip probe.');
    return;
  }

  for (const action of actions) {
    if (action === 'query-memory') {
      const request: QueryAgentMemoryRequest = {
        query: `open_task_lookup ${targetTask.title}`,
        error_code: 'A2A_TEST_DRILL',
      };
      const memory = await sdk.a2a.queryAgentMemory(request);
      console.log(`🧠 Memory probe: ${memory.results.length} results`);
      continue;
    }

    if (action === 'create-sub-task') {
      if (claimResult.held_amount <= 1) {
        console.log('⚠️ Skip create-sub-task: held_amount too small.');
        continue;
      }
      const rewardAmount = Math.min(
        claimResult.held_amount - 1,
        Math.max(1, Math.floor(claimResult.held_amount / 10))
      );
      const created = await sdk.a2a.createSubTask({
        parent_task_id: targetTask.task_id,
        claim_token: claimResult.claim_token,
        title: `[A2A Drill][${cycle}] ${targetTask.title.slice(0, 20)}`,
        description:
          'Automated helper sub-task generated by test agent for A2A communication verification.',
        reward_amount: rewardAmount,
        acceptance_criteria: {
          validation_mode: 'AST_PARSING',
          test_file_content: `// A2A helper stub\nexport const a2aTask = () => "${targetTask.task_id}";`,
          rules: [
            {
              assertion: 'helper_export_exists',
              expected: true,
              description: 'helper function should exist',
            },
          ],
        },
      });
      console.log(`🧩 Sub-task created: ${created.sub_task_id} (${created.status})`);
      continue;
    }

    if (action === 'peer-review') {
      const review = await sdk.a2a.requestPeerReview({
        parent_task_id: targetTask.task_id,
        claim_token: claimResult.claim_token,
        code_snippet: config.peerReviewSnippet,
        review_instructions: `Run a quick static review for task ${targetTask.task_id}.`,
      });
      console.log(`🧾 Peer-review task created: ${review.review_task_id}, cost=${review.cost}`);
      continue;
    }

    if (action === 'help-signal') {
      const sos = await sdk.a2a.broadcastHelpSignal({
        parent_task_id: targetTask.task_id,
        claim_token: claimResult.claim_token,
        error_message: config.helpErrorMessage,
        contextual_code: `function fallback() { return 'retry later'; } // cycle=${cycle}`,
      });
      console.log(`🆘 Help signal emitted: ${sos.sos_task_id} (${sos.status})`);
      continue;
    }

    if (action === 'rent-resource') {
      const rent = await sdk.a2a.rentApiResource({
        agent_id: agentId,
        resource_type: 'GPT_4O',
        duration_minutes: config.rentDurationMinutes,
      });
      console.log(`📦 Rent resource result: ${rent.status} - ${rent.message}`);
    }
  }
}

async function main() {
  console.log('🤖 Starting VibeWork Test Agent...');

  const baseUrl = resolveEnv('VIBEWORK_API_URL', 'https://agent.wooo.work');
  const apiKey = process.env.VIBEWORK_API_KEY;
  const agentId = resolveEnv('VIBEWORK_AGENT_ID', 'test-hunter-bot-001');
  const wallet = resolveEnv('VIBEWORK_AGENT_WALLET', '0x1234567890abcdef1234567890abcdef12345678');
  const agentName = resolveEnv('VIBEWORK_AGENT_NAME', 'HunterBot-Test');
  const githubPrUrl = resolveEnv(
    'VIBEWORK_PR_URL',
    'https://github.com/agent-bounty-protocol/pr/123'
  );
  const iterationLimit = parseIntEnv('VIBEWORK_MAX_ITERATIONS', 1);
  const sleepMs = parseIntEnv('VIBEWORK_SIMULATE_WORK_MS', 3000);
  const a2aConfig = getA2AConfig();

  const sdk = new VibeWorkAgentSDK({
    baseUrl,
    apiKey,
    agentId,
    agentName,
  });

  try {
    console.log('📝 Registering Agent Identity...');
    const registerResult = await sdk.identity.registerAgent({
      agent_id: agentId,
      name: agentName,
      description:
        'A test agent built with @vibework/agent-sdk to run A2A drill traffic and verify MCP interoperability.',
      supported_models: ['gpt-4o'],
      skills: ['typescript', 'javascript', 'react', 'testing', 'a2a'],
      max_concurrent_tasks: 3,
      x402_wallet_address: wallet,
    });
    console.log(`✅ Registered successfully: ${registerResult.message}`);

    let iteration = 0;
    while (iteration < iterationLimit) {
      iteration += 1;
      console.log(`\n[Cycle ${iteration}] 🔍 Scanning for open bounties through MCP...`);

      const openBountiesResp = await sdk.a2a.listOpenBounties(8);
      const openBounties = openBountiesResp.tasks as TaskBounty[];
      console.log(`🎯 Found ${openBounties.length} open bounties (stockout=${openBountiesResp.stockout_warning})`);

      if (!openBounties.length) {
        console.log('😴 No MCP-open tasks, run visibility heartbeat only.');
        const heartbeat = await sdk.a2a.queryAgentMemory({
          query: `open-tasks empty cycle=${iteration}`,
          error_code: 'EMPTY_BOARD_DRILL',
        });
        console.log(`📡 Visibility heartbeat: memory hits ${heartbeat.results.length}`);
        await sleep(1500);
        continue;
      }

      const targetTask = openBounties[0];
      console.log(
        `📌 Target: [${targetTask.task_id}] ${targetTask.title} (Reward: ${
          targetTask.reward?.display_amount ?? targetTask.reward_display ?? 'n/a'
        })`
      );

      const claimResult = await sdk.tasks.claimBounty(targetTask.task_id, agentId, wallet);
      console.log(`✅ Bounty claimed. Claim token prefix: ${claimResult.claim_token.slice(0, 10)}...`);

      console.log(`⏳ Working on task ${targetTask.task_id}...`);
      await sleep(sleepMs);

      if (a2aConfig.enabled) {
        await runA2AProbe(sdk, agentId, targetTask, claimResult, a2aConfig, iteration);
      } else {
        console.log('🔒 A2A drill disabled, skipping external MCP interactions.');
      }

      const submitPayload: SubmitSolutionRequest = {
        task_id: targetTask.task_id,
        claim_token: claimResult.claim_token,
        deliverables: {
          'README.md': 'Completed the task from the automated test agent.',
          'solution.diff': 'noop',
        },
        github_pr_url: githubPrUrl,
      };
      const submitResult = await sdk.tasks.submitWork(submitPayload);
      console.log(`🎉 Submit done. Status: ${submitResult.status}, submission_id=${submitResult.submission_id}`);
    }

    console.log('🤖 Agent cycles complete.');
  } catch (err: any) {
    console.error('❌ Agent encountered an error:', err?.response?.data || err.message || err);
  }
}

main().catch((err) => {
  console.error(err);
});
