import WebSocket from 'ws';
import { appendFileSync } from 'fs';

const CDP_PORT = 18800;
const COOKIE_VALUE = 'dc4d1551406351a93c09082ea08e2d2e';
const TARGET_URL = 'https://www.nodeseek.com';
const LOG_FILE = '/Users/jianzhang/.openclaw/workspace/scripts/checkin.log';

let msgId = 1;
let pendingCallbacks = new Map();
let loadEventResolve = null;

function log(message) {
  const timestamp = new Date().toISOString();
  const logLine = `[${timestamp}] ${message}\n`;
  console.log(logLine.trim());
  try {
    appendFileSync(LOG_FILE, logLine);
  } catch (e) {
    console.error('Failed to write log:', e.message);
  }
}

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

async function send(ws, method, params = {}) {
  return new Promise((resolve, reject) => {
    const id = msgId++;
    const msg = JSON.stringify({ id, method, params });
    pendingCallbacks.set(id, { resolve, reject });
    ws.send(msg);
    
    setTimeout(() => {
      if (pendingCallbacks.has(id)) {
        pendingCallbacks.delete(id);
        reject(new Error(`Timeout for ${method}`));
      }
    }, 30000);
  });
}

async function main() {
  log('开始 NodeSeek 朦胧签到任务');
  
  let ws;
  let targetId = null;
  
  try {
    // Step 1: Get browser WebSocket URL
    log('获取 CDP 连接信息...');
    const resp = await fetch(`http://127.0.0.1:${CDP_PORT}/json/version`);
    const version = await resp.json();
    const browserWsUrl = version.webSocketDebuggerUrl;
    log(`Browser WS: ${browserWsUrl}`);
    
    // Step 2: Connect to browser
    ws = new WebSocket(browserWsUrl);
    
    ws.on('message', (data) => {
      try {
        const msg = JSON.parse(data.toString());
        
        // Handle command responses
        if (msg.id && pendingCallbacks.has(msg.id)) {
          const { resolve, reject } = pendingCallbacks.get(msg.id);
          pendingCallbacks.delete(msg.id);
          if (msg.error) {
            reject(new Error(msg.error.message || JSON.stringify(msg.error)));
          } else {
            resolve(msg.result);
          }
        }
        
        // Handle load event
        if (msg.method === 'Page.loadEventFired' && loadEventResolve) {
          loadEventResolve();
          loadEventResolve = null;
        }
      } catch (e) {
        // Ignore
      }
    });
    
    await new Promise((resolve, reject) => {
      ws.on('open', resolve);
      ws.on('error', reject);
    });
    log('CDP 连接成功');
    
    // Step 3: Create new target
    log('创建新标签页...');
    const targetResult = await send(ws, 'Target.createTarget', {
      url: 'about:blank'
    });
    targetId = targetResult.targetId;
    log(`Target ID: ${targetId}`);
    
    // Step 4: Get target's WebSocket URL via HTTP
    const targetsResp = await fetch(`http://127.0.0.1:${CDP_PORT}/json`);
    const targets = await targetsResp.json();
    const pageTarget = targets.find(t => t.id === targetId);
    
    if (!pageTarget) {
      throw new Error('找不到创建的标签页');
    }
    
    const pageWsUrl = pageTarget.webSocketDebuggerUrl;
    log(`Page WS: ${pageWsUrl}`);
    
    // Step 5: Close browser connection and connect to page
    ws.close();
    await sleep(500);
    
    ws = new WebSocket(pageWsUrl);
    ws.on('message', (data) => {
      try {
        const msg = JSON.parse(data.toString());
        
        if (msg.id && pendingCallbacks.has(msg.id)) {
          const { resolve, reject } = pendingCallbacks.get(msg.id);
          pendingCallbacks.delete(msg.id);
          if (msg.error) {
            reject(new Error(msg.error.message || JSON.stringify(msg.error)));
          } else {
            resolve(msg.result);
          }
        }
        
        if (msg.method === 'Page.loadEventFired' && loadEventResolve) {
          loadEventResolve();
          loadEventResolve = null;
        }
      } catch (e) {
        // Ignore
      }
    });
    
    await new Promise((resolve, reject) => {
      ws.on('open', resolve);
      ws.on('error', reject);
    });
    log('已连接到页面');
    
    // Step 6: Enable domains
    await send(ws, 'Page.enable');
    await send(ws, 'Network.enable');
    
    // Step 7: Set cookie
    log('设置 Cookie...');
    await send(ws, 'Network.setCookie', {
      name: '_nk',
      value: COOKIE_VALUE,
      domain: '.nodeseek.com',
      path: '/'
    });
    log('Cookie 设置成功');
    
    // Step 8: Navigate
    log('导航到 NodeSeek...');
    const loadPromise = new Promise(resolve => { loadEventResolve = resolve; });
    await send(ws, 'Page.navigate', { url: TARGET_URL });
    
    log('等待页面加载...');
    await loadPromise;
    log('页面加载完成');
    
    // Step 9: Wait 8 seconds
    log('等待 8 秒...');
    await sleep(8000);
    
    // Step 10: Call attendance API
    log('调用签到 API...');
    const evalResult = await send(ws, 'Runtime.evaluate', {
      expression: `fetch('/api/attendance',{
        method:'POST',
        headers:{'Content-Type':'application/json'},
        body:JSON.stringify({random:true})
      }).then(r => r.json()).catch(e => ({error: e.message}))`,
      returnByValue: true,
      awaitPromise: true
    });
    
    const result = evalResult.result.value;
    log(`签到结果: ${JSON.stringify(result)}`);
    
    // Step 11: Close page
    log('关闭标签页...');
    await send(ws, 'Page.close');
    
    ws.close();
    log('签到任务完成 ✓');
    
  } catch (error) {
    log(`错误: ${error.message}`);
    if (ws && ws.readyState === WebSocket.OPEN) {
      try {
        ws.close();
      } catch (e) {}
    }
    process.exit(1);
  }
}

main();
