/**
 * ═══════════════════════════════════════════
 * 光湖智库 · 前端主脚本 v2.0
 * guanghu.online · ZY-PROJ-006
 * 守护: 铸渊 · ICE-GL-ZY001
 * 版权: 国作登字-2026-A-00037559
 *
 * v2.0: 邮箱登录 + 真实搜索下载 + Agent对话 + 登录态管理
 * ═══════════════════════════════════════════
 */

'use strict';

const API_BASE = '/api';
const REQUEST_TIMEOUT_MS = 15000;
let currentToken = localStorage.getItem('zhiku_token') || null;
let currentEmail = localStorage.getItem('zhiku_email') || null;
let codeCooldown = 0;
let codeCooldownTimer = null;

/* ═══ 星空背景 ═══ */
(function initStars() {
  const canvas = document.getElementById('starCanvas');
  if (!canvas) return;
  const ctx = canvas.getContext('2d');
  let stars = [];
  const STAR_COUNT = 200;

  function resize() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    stars = Array.from({ length: STAR_COUNT }, () => ({
      x: Math.random() * canvas.width,
      y: Math.random() * canvas.height,
      r: Math.random() * 1.2 + 0.3,
      a: Math.random(),
      da: (Math.random() - 0.5) * 0.008
    }));
  }

  function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    for (const s of stars) {
      s.a += s.da;
      if (s.a > 1 || s.a < 0.1) s.da = -s.da;
      ctx.beginPath();
      ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2);
      ctx.fillStyle = `rgba(200,210,255,${s.a * 0.5})`;
      ctx.fill();
    }
    requestAnimationFrame(draw);
  }

  resize();
  window.addEventListener('resize', resize);
  draw();
})();

/* ═══ Header 滚动阴影 ═══ */
document.querySelector('.content')?.addEventListener('scroll', function() {
  const header = document.getElementById('header');
  if (header) header.classList.toggle('scrolled', this.scrollTop > 10);
});

/* ═══ 工具函数 ═══ */
function escapeHtml(str) {
  const div = document.createElement('div');
  div.textContent = str || '';
  return div.innerHTML;
}

function showLoginMsg(text, type) {
  const el = document.getElementById('loginMsg');
  if (!el) return;
  el.textContent = text;
  el.className = 'login-msg ' + (type || '');
}

/* ═══════════════════════════════════════════
 * 邮箱登录系统 · Email Auth
 * ═══════════════════════════════════════════ */

/** 发送验证码 */
async function loginSendCode() {
  const emailInput = document.getElementById('loginEmail');
  const email = (emailInput?.value || '').trim();

  if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
    showLoginMsg('请输入有效的邮箱地址', 'err');
    return;
  }

  const sendBtn = document.getElementById('loginSendBtn');
  const sendBtn2 = document.getElementById('loginSendBtn2');
  if (sendBtn) sendBtn.disabled = true;
  if (sendBtn2) sendBtn2.disabled = true;
  showLoginMsg('正在发送验证码...', 'info');

  try {
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
    const res = await fetch(`${API_BASE}/auth/send-code`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email }),
      signal: controller.signal
    });
    clearTimeout(timeout);

    if (!res.ok && res.status >= 500) {
      showLoginMsg('服务器暂时不可用，请稍后重试', 'err');
      if (sendBtn) sendBtn.disabled = false;
      if (sendBtn2) sendBtn2.disabled = false;
      return;
    }

    let data;
    try {
      data = await res.json();
    } catch (jsonErr) {
      console.error('[zhiku] send-code JSON parse failed:', jsonErr);
      showLoginMsg('服务器响应异常，请稍后重试', 'err');
      if (sendBtn) sendBtn.disabled = false;
      if (sendBtn2) sendBtn2.disabled = false;
      return;
    }

    if (data.error) {
      showLoginMsg(data.message || '发送失败', 'err');
      if (sendBtn) sendBtn.disabled = false;
      if (sendBtn2) sendBtn2.disabled = false;
      return;
    }

    showLoginMsg('验证码已发送，请查收邮件', 'ok');

    // 显示验证码输入区
    const codeRow = document.getElementById('loginCodeRow');
    if (codeRow) codeRow.style.display = 'flex';
    if (sendBtn) sendBtn.style.display = 'none';
    const verifyBtn = document.getElementById('loginVerifyBtn');
    if (verifyBtn) verifyBtn.style.display = 'block';

    // 禁用邮箱输入
    if (emailInput) emailInput.readOnly = true;

    // 60秒冷却倒计时
    codeCooldown = 60;
    if (codeCooldownTimer) clearInterval(codeCooldownTimer);
    codeCooldownTimer = setInterval(() => {
      codeCooldown--;
      if (sendBtn2) {
        if (codeCooldown > 0) {
          sendBtn2.textContent = `${codeCooldown}s`;
          sendBtn2.disabled = true;
        } else {
          sendBtn2.textContent = '重新发送';
          sendBtn2.disabled = false;
          clearInterval(codeCooldownTimer);
          codeCooldownTimer = null;
        }
      }
    }, 1000);

    // 自动聚焦验证码输入
    document.getElementById('loginCode')?.focus();

  } catch (err) {
    console.error('[zhiku] send-code fetch error:', err.name, err.message);
    let msg = '网络连接失败，请检查网络后重试';
    if (err.name === 'AbortError') {
      msg = '请求超时，请检查网络后重试';
    } else if (err.name === 'TypeError') {
      // Safari/iOS 连接失败时抛出 TypeError，错误信息不友好
      msg = '服务器连接失败，请稍后重试';
    } else if (err.message) {
      msg = '连接失败，请稍后重试';
    }
    showLoginMsg(msg, 'err');
    if (sendBtn) sendBtn.disabled = false;
    if (sendBtn2) sendBtn2.disabled = false;
  }
}

