const fs = require('fs');
const content = fs.readFileSync('temp/rich-outline-fail_57_1779015509994.txt', 'utf-8');
const marker = '========== AI 原始响应 ';
const markerIdx = content.indexOf(marker);
const headerEndIdx = content.indexOf(' ==========', markerIdx);
const aiStart = content.indexOf('\n', headerEndIdx) + 1;
const aiEnd = content.indexOf('\n\n', aiStart);
const aiResponse = content.substring(aiStart, aiEnd);

console.log('AI response length:', aiResponse.length);

// Extract the substring around the error and try to parse it
const pos = 1624;
const start = Math.max(0, pos - 500);
const end = Math.min(aiResponse.length, pos + 200);
const snippet = aiResponse.substring(start, end);

console.log('\n=== Snippet around error (500 before, 200 after pos 1624) ===');
console.log('Start offset:', start, 'End offset:', end);
console.log('JSON snippet:', JSON.stringify('...' + snippet + '...'));

// Now let's try to create a mini JSON with just the part around the error
// and see if we can identify the issue
const beforeSnippet = aiResponse.substring(0, pos);
const afterSnippet = aiResponse.substring(pos);

// Try parsing a truncated version that ends at the error position
console.log('\n=== Try parsing up to error position ===');
try {
  JSON.parse(beforeSnippet);
  console.log('Parsed OK (unexpected)');
} catch(e) {
  console.log('Parse error at:', e.message);
}

// Try parsing from error position onwards
console.log('\n=== Try parsing from error position ===');
try {
  const data = JSON.parse('{' + afterSnippet);
  console.log('Parsed OK, chapters:', data.chapters?.length);
} catch(e) {
  console.log('Parse error at:', e.message.substring(0, 80));
}

// Let me check if maybe there's a weird character right before position 1624
// that I'm missing
console.log('\n=== Detailed byte analysis ===');
for (let i = 1618; i < 1635; i++) {
  const code = aiResponse.charCodeAt(i);
  console.log('  pos', i, ':', 'U+' + code.toString(16).toUpperCase().padStart(4, '0'), JSON.stringify(aiResponse[i]));
}

// Let's also check if maybe there's a BOM or something
console.log('\nFirst char:', aiResponse.charCodeAt(0), JSON.stringify(aiResponse[0]));
console.log('First 3 chars:', aiResponse.substring(0, 3).split('').map(c => c.charCodeAt(0)));

// Try using TextEncoder to get actual bytes
const encoder = new TextEncoder();
const bytes = encoder.encode(aiResponse);
console.log('\n=== UTF-8 bytes around position 1624 (converted to code units) ===');
// Since the string is 18719 chars but UTF-8 bytes is 38333,
// that means most chars are 3-byte Chinese chars
// Let's find the byte offset for UTF-16 position 1624
let utf8Offset = 0;
for (let utf16Idx = 0; utf16Idx < 1624; utf16Idx++) {
  const code = aiResponse.charCodeAt(utf16Idx);
  if (code <= 0x7F) utf8Offset += 1;
  else if (code <= 0x7FF) utf8Offset += 2;
  else if (code <= 0xFFFF) utf8Offset += 3;
  else utf8Offset += 4;
}
console.log('UTF-8 offset for UTF-16 pos 1624:', utf8Offset);
console.log('UTF-8 bytes around that position:');
for (let i = utf8Offset - 5; i < utf8Offset + 10; i++) {
  if (i >= 0 && i < bytes.length) {
    console.log('  byte', i, ':', bytes[i], String.fromCharCode(bytes[i]));
  }
}

// Now check if those UTF-8 bytes form valid UTF-8 characters
console.log('\n=== Checking UTF-8 validity around position ===');
// 3-byte UTF-8 for CJK: 1110xxxx 10xxxxxx 10xxxxxx
// Let's see what the bytes around utf8Offset actually represent
for (let i = utf8Offset - 3; i < utf8Offset + 6; i++) {
  if (i >= 0 && i < bytes.length) {
    const b = bytes[i];
    console.log('  byte', i, ':', b, 'binary:', b.toString(2).padStart(8, '0'));
  }
}