#!/usr/bin/env node
/**
 * Probe MinerU Cloud API for real supported file formats.
 *
 * Usage:
 *   MINERU_CLOUD_API_KEY=sk-... node scripts/probe-mineru-cloud.mjs
 *
 * For each sample in tmp/samples/, submits it to /file-urls/batch and polls
 * /extract-results/batch/{id} until a terminal state, then prints the outcome.
 * We don't download the ZIP — success at the extraction stage is enough signal
 * for "MinerU Cloud accepts this format."
 */

import { readFileSync, readdirSync, statSync } from 'node:fs';
import { join } from 'node:path';

const API_ROOT = (process.env.MINERU_CLOUD_BASE_URL || 'https://mineru.net/api/v4').replace(
  /\/+$/,
  '',
);
const API_KEY = process.env.MINERU_CLOUD_API_KEY;
if (!API_KEY) {
  console.error('Set MINERU_CLOUD_API_KEY env var.');
  process.exit(1);
}

const SAMPLES_DIR = new URL('../tmp/samples/', import.meta.url).pathname;
const POLL_INTERVAL_MS = 3000;
const POLL_MAX_MS = 5 * 60 * 1000;

async function readJson(res, ctx) {
  const text = await res.text();
  let json;
  try {
    json = JSON.parse(text);
  } catch {
    throw new Error(`${ctx}: invalid JSON HTTP ${res.status}: ${text.slice(0, 300)}`);
  }
  if (!res.ok) throw new Error(`${ctx}: HTTP ${res.status}: ${text.slice(0, 300)}`);
  if (json.code !== 0) throw new Error(`${ctx}: code ${json.code} — ${json.msg || 'unknown'}`);
  return json.data;
}

async function probe(fileName) {
  const buffer = readFileSync(join(SAMPLES_DIR, fileName));
  process.stdout.write(`\n[${fileName}] (${buffer.byteLength} bytes)\n`);

  // Step 1: request presigned URL
  let batch;
  try {
    const res = await fetch(`${API_ROOT}/file-urls/batch`, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        files: [{ name: fileName }],
        enable_formula: true,
        enable_table: true,
        language: 'ch',
      }),
    });
    batch = await readJson(res, 'file-urls/batch');
  } catch (e) {
    console.log(`  ❌ batch request rejected: ${e.message}`);
    return { fileName, result: 'batch-rejected', error: e.message };
  }

  const uploadUrls = batch.file_urls ?? batch.files;
  if (!batch.batch_id || !uploadUrls?.length) {
    console.log(`  ❌ malformed batch response`);
    return { fileName, result: 'batch-malformed' };
  }

  // Step 2: upload
  const putRes = await fetch(uploadUrls[0], {
    method: 'PUT',
    body: buffer,
  });
  if (!putRes.ok) {
    const text = await putRes.text().catch(() => putRes.statusText);
    console.log(`  ❌ upload failed HTTP ${putRes.status}: ${text.slice(0, 200)}`);
    return { fileName, result: 'upload-failed', status: putRes.status };
  }

  // Step 3: poll
  const deadline = Date.now() + POLL_MAX_MS;
  let lastState = '';
  while (Date.now() < deadline) {
    await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
    let statusData;
    try {
      const res = await fetch(`${API_ROOT}/extract-results/batch/${batch.batch_id}`, {
        headers: { Authorization: `Bearer ${API_KEY}`, Accept: 'application/json' },
      });
      statusData = await readJson(res, 'poll');
    } catch (e) {
      console.log(`  ⚠️  poll error: ${e.message}`);
      continue;
    }
    const rows = statusData.extract_result;
    const list = Array.isArray(rows) ? rows : rows ? [rows] : [];
    const row = list[0];
    if (!row) continue;
    const state = row.state || '';
    if (state !== lastState) {
      process.stdout.write(`  → state=${state}\n`);
      lastState = state;
    }
    if (state === 'done') {
      console.log(`  ✅ MinerU accepted ${fileName}`);
      return { fileName, result: 'accepted', errMsg: row.err_msg };
    }
    if (state === 'failed' || row.err_msg) {
      console.log(`  ❌ MinerU rejected ${fileName}: ${row.err_msg || 'failed'}`);
      return { fileName, result: 'rejected', error: row.err_msg };
    }
  }
  console.log(`  ⏱️  timed out`);
  return { fileName, result: 'timeout' };
}

const files = readdirSync(SAMPLES_DIR).filter((f) => {
  const p = join(SAMPLES_DIR, f);
  return statSync(p).isFile() && !f.startsWith('.');
});

const results = [];
for (const f of files.sort()) {
  results.push(await probe(f));
}

console.log('\n\n═══ SUMMARY ═══');
for (const r of results) {
  const icon = r.result === 'accepted' ? '✅' : '❌';
  console.log(`${icon} ${r.fileName}: ${r.result}${r.error ? ` — ${r.error}` : ''}`);
}