/** 验证码校验 → 登录 */
async function loginVerify() {
  const email = (document.getElementById('loginEmail')?.value || '').trim();
  const code = (document.getElementById('loginCode')?.value || '').trim();

  if (!email || !code) {
    showLoginMsg('请输入邮箱和验证码', 'err');
    return;
  }

  if (!/^\d{6}$/.test(code)) {
    showLoginMsg('验证码为6位数字', 'err');
    return;
  }

  const verifyBtn = document.getElementById('loginVerifyBtn');
  if (verifyBtn) verifyBtn.disabled = true;
  showLoginMsg('验证中...', 'info');

  try {
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
    const res = await fetch(`${API_BASE}/auth/verify`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email, code }),
      signal: controller.signal
    });
    clearTimeout(timeout);

    let data;
    try {
      data = await res.json();
    } catch (jsonErr) {
      console.error('[zhiku] verify JSON parse failed:', jsonErr);
      showLoginMsg('服务器响应异常，请稍后重试', 'err');
      if (verifyBtn) verifyBtn.disabled = false;
      return;
    }

    if (data.error) {
      showLoginMsg(data.message || '验证失败', 'err');
      if (verifyBtn) verifyBtn.disabled = false;
      return;
    }

    // 登录成功
    currentToken = data.token;
    currentEmail = data.email || email;
    localStorage.setItem('zhiku_token', currentToken);
    localStorage.setItem('zhiku_email', currentEmail);

    showLoginMsg('登录成功 · 欢迎来到光湖智库', 'ok');

    // 切换到主页面
    setTimeout(() => {
      enterMainPage();
    }, 600);

  } catch (err) {
    console.error('[zhiku] verify fetch error:', err.name, err.message);
    let msg = '网络连接失败，请检查网络后重试';
    if (err.name === 'AbortError') {
      msg = '请求超时，请检查网络后重试';
    } else if (err.name === 'TypeError') {
      msg = '服务器连接失败，请稍后重试';
    } else if (err.message) {
      msg = '连接失败，请稍后重试';
    }
    showLoginMsg(msg, 'err');
    if (verifyBtn) verifyBtn.disabled = false;
  }
}

