/**
 * dispatch-webhook skill
 * 發送 Webhook 到 VPS，處理重試與錯誤
 */

interface DispatchInput {
  target: 'vps-a' | 'vps-b';
  payload: Record<string, unknown>;
  webhookUrl: string;
  webhookToken: string;
  timeoutMs?: number;
  retries?: number;
}

async function fetchWithTimeout(url: string, options: RequestInit, timeoutMs: number): Promise<Response> {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), timeoutMs);
  try {
    return await fetch(url, { ...options, signal: controller.signal });
  } finally {
    clearTimeout(timer);
  }
}

export async function handler(ctx: any) {
  const input: DispatchInput = ctx.input || ctx.params;

  if (!input.webhookUrl) {
    throw new Error(`${input.target.toUpperCase()} Webhook URL 未設定。請在環境變數設定 VPS_A_WEBHOOK_URL 或 VPS_B_WEBHOOK_URL`);
  }
  if (!input.webhookToken) {
    throw new Error(`${input.target.toUpperCase()} Webhook Token 未設定`);
  }

  const timeoutMs = input.timeoutMs ?? 30000;
  const maxRetries = input.retries ?? 3;
  let lastError: Error | null = null;

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetchWithTimeout(
        input.webhookUrl,
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${input.webhookToken}`,
            'X-OpenClaw-Version': '1.0',
            'X-OpenClaw-Task-Id': String(input.payload.task_id || ''),
          },
          body: JSON.stringify(input.payload),
        },
        timeoutMs
      );

      if (response.status === 401) {
        throw new Error('Webhook Token 驗證失敗（401），請確認 VPS_WEBHOOK_TOKEN 設定正確');
      }

      if (!response.ok && response.status !== 202) {
        const body = await response.text().catch(() => '');
        throw new Error(`VPS 回應錯誤 ${response.status}：${body.slice(0, 200)}`);
      }

      const result = await response.json().catch(() => ({ status: 'accepted' }));
      return {
        success: true,
        status: result.status || 'accepted',
        task_id: input.payload.task_id,
        target: input.target,
        attempt,
      };

    } catch (err: any) {
      lastError = err;
      if (err.message?.includes('401') || err.message?.includes('Token')) {
        break; // 認證錯誤不重試
      }
      if (attempt < maxRetries) {
        await new Promise(r => setTimeout(r, 5000 * attempt)); // 指數退避
      }
    }
  }

  throw lastError || new Error('Webhook 發送失敗');
}
