#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Rewrite 3 functions in portal.html to implement 80% KB + 20% AI optimization:
1. handleMaterialSearch() - 素材检索
2. handleCaseSearch() - 案例推荐
3. handleAccountSetup() - 账户搭建

Logic:
- KB has related content -> KB content occupies 80% display, AI analysis/optimization occupies 20%
- KB has NO related content -> 100% AI generated
"""

import re

filepath = r'D:\AI-Ad-Agent\portal\portal.html'

with open(filepath, 'r', encoding='utf-8') as f:
    content = f.read()

# ============================================================
# Function 1: handleMaterialSearch (素材检索)
# ============================================================
old_material = '''async function handleMaterialSearch() {
  if (!requireLogin()) return;
  const prompt = document.getElementById('material-search-prompt').value.trim();
  if (!prompt) { showToast('请输入提示词/需求描述'); return; }

  const industry = document.getElementById('material-search-industry').value;
  const materialType = document.getElementById('material-search-type').value;
  const color = document.getElementById('material-search-color').value;
  const otherReq = document.getElementById('material-search-other').value.trim();

  document.getElementById('material-search-loading').style.display = 'block';
  document.getElementById('material-search-results-card').style.display = 'none';
  document.getElementById('material-search-materials-card').style.display = 'none';
  document.getElementById('material-search-btn').disabled = true;

  try {
    // 1. 先搜索知识库数据库（80%权重 - 主要展示知识库内容）
    let dbMaterials = [];
    let dbCopies = [];  // 知识库中的文案（metadata）
    try {
      const searchParams = new URLSearchParams();
      searchParams.append('q', prompt + ' ' + industry);
      if (materialType === '图片') searchParams.append('category', 'material');
      const kbResp = await fetch(`${PORTAL_URL}/api/knowledge/search?${searchParams.toString()}`, {
        headers: { 'Authorization': `Bearer ${authToken}` }
      });
      const kbData = await kbResp.json();
      if (kbData.success && kbData.files) {
        dbMaterials = kbData.files;
        // 提取有知识摘要的文件（作为参考文案）
        dbCopies = kbData.files.filter(f => f.metadata && f.metadata.trim());
      }
    } catch(e) { console.error('Knowledge search error:', e); }

    // 2. 显示知识库中的参考文案（占80%篇幅）
    const copyListEl = document.getElementById('material-search-copy-list');
    copyListEl.innerHTML = '';
    
    if (dbCopies.length > 0) {
      // 知识库有文案，直接展示（占主要篇幅）
      dbCopies.slice(0, 5).forEach((f, i) => {
        const div = document.createElement('div');
        div.className = 'copy-card';
        div.style.cssText = 'background:#f0f9ff;border:1px solid #bae6fd;border-radius:8px;padding:14px 16px;margin-bottom:10px;';
        div.innerHTML = `
          <div style="font-size:11px;color:#0369a1;font-weight:600;margin-bottom:4px;">\ud83d\udcc2 \u77e5\u8bc6\u5e93\u6587\u6848 ${i+1} \u00b7 ${f.filename}</div>
          <div style="font-size:14px;line-height:1.6;">${f.metadata.substring(0, 300)}${f.metadata.length > 300 ? '...' : ''}</div>
          <div style="margin-top:8px;display:flex;gap:8px;">
            <button style="font-size:12px;padding:4px 10px;border-radius:6px;border:1px solid var(--border);background:#fff;cursor:pointer;" onclick="navigator.clipboard.writeText(this.closest('.copy-card').innerText)">\ud83d\udccb \u590d\u5236</button>
            <button style="font-size:12px;padding:4px 10px;border-radius:6px;border:1px solid var(--border);background:#fff;cursor:pointer;" onclick="previewKFile(${f.id})">\ud83d\udc41\ufe0f \u9884\u89c8\u539f\u6587\u4ef6</button>
          </div>`;
        copyListEl.appendChild(div);
      });
    } else {
      // 知识库没有文案，用AI生成（但标注为"AI生成"）
      const copyPrompt = `\u4f60\u662f\u4e00\u4f4d\u8d44\u6df1\u5e7f\u544a\u6587\u6848\u7b56\u5212\u3002\u6839\u636e\u4ee5\u4e0b\u9700\u6c42\uff0c\u751f\u62103\u6761\u4e0d\u540c\u7684\u5e7f\u544a\u7d20\u6750\u6587\u6848\uff08\u6bcf\u6761100\u5b57\u4ee5\u5185\uff09\uff0c\u8981\u5438\u5f15\u4eba\u3001\u6709\u8f6c\u5316\u7387\u3002
\u9700\u6c42\uff1a${prompt}
\u884c\u4e1a\uff1a${industry || '\u4e0d\u9650'}
\u7d20\u6750\u7c7b\u578b\uff1a${materialType || '\u4e0d\u9650'}
\u4e3b\u8272\u8c03\uff1a${color || '\u4e0d\u9650'}
\u5176\u4ed6\u9700\u6c42\uff1a${otherReq || '\u65e0'}

\u8bf7\u6309\u4ee5\u4e0b JSON \u683c\u5f0f\u8fd4\u56de\uff1a
[{"title": "\u6587\u6848\u6807\u9898", "body": "\u6587\u6848\u6b63\u6587", "style": "\u98ce\u683c\u6807\u7b7e"}, ...]
\u53ea\u8fd4\u56de JSON\uff0c\u4e0d\u8981\u5176\u4ed6\u89e3\u91ca\u3002`;

      let copyList = [];
      try {
        const resp = await fetch(`${PORTAL_URL}/api/ollama/api/generate`, {
          method: 'POST',
          headers: {'Content-Type': 'application/json'},
          body: JSON.stringify({model: DEFAULT_MODEL, prompt: copyPrompt, stream: false, think: false})
        });
        const data = await resp.json();
        const text = data.response || data.message || '';
        const jsonMatch = text.match(/\\[.*\\]/s);
        if (jsonMatch) copyList = JSON.parse(jsonMatch[0]);
      } catch(e) { console.error('Ollama error:', e); showToast('AI服务调用失败', 'warning'); }

      if (!copyList || copyList.length === 0) {
        copyList = [
          {title: '\u53c2\u8003\u65b9\u6848', body: prompt, style: '\u57fa\u7840'},
        ];
      }

      copyList.forEach((item, i) => {
        const div = document.createElement('div');
        div.className = 'copy-card';
        div.style.cssText = 'background:#fef3c7;border:1px solid #fbbf24;border-radius:8px;padding:14px 16px;margin-bottom:10px;';
        div.innerHTML = `
          <div style="font-size:11px;color:#92400e;font-weight:600;margin-bottom:4px;">\ud83e\udd16 AI\u751f\u6210\u6587\u6848 ${i+1} \u00b7 ${item.style || '\u901a\u7528'}</div>
          <div style="font-size:14px;line-height:1.6;"><strong>${item.title || ''}</strong><br>${item.body || ''}</div>
          <div style="margin-top:8px;display:flex;gap:8px;">
            <button style="font-size:12px;padding:4px 10px;border-radius:6px;border:1px solid var(--border);background:#fff;cursor:pointer;" onclick="navigator.clipboard.writeText(this.closest('.copy-card').innerText)">\ud83d\udccb \u590d\u5236</button>
          </div>`;
        copyListEl.appendChild(div);
      });
    }
    
    document.getElementById('material-search-results-card').style.display = '';

    // 3. 显示知识库素材
    const grid = document.getElementById('material-search-material-grid');
    const empty = document.getElementById('material-search-material-empty');
    grid.innerHTML = '';
    if (dbMaterials.length === 0) {
      empty.style.display = '';
    } else {
      empty.style.display = 'none';
      dbMaterials.forEach(m => {
        const div = document.createElement('div');
        div.className = 'material-card';
        div.style.cssText = 'border:1px solid var(--border);border-radius:10px;overflow:hidden;padding:12px;';
        div.innerHTML = `
          <div style="font-size:14px;font-weight:500;margin-bottom:4px;">${m.filename || '\u7d20\u6750'}</div>
          <div style="font-size:12px;color:var(--text-secondary);">\u5206\u7c7b\uff1a${m.category || '\u672a\u5206\u7c7b'} \u00b7 ${m.upload_time || ''}</div>
          ${m.metadata ? `<div style="font-size:12px;margin-top:6px;color:var(--text);">${m.metadata.substring(0, 100)}</div>` : ''}
          <div style="margin-top:8px;display:flex;gap:6px;">
            <button style="font-size:11px;padding:3px 8px;border-radius:6px;border:1px solid var(--border);background:#fff;cursor:pointer;" onclick="previewKFile(${m.id})">\ud83d\udc41\ufe0f \u9884\u89c8</button>
            <button style="font-size:11px;padding:3px 8px;border-radius:6px;border:1px solid var(--border);background:#fff;cursor:pointer;" onclick="downloadKFile(${m.id})">\u2b07\ufe0f \u4e0b\u8f7d</button>
          </div>`;
        grid.appendChild(div);
      });
    }
    document.getElementById('material-search-materials-card').style.display = '';

    // \u4fdd\u5b58\u8bb0\u5f55
    saveRecord('material_search', '\u7d20\u6750\u68c0\u7d22: ' + prompt.substring(0, 50), 
      '\u63d0\u793a\u8bcd: ' + prompt + '<br>\u884c\u4e1a: ' + industry + '<br>\u77e5\u8bc6\u5e93\u6587\u6848: ' + dbCopies.length + '\u6761<br>\u77e5\u8bc6\u5e93\u7d20\u6750: ' + dbMaterials.length + '\u6761',
      { prompt, industry, material_type: materialType });

  } catch(e) {
    showToast('\u68c0\u7d22\u5931\u8d25\uff1a' + e.message, 'error');
  } finally {
    document.getElementById('material-search-loading').style.display = 'none';
    document.getElementById('material-search-btn').disabled = false;
  }
}'''

new_material = '''async function handleMaterialSearch() {
  if (!requireLogin()) return;
  const prompt = document.getElementById('material-search-prompt').value.trim();
  if (!prompt) { showToast('请输入提示词/需求描述'); return; }

  const industry = document.getElementById('material-search-industry').value;
  const materialType = document.getElementById('material-search-type').value;
  const color = document.getElementById('material-search-color').value;
  const otherReq = document.getElementById('material-search-other').value.trim();

  document.getElementById('material-search-loading').style.display = 'block';
  document.getElementById('material-search-results-card').style.display = 'none';
  document.getElementById('material-search-materials-card').style.display = 'none';
  document.getElementById('material-search-btn').disabled = true;

  try {
    // === 第1步：搜索知识库（占80%主体内容）===
    let dbMaterials = [];
    let dbCopies = [];
    try {
      const searchParams = new URLSearchParams();
      searchParams.append('q', prompt + ' ' + industry);
      if (materialType === '图片') searchParams.append('category', 'material');
      const kbResp = await fetch(`${PORTAL_URL}/api/knowledge/search?${searchParams.toString()}`, {
        headers: { 'Authorization': `Bearer ${authToken}` }
      });
      const kbData = await kbResp.json();
      if (kbData.success && kbData.files) {
        dbMaterials = kbData.files;
        dbCopies = kbData.files.filter(f => f.metadata && f.metadata.trim());
      }
    } catch(e) { console.error('Knowledge search error:', e); }

    const copyListEl = document.getElementById('material-search-copy-list');
    copyListEl.innerHTML = '';
    const hasKB = dbCopies.length > 0;

    // === 第2步：知识库内容占80% ===
    if (hasKB) {
      // 知识库有内容：展示知识库文案（80%主体）
      dbCopies.slice(0, 8).forEach((f, i) => {
        const div = document.createElement('div');
        div.className = 'copy-card';
        div.style.cssText = 'background:#f0f9ff;border:1px solid #bae6fd;border-radius:8px;padding:14px 16px;margin-bottom:10px;';
        div.innerHTML = `<div style="font-size:11px;color:#0369a1;font-weight:600;margin-bottom:4px;">\ud83d\udcc2 知识库文案 ${i+1} · ${f.filename}</div><div style="font-size:14px;line-height:1.6;">${f.metadata.substring(0, 500)}${f.metadata.length > 500 ? '...' : ''}</div><div style="margin-top:8px;display:flex;gap:8px;"><button style="font-size:12px;padding:4px 10px;border-radius:6px;border:1px solid var(--border);background:#fff;cursor:pointer;" onclick="navigator.clipboard.writeText(this.closest('.copy-card').innerText)">\ud83d\udccb 复制</button><button style="font-size:12px;padding:4px 10px;border-radius:6px;border:1px solid var(--border);background:#fff;cursor:pointer;" onclick="previewKFile(${f.id})">\ud83d\udc41\ufe0f 预览原文件</button></div>`;
        copyListEl.appendChild(div);
      });
    }

    // === 第3步：AI分析优化占20% ===
    let aiSuggestion = '';
    if (hasKB) {
      // 知识库有内容：AI基于知识库内容做优化分析（20%）
      const kbSummary = dbCopies.slice(0, 5).map(f => f.metadata.substring(0, 200)).join('\\n---\\n');
      const aiPrompt = `你是资深广告素材优化师。以下是知识库中的素材文案，请基于这些内容做优化分析和建议（不要重新生成文案，只做分析优化）：\\n\\n需求：${prompt}\\n行业：${industry || '不限'}\\n\\n知识库文案内容：\\n${kbSummary}\\n\\n请输出：\\n1. 知识库文案的亮点分析（2-3点）\\n2. 优化建议（2-3点，如何提升转化率）\\n3. 推荐使用场景\\n\\n控制在200字以内。`;

      try {
        const resp = await fetch(`${PORTAL_URL}/api/ollama/api/generate`, {
          method: 'POST',
          headers: {'Content-Type': 'application/json'},
          body: JSON.stringify({model: DEFAULT_MODEL, prompt: aiPrompt, stream: false, think: false})
        });
        const data = await resp.json();
        aiSuggestion = data.response || data.message || '';
      } catch(e) { console.error('AI analysis error:', e); }

      // 展示AI优化分析（20%篇幅）
      if (aiSuggestion) {
        const aiDiv = document.createElement('div');
        aiDiv.className = 'copy-card';
        aiDiv.style.cssText = 'background:#fef3c7;border:1px solid #fbbf24;border-radius:8px;padding:14px 16px;margin-bottom:10px;';
        aiDiv.innerHTML = `<div style="font-size:11px;color:#92400e;font-weight:600;margin-bottom:6px;">\ud83e\udd16 AI优化分析（基于知识库内容）</div><div style="font-size:13px;line-height:1.6;color:#78350f;">${aiSuggestion.replace(/</g,'&lt;').replace(/\\n/g,'<br>')}</div>`;
        copyListEl.appendChild(aiDiv);
      }
    } else {
      // 知识库无内容：100% AI生成
      const copyPrompt = `你是资深广告文案策划。根据以下需求生成3条广告素材文案（每条100字以内）：\\n需求：${prompt}\\n行业：${industry || '不限'}\\n素材类型：${materialType || '不限'}\\n主色调：${color || '不限'}\\n其他需求：${otherReq || '无'}\\n\\n请按JSON格式返回：[{"title":"标题","body":"正文","style":"风格"}]\\n只返回JSON。`;

      let copyList = [];
      try {
        const resp = await fetch(`${PORTAL_URL}/api/ollama/api/generate`, {
          method: 'POST',
          headers: {'Content-Type': 'application/json'},
          body: JSON.stringify({model: DEFAULT_MODEL, prompt: copyPrompt, stream: false, think: false})
        });
        const data = await resp.json();
        const text = data.response || data.message || '';
        const jsonMatch = text.match(/\\[.*\\]/s);
        if (jsonMatch) copyList = JSON.parse(jsonMatch[0]);
      } catch(e) { console.error('Ollama error:', e); }

      if (!copyList || copyList.length === 0) {
        copyList = [{title: '参考方案', body: prompt, style: '基础'}];
      }

      copyList.forEach((item, i) => {
        const div = document.createElement('div');
        div.className = 'copy-card';
        div.style.cssText = 'background:#fef3c7;border:1px solid #fbbf24;border-radius:8px;padding:14px 16px;margin-bottom:10px;';
        div.innerHTML = `<div style="font-size:11px;color:#92400e;font-weight:600;margin-bottom:4px;">\ud83e\udd16 AI生成文案 ${i+1} · ${item.style || '通用'}</div><div style="font-size:14px;line-height:1.6;"><strong>${item.title || ''}</strong><br>${item.body || ''}</div><div style="margin-top:8px;"><button style="font-size:12px;padding:4px 10px;border-radius:6px;border:1px solid var(--border);background:#fff;cursor:pointer;" onclick="navigator.clipboard.writeText(this.closest('.copy-card').innerText)">\ud83d\udccb 复制</button></div>`;
        copyListEl.appendChild(div);
      });
    }

    document.getElementById('material-search-results-card').style.display = '';

    // === 第4步：显示知识库素材文件 ===
    const grid = document.getElementById('material-search-material-grid');
    const empty = document.getElementById('material-search-material-empty');
    grid.innerHTML = '';
    if (dbMaterials.length === 0) {
      empty.style.display = '';
    } else {
      empty.style.display = 'none';
      dbMaterials.forEach(m => {
        const div = document.createElement('div');
        div.className = 'material-card';
        div.style.cssText = 'border:1px solid var(--border);border-radius:10px;overflow:hidden;padding:12px;';
        div.innerHTML = `<div style="font-size:14px;font-weight:500;margin-bottom:4px;">${m.filename || '素材'}</div><div style="font-size:12px;color:var(--text-secondary);">分类：${m.category || '未分类'} · ${m.upload_time || ''}</div>${m.metadata ? `<div style="font-size:12px;margin-top:6px;color:var(--text);">${m.metadata.substring(0, 100)}</div>` : ''}<div style="margin-top:8px;display:flex;gap:6px;"><button style="font-size:11px;padding:3px 8px;border-radius:6px;border:1px solid var(--border);background:#fff;cursor:pointer;" onclick="previewKFile(${m.id})">\ud83d\udc41\ufe0f 预览</button><button style="font-size:11px;padding:3px 8px;border-radius:6px;border:1px solid var(--border);background:#fff;cursor:pointer;" onclick="downloadKFile(${m.id})">\u2b07\ufe0f 下载</button></div>`;
        grid.appendChild(div);
      });
    }
    document.getElementById('material-search-materials-card').style.display = '';

    saveRecord('material_search', '素材检索: ' + prompt.substring(0, 50),
      '提示词: ' + prompt + '<br>行业: ' + industry + '<br>知识库文案: ' + dbCopies.length + '条<br>知识库素材: ' + dbMaterials.length + '条<br>AI优化: ' + (hasKB ? '20%分析' : '100%生成'),
      { prompt, industry, material_type: materialType });

  } catch(e) {
    showToast('检索失败：' + e.message, 'error');
  } finally {
    document.getElementById('material-search-loading').style.display = 'none';
    document.getElementById('material-search-btn').disabled = false;
  }
}'''

if old_material in content:
    content = content.replace(old_material, new_material)
    print("[OK] handleMaterialSearch replaced")
else:
    print("[SKIP] handleMaterialSearch not found (may already be updated)")

# ============================================================
# Function 2: handleCaseSearch (案例推荐)
# ============================================================
old_case = '''async function handleCaseSearch() {
  if (!requireLogin()) return;
  const prompt = document.getElementById('case-recommend-prompt').value.trim();
  if (!prompt) { showToast('请输入提示词/案例需求'); return; }

  const industry = document.getElementById('case-recommend-industry').value;
  const dimensions = document.getElementById('case-recommend-dimensions').value;
  const platform = document.getElementById('case-recommend-platform').value;

  document.getElementById('case-recommend-loading').style.display = 'block';
  document.getElementById('case-recommend-results-card').style.display = 'none';
  document.getElementById('case-recommend-search-btn').disabled = true;

  try {
    // 1. 先搜索知识库数据库（80%权重）
    let dbCases = [];
    try {
      const searchParams = new URLSearchParams();
      searchParams.append('q', prompt + ' ' + industry);
      searchParams.append('category', 'case');
      const kbResp = await fetch(`${PORTAL_URL}/api/knowledge/search?${searchParams.toString()}`, {
        headers: { 'Authorization': `Bearer ${authToken}` }
      });
      const kbData = await kbResp.json();
      if (kbData.success && kbData.files) {
        dbCases = kbData.files;
      }
    } catch(e) { console.error('Knowledge search error:', e); }

    // 2. 用AI推荐案例（20%权重，基于搜索结果作为上下文）
    let aiCases = [];
    try {
      let context = '';
      if (dbCases.length > 0) {
        context = '知识库中找到以下案例：\\n' + 
          dbCases.slice(0, 5).map(f => `- ${f.filename}: ${f.metadata || '无摘要'}`).join('\\n');
      }
      
      const aiPrompt = `你是一位资深广告优化师。根据以下需求，推荐3个相关的广告案例（可以是已知的经典案例或基于知识库内容），每个案例包含：案例名称、行业、平台、核心数据（点击率/转化率等）、亮点分析。
需求：${prompt}
行业：${industry || '不限'}
数据维度：${dimensions || '不限'}
平台：${platform || '不限'}
${context ? `\\n${context}` : ''}

请按以下 JSON 格式返回：
[{"name": "案例名称", "industry": "行业", "platform": "平台", "metrics": {"点击率": "X%", "转化率": "Y%"}, "highlights": ["亮点1", "亮点2"]}, ...]
只返回 JSON，不要其他解释。`;

      const resp = await fetch(`${PORTAL_URL}/api/ollama/api/generate`, {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({model: DEFAULT_MODEL, prompt: aiPrompt, stream: false, think: false})
      });
      const data = await resp.json();
      const text = data.response || data.message || '';
      const jsonMatch = text.match(/\\[.*\\]/s);
      if (jsonMatch) {
        aiCases = JSON.parse(jsonMatch[0]);
      }
    } catch(e) { console.error('Ollama error:', e); }

    // 3. 合并结果（数据库结果 + AI推荐）
    let allCases = [];
    
    // 先添加数据库结果
    dbCases.forEach(f => {
      allCases.push({
        id: f.id,
        filename: f.filename,
        category: f.category,
        upload_time: f.upload_time,
        metadata: f.metadata,
        source: 'database'
      });
    });
    
    // 再添加AI推荐
    aiCases.forEach((c, i) => {
      allCases.push({
        id: 'ai_' + i,
        filename: c.name || 'AI推荐案例',
        category: '案例',
        industry: c.industry || '',
        platform: c.platform || '',
        metrics: c.metrics || {},
        highlights: c.highlights || [],
        source: 'ai'
      });
    });

    // 4. 显示案例
    const grid = document.getElementById('case-recommend-grid');
    const empty = document.getElementById('case-recommend-empty');
    grid.innerHTML = '';
    if (allCases.length === 0) {
      empty.style.display = '';
    } else {
      empty.style.display = 'none';
      allCases.forEach(c => {
        const div = document.createElement('div');
        div.className = 'case-card';
        div.style.cssText = 'border:1px solid var(--border);border-radius:10px;overflow:hidden;padding:14px;margin-bottom:10px;cursor:pointer;transition:all 0.2s;';
        
        let metricsHtml = '';
        if (c.metrics) {
          metricsHtml = Object.entries(c.metrics).map(([k,v]) => 
            `<span style="font-size:11px;padding:3px 8px;border-radius:99px;background:#ede9fe;color:#6366f1;margin-right:4px;">${k}: ${v}</span>`
          ).join('');
        }
        
        let sourceBadge = c.source === 'database' ? 
          '<span style="font-size:10px;padding:2px 6px;border-radius:4px;background:#dbeafe;color:#2563eb;">知识库</span>' : 
          '<span style="font-size:10px;padding:2px 6px;border-radius:4px;background:#ede9fe;color:#6366f1;">AI推荐</span>';
        
        div.innerHTML = `
          <div style="font-size:15px;font-weight:600;margin-bottom:6px;">${c.filename || c.name || '案例'}</div>
          <div style="font-size:13px;color:var(--text-secondary);line-height:1.5;margin-bottom:10px;">行业：${c.industry || ''} · 平台：${c.platform || ''}</div>
          <div>${metricsHtml}</div>
          <div style="font-size:11px;color:var(--text-secondary);margin-top:10px;display:flex;justify-content:space-between;align-items:center;">
            <span>来源：${c.upload_time || 'AI生成'}</span>
            ${sourceBadge}
          </div>`;
        grid.appendChild(div);
      });
    }
    document.getElementById('case-recommend-results-card').style.display = '';

    // 保存记录
    saveRecord('case_recommend', '案例推荐: ' + prompt.substring(0, 50),
      '需求: ' + prompt + '<br>行业: ' + industry + '<br>推荐案例数: ' + allCases.length + '<br>知识库结果: ' + dbCases.length + '条',
      { prompt, industry, platform });

  } catch(e) {
    showToast('推荐失败：' + e.message, 'error');
  } finally {
    document.getElementById('case-recommend-loading').style.display = 'none';
    document.getElementById('case-recommend-search-btn').disabled = false;
  }
}'''

new_case = '''async function handleCaseSearch() {
  if (!requireLogin()) return;
  const prompt = document.getElementById('case-recommend-prompt').value.trim();
  if (!prompt) { showToast('请输入提示词/案例需求'); return; }

  const industry = document.getElementById('case-recommend-industry').value;
  const dimensions = document.getElementById('case-recommend-dimensions').value;
  const platform = document.getElementById('case-recommend-platform').value;

  document.getElementById('case-recommend-loading').style.display = 'block';
  document.getElementById('case-recommend-results-card').style.display = 'none';
  document.getElementById('case-recommend-search-btn').disabled = true;

  try {
    // === 第1步：搜索知识库案例（占80%主体）===
    let dbCases = [];
    try {
      const searchParams = new URLSearchParams();
      searchParams.append('q', prompt + ' ' + industry);
      searchParams.append('category', 'case');
      const kbResp = await fetch(`${PORTAL_URL}/api/knowledge/search?${searchParams.toString()}`, {
        headers: { 'Authorization': `Bearer ${authToken}` }
      });
      const kbData = await kbResp.json();
      if (kbData.success && kbData.files) {
        dbCases = kbData.files;
      }
    } catch(e) { console.error('Knowledge search error:', e); }

    const grid = document.getElementById('case-recommend-grid');
    const empty = document.getElementById('case-recommend-empty');
    grid.innerHTML = '';
    const hasKB = dbCases.length > 0;

    if (hasKB) {
      // === 知识库案例占80%主体展示 ===
      empty.style.display = 'none';
      dbCases.slice(0, 10).forEach((f, i) => {
        const div = document.createElement('div');
        div.className = 'case-card';
        div.style.cssText = 'border:1px solid #bae6fd;border-radius:10px;padding:14px;margin-bottom:10px;background:#f0f9ff;';
        div.innerHTML = `<div style="display:flex;justify-content:space-between;align-items:start;margin-bottom:6px;"><div style="font-size:15px;font-weight:600;">${f.filename || '案例'}</div><span style="font-size:10px;padding:2px 8px;border-radius:4px;background:#dbeafe;color:#2563eb;flex-shrink:0;">知识库 ${i+1}</span></div><div style="font-size:13px;color:var(--text-secondary);margin-bottom:8px;">分类：${f.category || '案例'} · ${f.upload_time || ''}</div>${f.metadata ? `<div style="font-size:13px;line-height:1.6;color:var(--text);">${f.metadata.substring(0, 400)}${f.metadata.length > 400 ? '...' : ''}</div>` : ''}<div style="margin-top:10px;display:flex;gap:6px;"><button style="font-size:11px;padding:4px 10px;border-radius:6px;border:1px solid var(--border);background:#fff;cursor:pointer;" onclick="previewKFile(${f.id})">\ud83d\udc41\ufe0f 预览详情</button><button style="font-size:11px;padding:4px 10px;border-radius:6px;border:1px solid var(--border);background:#fff;cursor:pointer;" onclick="downloadKFile(${f.id})">\u2b07\ufe0f 下载</button></div>`;
        grid.appendChild(div);
      });

      // === AI分析评估占20% ===
      const kbSummary = dbCases.slice(0, 5).map(f => `${f.filename}: ${f.metadata ? f.metadata.substring(0, 200) : '无摘要'}`).join('\\n---\\n');
      const aiPrompt = `你是资深广告案例分析专家。以下是从知识库中检索到的案例，请对这些案例做分析评估（不要重新生成案例）：\\n\\n用户需求：${prompt}\\n行业：${industry || '不限'}\\n平台：${platform || '不限'}\\n\\n知识库案例：\\n${kbSummary}\\n\\n请输出：\\n1. 案例亮点总结（2-3点）\\n2. 适用场景分析\\n3. 优化建议（如何在当前需求下应用这些案例经验）\\n\\n控制在200字以内。`;

      try {
        const resp = await fetch(`${PORTAL_URL}/api/ollama/api/generate`, {
          method: 'POST',
          headers: {'Content-Type': 'application/json'},
          body: JSON.stringify({model: DEFAULT_MODEL, prompt: aiPrompt, stream: false, think: false})
        });
        const data = await resp.json();
        const aiText = data.response || data.message || '';
        if (aiText) {
          const aiDiv = document.createElement('div');
          aiDiv.style.cssText = 'border:1px solid #fbbf24;border-radius:10px;padding:14px;margin-bottom:10px;background:#fef3c7;';
          aiDiv.innerHTML = `<div style="display:flex;justify-content:space-between;align-items:start;margin-bottom:6px;"><div style="font-size:15px;font-weight:600;color:#92400e;">\ud83e\udd16 AI案例分析（基于知识库案例）</div><span style="font-size:10px;padding:2px 8px;border-radius:4px;background:#fbbf24;color:#78350f;flex-shrink:0;">AI 20%</span></div><div style="font-size:13px;line-height:1.6;color:#78350f;">${aiText.replace(/</g,'&lt;').replace(/\\n/g,'<br>')}</div>`;
          grid.appendChild(aiDiv);
        }
      } catch(e) { console.error('AI analysis error:', e); }

    } else {
      // === 知识库无案例：100% AI生成 ===
      const aiPrompt = `你是资深广告优化师。根据以下需求推荐3个广告案例，每个案例包含名称、行业、平台、核心数据和亮点：\\n需求：${prompt}\\n行业：${industry || '不限'}\\n平台：${platform || '不限'}\\n\\n请按JSON格式返回：[{"name":"案例名","industry":"行业","platform":"平台","metrics":{"点击率":"X%","转化率":"Y%"},"highlights":["亮点1","亮点2"]}]\\n只返回JSON。`;

      let aiCases = [];
      try {
        const resp = await fetch(`${PORTAL_URL}/api/ollama/api/generate`, {
          method: 'POST',
          headers: {'Content-Type': 'application/json'},
          body: JSON.stringify({model: DEFAULT_MODEL, prompt: aiPrompt, stream: false, think: false})
        });
        const data = await resp.json();
        const text = data.response || data.message || '';
        const jsonMatch = text.match(/\\[.*\\]/s);
        if (jsonMatch) aiCases = JSON.parse(jsonMatch[0]);
      } catch(e) { console.error('Ollama error:', e); }

      if (aiCases.length === 0) {
        empty.style.display = '';
      } else {
        empty.style.display = 'none';
        aiCases.forEach((c, i) => {
          let metricsHtml = '';
          if (c.metrics) {
            metricsHtml = Object.entries(c.metrics).map(([k,v]) => `<span style="font-size:11px;padding:3px 8px;border-radius:99px;background:#ede9fe;color:#6366f1;margin-right:4px;">${k}: ${v}</span>`).join('');
          }
          const div = document.createElement('div');
          div.className = 'case-card';
          div.style.cssText = 'border:1px solid var(--border);border-radius:10px;padding:14px;margin-bottom:10px;';
          div.innerHTML = `<div style="display:flex;justify-content:space-between;align-items:start;margin-bottom:6px;"><div style="font-size:15px;font-weight:600;">${c.name || '案例'}</div><span style="font-size:10px;padding:2px 8px;border-radius:4px;background:#ede9fe;color:#6366f1;flex-shrink:0;">AI生成</span></div><div style="font-size:13px;color:var(--text-secondary);margin-bottom:10px;">行业：${c.industry || ''} · 平台：${c.platform || ''}</div><div>${metricsHtml}</div>${c.highlights ? `<div style="font-size:12px;margin-top:8px;color:var(--text);">${c.highlights.map(h => '\u2022 ' + h).join('<br>')}</div>` : ''}`;
          grid.appendChild(div);
        });
      }
    }

    document.getElementById('case-recommend-results-card').style.display = '';

    saveRecord('case_recommend', '案例推荐: ' + prompt.substring(0, 50),
      '需求: ' + prompt + '<br>行业: ' + industry + '<br>知识库案例: ' + dbCases.length + '条<br>AI分析: ' + (hasKB ? '20%评估' : '100%生成'),
      { prompt, industry, platform });

  } catch(e) {
    showToast('推荐失败：' + e.message, 'error');
  } finally {
    document.getElementById('case-recommend-loading').style.display = 'none';
    document.getElementById('case-recommend-search-btn').disabled = false;
  }
}'''

if old_case in content:
    content = content.replace(old_case, new_case)
    print("[OK] handleCaseSearch replaced")
else:
    print("[SKIP] handleCaseSearch not found (may already be updated)")

# ============================================================
# Function 3: handleAccountSetup (账户搭建)
# ============================================================
# This function is long, use regex to find and replace
# Find from "async function handleAccountSetup()" to the next "// ====== 知识库管理 ======"

pattern_account = r'async function handleAccountSetup\(\) \{.*?// ====== 知识库管理 ======'
match = re.search(pattern_account, content, re.DOTALL)
if match:
    old_account = match.group(0)
    
    new_account = '''async function handleAccountSetup() {
  if (!requireLogin()) return;
  const prompt = document.getElementById('account-setup-prompt').value.trim();
  const industry = document.getElementById('account-setup-industry').value;
  const platform = document.getElementById('account-setup-platform').value;
  const budget = document.getElementById('account-setup-budget').value.trim();
  const ageRange = document.getElementById('account-setup-age-range').value.trim();

  if (!prompt) { showToast('请输入提示词/推广目标'); return; }
  if (!industry) { showToast('请选择行业'); return; }
  if (!platform) { showToast('请选择推广平台'); return; }

  document.getElementById('account-setup-loading').style.display = 'block';
  document.getElementById('account-setup-result-card').style.display = 'none';
  document.getElementById('account-setup-error-msg').style.display = 'none';
  document.getElementById('account-setup-generate-btn').disabled = true;

  try {
    // === 第1步：搜索知识库（占80%主体）===
    let dbKnowledge = [];
    try {
      const searchParams = new URLSearchParams();
      searchParams.append('q', prompt + ' ' + industry + ' ' + platform);
      const kbResp = await fetch(`${PORTAL_URL}/api/knowledge/search?${searchParams.toString()}`, {
        headers: { 'Authorization': `Bearer ${authToken}` }
      });
      const kbData = await kbResp.json();
      if (kbData.success && kbData.files) {
        dbKnowledge = kbData.files;
      }
    } catch(e) { console.error('Knowledge search error:', e); }

    const hasKB = dbKnowledge.length > 0;
    let result = null;

    if (hasKB) {
      // === 知识库内容占80%：从知识库提取搭建方案 ===
      const kbSummary = dbKnowledge.slice(0, 5).map(f => `${f.filename}: ${f.metadata ? f.metadata.substring(0, 300) : '无摘要'}`).join('\\n---\\n');

      // AI基于知识库内容整理方案（20%优化）
      const aiPrompt = `你是资深广告投放专家。以下是知识库中的账户搭建相关内容，请基于这些内容整理出完整的账户搭建方案（80%使用知识库内容，20%做优化补充）：\\n\\n推广目标：${prompt}\\n行业：${industry}\\n平台：${platform}\\n预算：${budget || '待定'}\\n人群：${ageRange || '待定'}\\n\\n知识库内容：\\n${kbSummary}\\n\\n请基于以上知识库内容，整理并优化出账户搭建方案，按以下JSON格式返回：\\n{"flow":[{"step":1,"title":"步骤","desc":"说明"}],"copy":"推广文案150字内","materials":[{"type":"素材类型","desc":"描述"}],"budget":[{"item":"项目","amount":"金额/比例","note":"说明"}],"audience":[{"tag":"标签","desc":"说明"}]}\\n只返回JSON。`;

      try {
        const resp = await fetch(`${PORTAL_URL}/api/ollama/api/generate`, {
          method: 'POST',
          headers: {'Content-Type': 'application/json'},
          body: JSON.stringify({model: DEFAULT_MODEL, prompt: aiPrompt, stream: false, think: false})
        });
        const data = await resp.json();
        const text = data.response || data.message || '';
        const jsonMatch = text.match(/\\{.*\\}/s);
        if (jsonMatch) result = JSON.parse(jsonMatch[0]);
      } catch(e) { console.error('AI error:', e); }

      // 如果AI整理失败，用知识库内容构建基础方案
      if (!result) {
        result = {
          flow: dbKnowledge.slice(0, 5).map((f, i) => ({step: i+1, title: f.filename, desc: f.metadata ? f.metadata.substring(0, 150) : '参考知识库内容'})),
          copy: '基于知识库内容整理',
          materials: [{type: '知识库参考', desc: dbKnowledge.length + '条相关知识'}],
          budget: [{item: '参考知识库', amount: '详见知识库', note: '基于知识库方案'}],
          audience: [{tag: industry + '目标人群', desc: '参考知识库定义'}]
        };
      }
    } else {
      // === 知识库无内容：100% AI生成 ===
      const aiPrompt = `你是资深广告投放专家。根据以下信息生成完整的账户搭建方案：\\n推广目标：${prompt}\\n行业：${industry}\\n平台：${platform}\\n预算：${budget || '待定'}\\n人群：${ageRange || '待定'}\\n\\n请按JSON格式返回：\\n{"flow":[{"step":1,"title":"步骤","desc":"说明"}],"copy":"推广文案150字内","materials":[{"type":"素材类型","desc":"描述"}],"budget":[{"item":"项目","amount":"金额/比例","note":"说明"}],"audience":[{"tag":"标签","desc":"说明"}]}\\n只返回JSON。`;

      try {
        const resp = await fetch(`${PORTAL_URL}/api/ollama/api/generate`, {
          method: 'POST',
          headers: {'Content-Type': 'application/json'},
          body: JSON.stringify({model: DEFAULT_MODEL, prompt: aiPrompt, stream: false, think: false})
        });
        const data = await resp.json();
        const text = data.response || data.message || '';
        const jsonMatch = text.match(/\\{.*\\}/s);
        if (jsonMatch) result = JSON.parse(jsonMatch[0]);
      } catch(e) { console.error('AI error:', e); }

      // AI失败时的默认方案
      if (!result) {
        result = {
          flow: [
            {step:1, title:'创建广告账户', desc:`在${platform}后台创建企业广告账户，完成资质认证`},
            {step:2, title:'设置投放目标', desc:`选择「${industry}」行业，设定转化目标`},
            {step:3, title:'搭建广告组', desc:'按产品/人群/创意类型分组'},
            {step:4, title:'制作素材', desc:'准备3-5套图片/视频素材'},
            {step:5, title:'设置定向', desc:`按${ageRange || '18-40岁'}年龄段定向`},
            {step:6, title:'设定预算和出价', desc:`按${budget || '日预算500元'}设定策略`},
            {step:7, title:'上线测试', desc:'小预算测试2-3天，保留优质素材'},
            {step:8, title:'优化放量', desc:'根据数据优化，逐步放大预算'}
          ],
          copy: prompt,
          materials: [
            {type:'视频素材', desc:`15s/30s 短视频，展示${industry}产品使用场景`},
            {type:'图片素材', desc:'横版/竖版图片，包含产品特写、场景图'},
            {type:'文案素材', desc:'信息流标题+详情页文案'}
          ],
          budget: [
            {item:'素材制作', amount:'25%', note:'3-5条素材'},
            {item:'广告投放', amount:'60%', note:`按${budget || '日预算'}`},
            {item:'优化测试', amount:'15%', note:'A/B测试'}
          ],
          audience: [
            {tag:`${ageRange || '18-35岁'}`, desc:'主力消费人群'},
            {tag:industry + '兴趣人群', desc:'平台兴趣标签'},
            {tag:'相似人群', desc:'Look-alike扩量'}
          ]
        };
      }
    }

    // === 显示结果 ===
    // 1. 搭建流程
    const flowEl = document.getElementById('account-setup-flow-steps');
    flowEl.innerHTML = '';
    (result.flow || []).forEach(item => {
      const div = document.createElement('div');
      div.style.cssText = 'display:flex;gap:12px;align-items:flex-start;margin-bottom:10px;';
      div.innerHTML = `<div style="width:28px;height:28px;border-radius:99px;background:#ede9fe;color:#6366f1;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;flex-shrink:0;">${item.step || ''}</div><div><div style="font-size:14px;font-weight:600;">${item.title || ''}</div><div style="font-size:13px;color:var(--text-secondary);line-height:1.5;">${item.desc || ''}</div></div>`;
      flowEl.appendChild(div);
    });

    // 2. 推广文案
    document.getElementById('account-setup-copy-preview').textContent = result.copy || '暂无文案';

    // 3. 素材规划
    const matEl = document.getElementById('account-setup-material-plan');
    matEl.innerHTML = '';
    (result.materials || []).forEach(item => {
      const div = document.createElement('div');
      div.style.cssText = 'background:#f8fafc;border:1px solid var(--border);border-radius:8px;padding:12px 14px;';
      div.innerHTML = `<div style="font-size:11px;color:var(--primary);font-weight:600;margin-bottom:4px;">${item.type || ''}</div><div style="font-size:13px;color:var(--text);line-height:1.5;">${item.desc || ''}</div>`;
      matEl.appendChild(div);
    });

    // 4. 预算分配
    const budEl = document.getElementById('account-setup-budget-grid');
    budEl.innerHTML = '';
    (result.budget || []).forEach(item => {
      const div = document.createElement('div');
      div.style.cssText = 'background:#f8fafc;border:1px solid var(--border);border-radius:8px;padding:12px 14px;';
      div.innerHTML = `<div style="font-size:11px;color:var(--text-secondary);margin-bottom:4px;">${item.item || ''}</div><div style="font-size:16px;font-weight:700;color:var(--primary);">${item.amount || ''}</div><div style="font-size:11px;color:var(--text-secondary);margin-top:4px;">${item.note || ''}</div>`;
      budEl.appendChild(div);
    });

    // 5. 目标人群
    const audEl = document.getElementById('account-setup-audience-tags');
    audEl.innerHTML = '';
    (result.audience || []).forEach(item => {
      const span = document.createElement('span');
      span.style.cssText = 'padding:5px 12px;border-radius:99px;background:#fef3c7;color:#92400e;font-size:13px;font-weight:500;';
      span.textContent = (item.tag || '') + (item.desc ? '（' + item.desc + '）' : '');
      audEl.appendChild(span);
    });

    // 6. 知识库来源标注
    const resultCard = document.getElementById('account-setup-result-card');
    // 先移除旧的KB参考
    const oldRef = resultCard.querySelector('[data-kb-ref]');
    if (oldRef) oldRef.remove();

    if (hasKB) {
      let refHtml = '<div data-kb-ref="1" style="margin-top:16px;padding:14px;background:#f0f9ff;border:1px solid #bae6fd;border-radius:8px;">';
      refHtml += '<div style="font-size:13px;color:#0369a1;font-weight:600;margin-bottom:8px;">\ud83d\udcc2 知识库来源（80%内容来自知识库，AI优化占20%）</div>';
      dbKnowledge.slice(0, 5).forEach(f => {
        refHtml += `<div style="font-size:12px;color:#0c4a6e;margin-top:6px;display:flex;align-items:center;gap:6px;"><span>\u2022</span><span style="flex:1;">${f.filename}</span><button style="font-size:11px;padding:2px 8px;border-radius:4px;border:1px solid #bae6fd;background:#fff;cursor:pointer;color:#0369a1;" onclick="previewKFile(${f.id})">\ud83d\udc41\ufe0f 查看</button></div>`;
      });
      refHtml += '</div>';
      resultCard.insertAdjacentHTML('beforeend', refHtml);
    } else {
      let refHtml = '<div data-kb-ref="1" style="margin-top:16px;padding:14px;background:#fef3c7;border:1px solid #fbbf24;border-radius:8px;">';
      refHtml += '<div style="font-size:13px;color:#92400e;font-weight:600;">\ud83e\udd16 本方案由AI 100%生成（知识库中未找到相关内容）</div>';
      refHtml += '</div>';
      resultCard.insertAdjacentHTML('beforeend', refHtml);
    }

    document.getElementById('account-setup-result-card').style.display = '';

    saveRecord('account_setup', '账户搭建: ' + prompt.substring(0, 50),
      '推广目标: ' + prompt + '<br>行业: ' + industry + '<br>平台: ' + platform + '<br>知识库参考: ' + dbKnowledge.length + '条<br>AI占比: ' + (hasKB ? '20%优化' : '100%生成'),
      { prompt, industry, platform, budget });

  } catch(e) {
    document.getElementById('account-setup-error-msg').textContent = '生成失败：' + e.message;
    document.getElementById('account-setup-error-msg').style.display = '';
  } finally {
    document.getElementById('account-setup-loading').style.display = 'none';
    document.getElementById('account-setup-generate-btn').disabled = false;
  }
}


// ====== 知识库管理 ======'''

    content = content.replace(old_account, new_account)
    print("[OK] handleAccountSetup replaced")
else:
    print("[SKIP] handleAccountSetup not found")

# Write back
with open(filepath, 'w', encoding='utf-8') as f:
    f.write(content)

print("\nAll 3 functions updated successfully!")
print("Logic: KB has content -> 80% KB + 20% AI analysis")
print("       KB no content  -> 100% AI generation")