/** 退出登录 */
async function doLogout() {
  try {
    await fetch(`${API_BASE}/auth/logout`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${currentToken}`
      }
    });
  } catch {}

  currentToken = null;
  currentEmail = null;
  localStorage.removeItem('zhiku_token');
  localStorage.removeItem('zhiku_email');

  // 重置登录表单
  const emailInput = document.getElementById('loginEmail');
  if (emailInput) { emailInput.value = ''; emailInput.readOnly = false; }
  const codeInput = document.getElementById('loginCode');
  if (codeInput) codeInput.value = '';
  const codeRow = document.getElementById('loginCodeRow');
  if (codeRow) codeRow.style.display = 'none';
  const sendBtn = document.getElementById('loginSendBtn');
  if (sendBtn) { sendBtn.style.display = 'block'; sendBtn.disabled = false; }
  const verifyBtn = document.getElementById('loginVerifyBtn');
  if (verifyBtn) { verifyBtn.style.display = 'none'; verifyBtn.disabled = false; }
  showLoginMsg('', '');

  // 显示登录弹窗，隐藏主页面
  document.getElementById('loginOverlay').style.display = 'flex';
  document.getElementById('mainPage').style.display = 'none';
}

/** 进入主页面 */
function enterMainPage() {
  document.getElementById('loginOverlay').style.display = 'none';
  document.getElementById('mainPage').style.display = 'block';

  // 更新用户栏
  const userBarEmail = document.getElementById('userBarEmail');
  if (userBarEmail) userBarEmail.textContent = currentEmail || '—';

  // 加载健康状态
  checkHealth();
}

/** 校验已存储的会话 */
async function checkSession() {
  if (!currentToken) return false;

  try {
    const res = await fetch(`${API_BASE}/auth/session`, {
      headers: { 'Authorization': `Bearer ${currentToken}` }
    });
    const data = await res.json();
    if (!data.error && data.user) {
      currentEmail = data.user.email || currentEmail;
      localStorage.setItem('zhiku_email', currentEmail);
      return true;
    }
  } catch {}

  // Token 失效
  currentToken = null;
  currentEmail = null;
  localStorage.removeItem('zhiku_token');
  localStorage.removeItem('zhiku_email');
  return false;
}

/* ═══ 验证码输入框回车确认 ═══ */
document.getElementById('loginCode')?.addEventListener('keydown', e => {
  if (e.key === 'Enter') loginVerify();
});
document.getElementById('loginEmail')?.addEventListener('keydown', e => {
  if (e.key === 'Enter') loginSendCode();
});

/* ═══════════════════════════════════════════
 * API 健康检查
 * ═══════════════════════════════════════════ */

async function checkHealth() {
  const el = document.getElementById('apiStatus');
  try {
    const res = await fetch(`${API_BASE}/health`);
    const data = await res.json();
    if (data.status === 'ok') {
      // 计算数据源在线状态
      const sources = data.data_sources || [];
      const onlineSources = sources.filter(s => s.reachable);
      const sourceSummary = onlineSources.length + '/' + sources.length;
      el.textContent = `● API 在线 · ${data.uptime_human || ''} · 数据源 ${sourceSummary}`;
      el.className = 'api-status ok';

      // 如果有数据源离线，改为警告色
      if (onlineSources.length < sources.length) {
        el.className = 'api-status warn';
        const offlineSources = sources.filter(s => !s.reachable).map(s => s.name).join(', ');
        el.title = `离线数据源: ${offlineSources}`;
      }

      const statBooks = document.getElementById('statBooks');
      const statUptime = document.getElementById('statUptime');
      const statSources = document.getElementById('statSources');
      const statCos = document.getElementById('statCos');
      if (statBooks) statBooks.textContent = data.books_count || 0;
      if (statUptime) statUptime.textContent = data.uptime_human || '-';
      if (statSources) statSources.textContent = sourceSummary;
      if (statCos) statCos.textContent = data.cos_configured ? '已连接' : '未配置';
    } else {
      throw new Error('not ok');
    }
  } catch {
    if (el) {
      el.textContent = '● API 离线';
      el.className = 'api-status err';
    }
  }
}

setInterval(checkHealth, 30000);

/* ═══════════════════════════════════════════
 * 搜索功能 · 真实数据源搜索
 * ═══════════════════════════════════════════ */

/** 构建数据源状态提示 HTML */
function buildSourceStatusHtml(sourceStatus) {
  if (!sourceStatus || !sourceStatus.length) return '';
  const errorSources = sourceStatus.filter(s => s.status === 'error');
  if (errorSources.length === 0) return '';
  const tips = errorSources.map(s => {
    const name = escapeHtml(s.name);
    const err = s.error || '';
    const errMsg = err.includes('timeout') ? '连接超时' :
                   err.includes('ECONNREFUSED') ? '服务未启动' :
                   err.includes('ENOTFOUND') ? 'DNS解析失败' :
                   err.includes('ECONNRESET') ? '连接被重置' :
                   '不可达';
    return `<span class="source-err-tag">${name}: ${errMsg}</span>`;
  }).join(' ');
  return `<div class="source-status-bar">⚠️ 部分数据源离线: ${tips} · 仅本地书库可用</div>`;
}

async function doSearch() {
  const q = document.getElementById('searchInput').value.trim();
  const resultDiv = document.getElementById('searchResults');

  if (!q) {
    resultDiv.innerHTML = '<div class="no-results">请输入书名或作者名</div>';
    resultDiv.style.display = 'block';
    return;
  }

  if (!currentToken) {
    resultDiv.innerHTML = '<div class="no-results">请先登录后再搜索</div>';
    resultDiv.style.display = 'block';
    return;
  }

  resultDiv.innerHTML = '<div class="no-results search-loading">🔍 正在搜索「' + escapeHtml(q) + '」...</div>';
  resultDiv.style.display = 'block';

  try {
    const res = await fetch(`${API_BASE}/search?q=${encodeURIComponent(q)}`, {
      headers: { 'Authorization': `Bearer ${currentToken}` }
    });

    let data;
    try {
      data = await res.json();
    } catch (jsonErr) {
      resultDiv.innerHTML = '<div class="no-results">⚠️ 服务器响应异常，请稍后重试</div>';
      return;
    }

    if (data.error) {
      if (data.code === 'TOKEN_EXPIRED' || data.code === 'TOKEN_INVALID' || data.code === 'NO_TOKEN') {
        resultDiv.innerHTML = '<div class="no-results">⚠️ 登录已过期，请重新登录</div>';
        setTimeout(() => doLogout(), 2000);
        return;
      }
      resultDiv.innerHTML = '<div class="no-results">⚠️ ' + escapeHtml(data.message) + '</div>';
    } else if (!data.results || data.results.length === 0) {
      // 空结果时展示数据源状态，让用户知道为什么搜不到
      const statusHtml = buildSourceStatusHtml(data.source_status);
      const localInfo = (data.source_status || []).find(s => s.id === 'local');
      const localTotal = localInfo ? localInfo.books_total || 0 : 0;
      resultDiv.innerHTML = statusHtml +
        '<div class="no-results">' +
        (statusHtml ? '数据源离线时只能搜索本地书库（当前收录 ' + localTotal + ' 本）' :
        '未找到匹配书籍 · 可尝试其他关键词') +
        '</div>';
    } else {
      const statusHtml = buildSourceStatusHtml(data.source_status);
      const sourceColors = { local: '#34d399', fanqie: '#fbbf24', qimao: '#a78bfa', shu69: '#fb923c' };
      resultDiv.innerHTML = statusHtml +
        '<div class="search-summary">找到 ' + data.total + ' 个结果 · 来源: ' + (data.sources_queried || []).join(', ') + '</div>' +
        data.results.map(book => {
          const sourceColor = sourceColors[book.source] || '#94a7d0';
          const sourceName = book.source_name || book.source;
          const hasFile = book.has_file;
          const downloadAttr = !hasFile && book.source_book_id
            ? ` data-source="${escapeHtml(book.source)}" data-bookid="${escapeHtml(book.source_book_id)}" data-title="${escapeHtml(book.title)}" data-author="${escapeHtml(book.author || '')}"`
            : '';

          return `<div class="search-result-card">
            <div class="result-info">
              <div class="result-title">📕 ${escapeHtml(book.title)}</div>
              <div class="result-meta">
                ${escapeHtml(book.author || '未知作者')}
                ${book.category ? ' · ' + escapeHtml(book.category) : ''}
                ${book.word_count ? ' · ' + (book.word_count > 10000 ? Math.round(book.word_count / 10000) + '万字' : book.word_count + '字') : ''}
              </div>
              <div class="result-source">
                <span class="source-badge" style="border-color:${sourceColor};color:${sourceColor}">${sourceName}</span>
                ${hasFile ? '<span class="source-badge local-badge">已收录</span>' : ''}
              </div>
            </div>
            <div class="result-actions">
              ${hasFile
                ? `<button class="result-btn result-btn-read" onclick="readBook('${escapeHtml(book.id)}')">📖 阅读</button>
                   <button class="result-btn result-btn-dl" onclick="downloadLocal('${escapeHtml(book.id)}')">⬇️ 下载</button>`
                : (book.source_book_id
                    ? `<button class="result-btn result-btn-read" onclick="readBook('${escapeHtml(book.id)}')">📖 在线阅读</button>
                       <button class="result-btn result-btn-dl" onclick="startDownload('${escapeHtml(book.source)}','${escapeHtml(book.source_book_id)}','${escapeHtml(book.title)}','${escapeHtml(book.author || '')}')" ${downloadAttr}>⬇️ 下载到智库</button>`
                    : '')
              }
            </div>
          </div>`;
        }).join('');
    }
  } catch (err) {
    resultDiv.innerHTML = '<div class="no-results">搜索失败: ' + escapeHtml(err.message) + '</div>';
  }
}

document.getElementById('searchInput')?.addEventListener('keydown', e => {
  if (e.key === 'Enter') doSearch();
});

/* ═══════════════════════════════════════════
 * 下载功能
 * ═══════════════════════════════════════════ */

/** 启动从数据源下载到COS */
async function startDownload(source, sourceBookId, title, author) {
  if (!currentToken) { alert('请先登录'); return; }

  // 确认下载
  const sourceNames = { fanqie: '番茄小说', qimao: '七猫小说', shu69: '69书吧' };
  if (!confirm(`确认下载「${title}」(${sourceNames[source] || source}) 到智库？`)) return;

  try {
    const res = await fetch(`${API_BASE}/download/start`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${currentToken}`
      },
      body: JSON.stringify({ source, source_book_id: sourceBookId, title, author })
    });
    const data = await res.json();

    if (data.error) {
      alert('下载失败: ' + data.message);
      return;
    }

    // 弹出进度弹窗
    showDownloadProgress(data.task_id, title);

  } catch (err) {
    alert('下载请求失败: ' + err.message);
  }
}

/** 下载进度轮询 */
function showDownloadProgress(taskId, title) {
  const resultDiv = document.getElementById('searchResults');
  const progressHtml = `
    <div class="download-progress-card" id="dl-${taskId}">
      <div class="dl-title">⬇️ 正在下载「${escapeHtml(title)}」</div>
      <div class="dl-bar-wrap"><div class="dl-bar" id="dl-bar-${taskId}" style="width:0%"></div></div>
      <div class="dl-status" id="dl-status-${taskId}">排队中...</div>
    </div>
  `;

  // 在搜索结果顶部插入
  resultDiv.insertAdjacentHTML('afterbegin', progressHtml);

  // 轮询进度
  const pollInterval = setInterval(async () => {
    try {
      const res = await fetch(`${API_BASE}/download/status/${taskId}`, {
        headers: { 'Authorization': `Bearer ${currentToken}` }
      });
      const data = await res.json();

      const bar = document.getElementById(`dl-bar-${taskId}`);
      const status = document.getElementById(`dl-status-${taskId}`);
      if (bar) bar.style.width = (data.progress || 0) + '%';
      if (status) status.textContent = data.message || data.status;

      if (data.status === 'completed') {
        clearInterval(pollInterval);
        const card = document.getElementById(`dl-${taskId}`);
        if (card) {
          card.classList.add('dl-done');
          if (status) status.textContent = '✅ 下载完成 · 已收录到智库';
        }
      } else if (data.status === 'failed') {
        clearInterval(pollInterval);
        if (status) status.textContent = '❌ ' + (data.message || '下载失败');
      }
    } catch {
      // 网络异常时静默重试
    }
  }, 2000);

  // 5分钟超时保护
  setTimeout(() => clearInterval(pollInterval), 300000);
}

/** 本地已收录书籍下载 */
async function downloadLocal(bookId) {
  if (!currentToken) return;
  try {
    // 优先尝试本地下载（不依赖COS）
    const res = await fetch(`${API_BASE}/download/local/${encodeURIComponent(bookId)}`, {
      headers: { 'Authorization': `Bearer ${currentToken}` }
    });

    // 如果返回的是文件流（text/plain），直接触发下载
    const contentType = res.headers.get('content-type') || '';
    if (contentType.includes('text/plain')) {
      const blob = await res.blob();
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      const disposition = res.headers.get('content-disposition') || '';
      const filenameMatch = disposition.match(/filename\*=UTF-8''(.+)/);
      a.href = url;
      a.download = filenameMatch ? decodeURIComponent(filenameMatch[1]) : 'book.txt';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
      return;
    }

    const data = await res.json();
    if (data.error) {
      // 回退到旧版COS下载
      const res2 = await fetch(`${API_BASE}/download/${encodeURIComponent(bookId)}`, {
        headers: { 'Authorization': `Bearer ${currentToken}` }
      });
      const data2 = await res2.json();
      if (data2.error) {
        alert(data2.message);
      } else if (data2.download_url) {
        window.open(data2.download_url, '_blank');
      }
    } else if (data.download_url) {
      window.open(data.download_url, '_blank');
    }
  } catch (err) {
    alert('下载失败: ' + err.message);
  }
}

/* ═══════════════════════════════════════════
 * 在线阅读器 · Online Reader
 * ═══════════════════════════════════════════ */

let readerState = {
  bookId: '',
  source: '',
  sourceBookId: '',
  title: '',
  chapters: [],
  currentChapter: 0,
  fontSize: 18,
  theme: 'dark'  // 'dark' | 'light'
};

/** 打开在线阅读器 */
async function readBook(bookId) {
  if (!currentToken) {
    alert('请先登录后再阅读');
    return;
  }

  // 解析 bookId 获取 source 和 source_book_id
  // bookId 格式: "fq-123456" 或 "qm-789" 或 "fanqie-123456"
  let source = '';
  let sourceBookId = '';

  if (bookId.startsWith('fq-')) {
    source = 'fanqie';
    sourceBookId = bookId.replace('fq-', '');
  } else if (bookId.startsWith('qm-')) {
    source = 'qimao';
    sourceBookId = bookId.replace('qm-', '');
  } else if (bookId.includes('-')) {
    const parts = bookId.split('-');
    source = parts[0];
    sourceBookId = parts.slice(1).join('-');
  } else {
    source = 'fanqie';
    sourceBookId = bookId;
  }

  readerState.bookId = bookId;
  readerState.source = source;
  readerState.sourceBookId = sourceBookId;
  readerState.currentChapter = 0;

  // 显示阅读器
  document.getElementById('readerOverlay').style.display = 'flex';
  document.getElementById('readerContent').innerHTML = '<div class="reader-loading">📖 正在获取目录...</div>';
  document.getElementById('readerChapterList').innerHTML = '<div class="reader-loading">加载中...</div>';
  document.getElementById('readerNav').style.display = 'none';

  try {
    const res = await fetch(`${API_BASE}/reader/catalog/${encodeURIComponent(source)}/${encodeURIComponent(sourceBookId)}`, {
      headers: { 'Authorization': `Bearer ${currentToken}` }
    });
    const data = await res.json();

    if (data.error) {
      document.getElementById('readerContent').innerHTML = `<div class="reader-error">⚠️ ${escapeHtml(data.message)}</div>`;
      return;
    }

    readerState.chapters = data.chapters || [];
    readerState.title = (data.book && data.book.title) || '未知书名';

    document.getElementById('readerBookTitle').textContent = readerState.title;

    if (readerState.chapters.length === 0) {
      document.getElementById('readerContent').innerHTML = '<div class="reader-error">📭 未找到章节目录</div>';
      document.getElementById('readerChapterList').innerHTML = '<div class="reader-empty">暂无章节</div>';
      return;
    }

    // 渲染章节列表
    renderChapterList();

    // 加载第一章
    loadChapter(0);

  } catch (err) {
    document.getElementById('readerContent').innerHTML = `<div class="reader-error">加载失败: ${escapeHtml(err.message)}</div>`;
  }
}

/** 渲染章节侧边栏 */
function renderChapterList() {
  const list = document.getElementById('readerChapterList');
  list.innerHTML = readerState.chapters.map((ch, i) =>
    `<div class="reader-chapter-item${i === readerState.currentChapter ? ' active' : ''}" data-index="${i}" onclick="loadChapter(${i})">
      <span class="ch-index">${i + 1}</span>
      <span class="ch-title">${escapeHtml(ch.title || '第' + (i + 1) + '章')}</span>
    </div>`
  ).join('');
}

/** 加载指定章节 */
async function loadChapter(index) {
  if (index < 0 || index >= readerState.chapters.length) return;

  readerState.currentChapter = index;
  const ch = readerState.chapters[index];

  // 更新UI状态
  document.getElementById('readerContent').innerHTML = '<div class="reader-loading">📖 加载章节中...</div>';
  document.getElementById('readerNav').style.display = 'flex';
  document.getElementById('readerNavInfo').textContent = `${index + 1} / ${readerState.chapters.length}`;
  document.getElementById('readerPrevBtn').disabled = index === 0;
  document.getElementById('readerNextBtn').disabled = index === readerState.chapters.length - 1;

  // 更新章节列表高亮
  const items = document.querySelectorAll('.reader-chapter-item');
  items.forEach(el => el.classList.toggle('active', parseInt(el.dataset.index) === index));

  // 滚动章节列表到可见位置
  const activeItem = document.querySelector('.reader-chapter-item.active');
  if (activeItem) activeItem.scrollIntoView({ block: 'nearest', behavior: 'smooth' });

  try {
    const params = new URLSearchParams({
      source: ch.source || readerState.source,
      item_id: ch.item_id || '',
      book_id: readerState.bookId
    });

    const res = await fetch(`${API_BASE}/reader/chapter?${params}`, {
      headers: { 'Authorization': `Bearer ${currentToken}` }
    });
    const data = await res.json();

    if (data.error) {
      document.getElementById('readerContent').innerHTML = `<div class="reader-error">⚠️ ${escapeHtml(data.message)}</div>`;
      return;
    }

    const content = data.content || '(空白章节)';
    const title = ch.title || `第${index + 1}章`;

    document.getElementById('readerContent').innerHTML =
      `<h2 class="reader-chapter-title">${escapeHtml(title)}</h2>` +
      `<div class="reader-text" style="font-size:${readerState.fontSize}px">${formatReaderText(content)}</div>`;

    // 滚动到顶部
    document.getElementById('readerBody').scrollTop = 0;

  } catch (err) {
    document.getElementById('readerContent').innerHTML = `<div class="reader-error">加载失败: ${escapeHtml(err.message)}</div>`;
  }
}

function readerPrevChapter() {
  if (readerState.currentChapter > 0) loadChapter(readerState.currentChapter - 1);
}

function readerNextChapter() {
  if (readerState.currentChapter < readerState.chapters.length - 1) loadChapter(readerState.currentChapter + 1);
}

function closeReader() {
  document.getElementById('readerOverlay').style.display = 'none';
}

function readerFontSmaller() {
  readerState.fontSize = Math.max(12, readerState.fontSize - 2);
  const textEl = document.querySelector('.reader-text');
  if (textEl) textEl.style.fontSize = readerState.fontSize + 'px';
}

function readerFontLarger() {
  readerState.fontSize = Math.min(32, readerState.fontSize + 2);
  const textEl = document.querySelector('.reader-text');
  if (textEl) textEl.style.fontSize = readerState.fontSize + 'px';
}

function toggleReaderTheme() {
  const container = document.querySelector('.reader-container');
  const btn = document.getElementById('readerThemeBtn');
  if (readerState.theme === 'dark') {
    readerState.theme = 'light';
    container.classList.add('reader-light');
    btn.textContent = '🌞';
  } else {
    readerState.theme = 'dark';
    container.classList.remove('reader-light');
    btn.textContent = '🌙';
  }
}

function formatReaderText(text) {
  // 将纯文本格式化为适合阅读的HTML
  return text
    .split('\n')
    .map(line => {
      line = line.trim();
      if (!line) return '';
      return `<p class="reader-para">${escapeHtml(line)}</p>`;
    })
    .filter(Boolean)
    .join('');
}

/* 阅读器键盘快捷键 */
document.addEventListener('keydown', (e) => {
  const overlay = document.getElementById('readerOverlay');
  if (!overlay || overlay.style.display === 'none') return;
  if (e.key === 'Escape') closeReader();
  if (e.key === 'ArrowLeft') readerPrevChapter();
  if (e.key === 'ArrowRight') readerNextChapter();
});

/* ═══════════════════════════════════════════
 * AI图书管理员Agent · 对话交互
 * ═══════════════════════════════════════════ */

let agentSending = false;

async function agentSend() {
  const input = document.getElementById('agentInput');
  const msg = (input?.value || '').trim();
  if (!msg || agentSending) return;
  if (!currentToken) {
    appendAgentMessage('bot', '请先登录后再和我对话 📚');
    return;
  }

  // 显示用户消息
  appendAgentMessage('user', msg);
  input.value = '';
  agentSending = true;

  // 显示thinking状态
  const thinkingId = appendAgentMessage('bot', '思考中...', true);

  try {
    const res = await fetch(`${API_BASE}/agent/chat`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${currentToken}`
      },
      body: JSON.stringify({ message: msg })
    });
    const data = await res.json();

    // 移除thinking
    removeAgentMessage(thinkingId);

    if (data.error) {
      if (data.code === 'TOKEN_EXPIRED' || data.code === 'NO_TOKEN') {
        appendAgentMessage('bot', '登录已过期，请重新登录');
        setTimeout(() => doLogout(), 2000);
      } else {
        appendAgentMessage('bot', '⚠️ ' + (data.message || 'Agent异常'));
      }
    } else {
      // 显示Agent回复
      appendAgentMessage('bot', data.reply || '(无回复)');

      // 处理工具调用结果
      if (data.tool_results && data.tool_results.length > 0) {
        for (const tool of data.tool_results) {
          if (tool.type === 'search' && tool.results) {
            appendAgentSearchResults(tool.results);
          }
          if (tool.type === 'download') {
            appendAgentMessage('bot', `⬇️ 已创建下载任务: 「${tool.title}」(任务ID: ${tool.task_id})`);
            showDownloadProgress(tool.task_id, tool.title);
          }
        }
      }
    }
  } catch (err) {
    removeAgentMessage(thinkingId);
    appendAgentMessage('bot', '网络错误: ' + err.message);
  }

  agentSending = false;
}

let agentMsgCounter = 0;

function appendAgentMessage(role, text, isThinking) {
  const container = document.getElementById('agentMessages');
  if (!container) return;

  const id = 'amsg-' + (++agentMsgCounter);
  const div = document.createElement('div');
  div.className = `agent-msg agent-msg-${role}${isThinking ? ' agent-msg-thinking' : ''}`;
  div.id = id;

  const content = document.createElement('div');
  content.className = 'agent-msg-content';
  content.innerHTML = isThinking ? '<span class="thinking-dots">●●●</span>' : formatAgentText(text);
  div.appendChild(content);
  container.appendChild(div);

  // 自动滚动到底部
  container.scrollTop = container.scrollHeight;
  return id;
}

function removeAgentMessage(id) {
  const el = document.getElementById(id);
  if (el) el.remove();
}

function formatAgentText(text) {
  // 增强 Markdown 渲染 · 书岚风格
  let html = escapeHtml(text);

  // 分隔线
  html = html.replace(/^---$/gm, '<hr class="shulan-divider">');

  // 引用块
  html = html.replace(/^&gt;\s*(.+)$/gm, '<blockquote class="shulan-quote">$1</blockquote>');

  // 粗体
  html = html.replace(/\*\*(.+?)\*\*/g, '<strong class="shulan-bold">$1</strong>');

  // 斜体
  html = html.replace(/\*(.+?)\*/g, '<em class="shulan-italic">$1</em>');

  // 行内代码
  html = html.replace(/`(.+?)`/g, '<code>$1</code>');

  // 书名号高亮（限制匹配长度避免性能问题）
  html = html.replace(/《([^》]{1,100})》/g, '<span class="shulan-book-title">《$1》</span>');

  // 换行
  html = html.replace(/\n/g, '<br>');

  return html;
}

function appendAgentSearchResults(results) {
  const container = document.getElementById('agentMessages');
  if (!container || !results.length) return;

  const div = document.createElement('div');
  div.className = 'agent-msg agent-msg-bot';
  div.innerHTML = `<div class="agent-msg-content agent-search-results">
    <div class="agent-search-title">📜 找到 ${results.length} 本</div>
    ${results.slice(0, 8).map(book => {
      const sourceName = book.source_name || book.source;
      const sourceClass = book.source === 'fanqie' ? 'fanqie' : (book.source === 'qimao' ? 'qimao' : 'local');
      const hasFile = book.has_file;

      // 操作按钮 · 搜到书后直接展示「在线阅读」和「下载」
      let actionBtns = '';
      if (hasFile) {
        actionBtns = `
          <button class="shulan-action-btn shulan-btn-read" onclick="readBook('${escapeHtml(book.id || '')}')">📖 在线阅读</button>
          <button class="shulan-action-btn shulan-btn-dl" onclick="downloadLocal('${escapeHtml(book.id || '')}')">⬇️ 下载</button>
          <span class="agent-local-tag">已收录</span>`;
      } else if (book.source_book_id) {
        actionBtns = `
          <button class="shulan-action-btn shulan-btn-dl" onclick="startDownload('${escapeHtml(book.source)}','${escapeHtml(book.source_book_id)}','${escapeHtml(book.title)}','${escapeHtml(book.author || '')}')">⬇️ 下载到智库</button>`;
      }

      return `<div class="shulan-book-card">
        <div class="shulan-book-info">
          <span class="shulan-book-name">📖 ${escapeHtml(book.title)}</span>
          <span class="shulan-book-meta">${escapeHtml(book.author || '')} · <span class="source-badge ${sourceClass}">${sourceName}</span>${book.word_count ? ' · ' + book.word_count : ''}</span>
        </div>
        <div class="shulan-book-actions">${actionBtns}</div>
      </div>`;
    }).join('')}
  </div>`;
  container.appendChild(div);
  container.scrollTop = container.scrollHeight;
}

/* Agent输入框事件 */
document.getElementById('agentInput')?.addEventListener('keydown', e => {
  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault();
    agentSend();
  }
});

/* ═══════════════════════════════════════════
 * 初始化 · 自动恢复登录态
 * ═══════════════════════════════════════════ */

(async function init() {
  if (currentToken) {
    const valid = await checkSession();
    if (valid) {
      enterMainPage();
    } else {
      // Token失效，显示登录
      document.getElementById('loginOverlay').style.display = 'flex';
      document.getElementById('mainPage').style.display = 'none';
    }
  } else {
    document.getElementById('loginOverlay').style.display = 'flex';
    document.getElementById('mainPage').style.display = 'none';
  }
})();
