/**
 * file_parser.js - AI流程管理 文件解析工具集
 * 
 * 职责：解析各种格式的文件（Excel、PDF、Word、图片、文本）
 * 技术方案：前端解析为主，大模型API为辅
 */

class FileParser {
  constructor(options = {}) {
    this.llmConfig = options.llmConfig || null;
    this.maxFileSize = options.maxFileSize || 50 * 1024 * 1024; // 50MB
    this.chunkSize = options.chunkSize || 10000; // 每块字符数
    this.ocrEnabled = options.ocrEnabled !== false;
    this.timeout = options.timeout || 30000; // 默认30秒超时
    this.retryCount = options.retryCount || 2; // 默认重试2次
    this.retryDelay = options.retryDelay || 1000; // 重试间隔1秒
  }

  /**
   * 带超时的fetch
   */
  async fetchWithTimeout(url, options = {}, timeout = this.timeout) {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeout);
    
    try {
      const response = await fetch(url, {
        ...options,
        signal: controller.signal
      });
      clearTimeout(timeoutId);
      return response;
    } catch (error) {
      clearTimeout(timeoutId);
      throw error;
    }
  }

  /**
   * 带重试的请求
   */
  async fetchWithRetry(url, options = {}, retryCount = this.retryCount) {
    let lastError = null;
    
    for (let attempt = 0; attempt < retryCount; attempt++) {
      try {
        if (attempt > 0) {
          console.log(`[FileParser] 第${attempt + 1}次尝试...`);
          await this._sleep(this.retryDelay * attempt);
        }
        return await this.fetchWithTimeout(url, options);
      } catch (error) {
        lastError = error;
        console.warn(`[FileParser] 请求失败(尝试${attempt + 1}/${retryCount}):`, error.message);
        
        // 非网络错误不重试
        if (!this._isRetryableError(error)) {
          break;
        }
      }
    }
    
    throw lastError;
  }

  /**
   * 判断错误是否可重试
   */
  _isRetryableError(error) {
    const retryableMessages = ['network', 'timeout', 'abort', 'rate limit', '503', '502', '504', 'fetch'];
    const errorMsg = error.message?.toLowerCase() || '';
    return retryableMessages.some(msg => errorMsg.includes(msg));
  }

  /**
   * 延迟函数
   */
  _sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * 主解析入口
   * @param {File} file - 文件对象
   * @param {Object} options - 解析选项
   * @returns {Promise<Object>} 解析结果
   */
  async parse(file, options = {}) {
    // 检查文件大小
    if (file.size > this.maxFileSize) {
      throw new Error(`File too large: ${file.name} (${(file.size / 1024 / 1024).toFixed(2)}MB > ${this.maxFileSize / 1024 / 1024}MB limit)`);
    }

    const type = this.detectFileType(file);
    
    switch (type) {
      case 'excel':
        return await this.parseExcel(file, options);
      case 'pdf':
        return await this.parsePDF(file, options);
      case 'word':
        return await this.parseWord(file, options);
      case 'image':
        return await this.parseImage(file, options);
      case 'text':
        return await this.parseText(file, options);
      default:
        return await this.parseBinary(file, options);
    }
  }

  /**
   * 检测文件类型
   */
  detectFileType(file) {
    const name = file.name.toLowerCase();
    const type = file.type;

    // Excel
    if (/\.(xlsx|xls|csv)$/i.test(name) || 
        type.includes('spreadsheet') || 
        type.includes('excel') ||
        type === 'text/csv') {
      return 'excel';
    }

    // PDF
    if (/\.pdf$/i.test(name) || type === 'application/pdf') {
      return 'pdf';
    }

    // Word
    if (/\.(docx|doc)$/i.test(name) || 
        type.includes('word') ||
        type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
      return 'word';
    }

    // Image
    if (/\.(jpg|jpeg|png|gif|bmp|webp|tiff|svg)$/i.test(name) || 
        type.startsWith('image/')) {
      return 'image';
    }

    // Text
    if (/\.(txt|md|json|js|html|css|xml|yaml|yml|log|csv)$/i.test(name) ||
        type.startsWith('text/') ||
        type === 'application/json') {
      return 'text';
    }

    return 'binary';
  }

  /**
   * 解析Excel文件
   */
  async parseExcel(file, options = {}) {
    // 动态加载xlsx库
    await this.loadXLSX();

    const data = await file.arrayBuffer();
    const workbook = window.XLSX.read(data, { 
      type: 'array',
      cellFormula: true,
      cellNF: true,
      cellStyles: true
    });

    const result = {
      type: 'excel',
      name: file.name,
      size: file.size,
      sheetNames: workbook.SheetNames,
      sheets: {},
      summary: ''
    };

    let totalRows = 0;
    let totalCells = 0;

    workbook.SheetNames.forEach(sheetName => {
      const worksheet = workbook.Sheets[sheetName];
      const jsonData = window.XLSX.utils.sheet_to_json(worksheet, { 
        header: 1,
        defval: ''
      });
      
      // 计算统计信息
      const rowCount = jsonData.length;
      const colCount = rowCount > 0 ? jsonData[0].length : 0;
      totalRows += rowCount;
      totalCells += rowCount * colCount;

      // 截断大数据
      const maxRows = options.maxRows || 1000;
      const truncated = jsonData.length > maxRows;
      const displayData = truncated ? jsonData.slice(0, maxRows) : jsonData;

      result.sheets[sheetName] = {
        data: displayData,
        rowCount: rowCount,
        colCount: colCount,
        truncated: truncated,
        truncatedAt: truncated ? maxRows : null
      };
    });

    // 生成摘要
    result.summary = `Excel文件「${file.name}」包含 ${workbook.SheetNames.length} 个工作表，共约 ${totalRows} 行数据。`;
    if (Object.keys(result.sheets).length > 0) {
      const firstSheet = result.sheets[Object.keys(result.sheets)[0]];
      if (firstSheet.data.length > 0) {
        result.summary += `\n第一个工作表「${Object.keys(result.sheets)[0]}」有 ${firstSheet.rowCount} 行 × ${firstSheet.colCount} 列。`;
      }
    }

    // 转换为文本格式供AI使用
    result.textContent = this.excelToText(result);

    return result;
  }

  /**
   * Excel转文本
   */
  excelToText(result) {
    const lines = [];
    lines.push(`Excel文件: ${result.name}`);
    lines.push(`工作表数量: ${result.sheetNames.length}`);
    lines.push('');

    for (const [sheetName, sheet] of Object.entries(result.sheets)) {
      lines.push(`--- 工作表: ${sheetName} ---`);
      lines.push(`行数: ${sheet.rowCount}, 列数: ${sheet.colCount}`);
      
      // 输出前20行作为示例
      const previewRows = sheet.data.slice(0, 20);
      previewRows.forEach((row, idx) => {
        lines.push(`[${idx + 1}] ${row.join('\t')}`);
      });
      
      if (sheet.truncated) {
        lines.push(`... (已截断，共 ${sheet.rowCount} 行)`);
      }
      lines.push('');
    }

    return lines.join('\n');
  }

  /**
   * 解析PDF文件（简化版）
   */
  async parsePDF(file, options = {}) {
    // 目前返回基本信息，完整解析需要PDF.js
    const result = {
      type: 'pdf',
      name: file.name,
      size: file.size,
      text: '',
      pages: 0,
      summary: ''
    };

    // 尝试读取PDF页数（简单解析）
    try {
      const buffer = await file.arrayBuffer();
      const uint8Array = new Uint8Array(buffer);
      const text = new TextDecoder('ascii').decode(uint8Array.slice(0, 5000));
      
      // 查找页数
      const pageMatch = text.match(/\/Type\s*\/Pages[\s\S]*?\/Count\s+(\d+)/);
      if (pageMatch) {
        result.pages = parseInt(pageMatch[1]);
      }
    } catch (e) {}

    result.summary = `PDF文件「${file.name}」${result.pages > 0 ? `，约 ${result.pages} 页` : ''}。`;
    result.text = `[PDF文件: ${file.name}, 大小: ${(file.size / 1024).toFixed(2)}KB]`;

    return result;
  }

  /**
   * 解析Word文件（简化版）
   */
  async parseWord(file, options = {}) {
    // 目前返回基本信息，完整解析需要mammoth.js
    const result = {
      type: 'word',
      name: file.name,
      size: file.size,
      text: '',
      paragraphs: 0,
      summary: ''
    };

    result.summary = `Word文件「${file.name}」，大小 ${(file.size / 1024).toFixed(2)}KB。`;
    result.text = `[Word文件: ${file.name}]`;

    return result;
  }

  /**
   * 解析图片文件
   */
  async parseImage(file, options = {}) {
    const result = {
      type: 'image',
      name: file.name,
      size: file.size,
      mimeType: file.type,
      dataUrl: null,
      dimensions: null,
      ocrText: null,
      summary: ''
    };

    // 读取为DataURL
    result.dataUrl = await this.fileToDataURL(file);

    // 获取图片尺寸
    try {
      result.dimensions = await this.getImageDimensions(result.dataUrl);
    } catch (e) {}

    // OCR识别（如果启用）
    if (this.ocrEnabled && this.llmConfig?.apiKey) {
      try {
        result.ocrText = await this.performOCR(result.dataUrl);
      } catch (e) {
        console.warn('OCR failed:', e);
      }
    }

    result.summary = `图片文件「${file.name}」`;
    if (result.dimensions) {
      result.summary += `，尺寸 ${result.dimensions.width}×${result.dimensions.height}`;
    }
    if (result.ocrText) {
      result.summary += `，识别到 ${result.ocrText.length} 字符`;
    }

    result.text = result.ocrText || `[图片文件: ${file.name}]`;

    return result;
  }

  /**
   * 解析文本文件
   */
  async parseText(file, options = {}) {
    const content = await this.fileToText(file);
    
    // 截断过长的文本
    const maxLength = options.maxLength || 50000;
    const truncated = content.length > maxLength;
    const displayContent = truncated ? content.slice(0, maxLength) : content;

    const result = {
      type: 'text',
      name: file.name,
      size: file.size,
      content: displayContent,
      fullLength: content.length,
      truncated: truncated,
      lineCount: content.split('\n').length,
      summary: ''
    };

    result.summary = `文本文件「${file.name}」，共 ${result.lineCount} 行，${content.length} 字符`;
    if (truncated) {
      result.summary += ` (已截断显示前 ${maxLength} 字符)`;
    }

    result.text = displayContent;

    return result;
  }

  /**
   * 解析二进制文件
   */
  async parseBinary(file, options = {}) {
    return {
      type: 'binary',
      name: file.name,
      size: file.size,
      mimeType: file.type,
      summary: `二进制文件「${file.name}」，大小 ${(file.size / 1024).toFixed(2)}KB`,
      text: `[二进制文件: ${file.name}, 类型: ${file.type || 'unknown'}]`
    };
  }

  /**
   * 执行OCR识别（调用LLM多模态API）
   */
  async performOCR(dataUrl) {
    if (!this.llmConfig?.apiKey) {
      throw new Error('LLM API未配置');
    }

    // 压缩图片
    const compressed = await this.compressImage(dataUrl, 1920, 1080, 0.8);
    
    // 调用LLM多模态API进行图片理解（OCR功能）
    // 使用带重试的请求
    const response = await this.fetchWithRetry(
      'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions',
      {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${this.llmConfig.apiKey}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          model: 'qwen-vl-plus',
          messages: [
            {
              role: 'user',
              content: [
                { type: 'text', text: '请识别图片中的所有文字内容，并简要描述图片内容。' },
                { type: 'image_url', image_url: { url: compressed } }
              ]
            }
          ]
        })
      },
      2 // OCR重试2次
    );

    if (!response.ok) {
      throw new Error(`OCR API error: ${response.status}`);
    }

    const data = await response.json();
    // 兼容OpenAI格式返回
    return data.choices?.[0]?.message?.content || data.output?.text || '';
  }

  /**
   * 压缩图片
   */
  async compressImage(dataUrl, maxWidth, maxHeight, quality) {
    return new Promise((resolve, reject) => {
      const img = new Image();
      img.onload = () => {
        let { width, height } = img;
        
        // 计算缩放比例
        if (width > maxWidth || height > maxHeight) {
          const ratio = Math.min(maxWidth / width, maxHeight / height);
          width *= ratio;
          height *= ratio;
        }

        const canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        const ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0, width, height);
        
        resolve(canvas.toDataURL('image/jpeg', quality));
      };
      img.onerror = reject;
      img.src = dataUrl;
    });
  }

  /**
   * 获取图片尺寸
   */
  async getImageDimensions(dataUrl) {
    return new Promise((resolve, reject) => {
      const img = new Image();
      img.onload = () => {
        resolve({ width: img.width, height: img.height });
      };
      img.onerror = reject;
      img.src = dataUrl;
    });
  }

  /**
   * 文件转DataURL
   */
  async fileToDataURL(file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = (e) => resolve(e.target.result);
      reader.onerror = reject;
      reader.readAsDataURL(file);
    });
  }

  /**
   * 文件转文本（自动检测编码：优先 UTF-8，降级 GBK/GB2312）
   */
  async fileToText(file) {
    // 先尝试 UTF-8 读取
    const utf8Text = await new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = (e) => resolve(e.target.result);
      reader.onerror = reject;
      reader.readAsText(file, 'utf-8');
    });
    // 检测是否有乱码（大量 Unicode 替换字符 \ufffd 说明编码不对）
    const replacementCount = (utf8Text.match(/\ufffd/g) || []).length;
    const totalChars = utf8Text.length || 1;
    // 如果替换字符占比超过 5%，很可能是 GBK/GB2312 编码，重新读取
    if (replacementCount / totalChars > 0.05) {
      try {
        const gbkText = await new Promise((resolve, reject) => {
          const reader = new FileReader();
          reader.onload = (e) => resolve(e.target.result);
          reader.onerror = reject;
          reader.readAsText(file, 'gbk');
        });
        // GBK 结果如果没有替换字符，用 GBK 版本
        if ((gbkText.match(/\ufffd/g) || []).length < replacementCount) {
          return gbkText;
        }
      } catch (e) {
        // GBK 不支持（部分浏览器），保持 UTF-8 结果
      }
    }
    return utf8Text;
  }

  /**
   * 动态加载XLSX库
   */
  async loadXLSX() {
    if (window.XLSX) return;
    
    return new Promise((resolve, reject) => {
      const script = document.createElement('script');
      script.src = typeof chrome !== 'undefined' && chrome.runtime
        ? chrome.runtime.getURL('libs/xlsx.min.js')
        : 'libs/xlsx.min.js';
      script.onload = resolve;
      script.onerror = () => reject(new Error('Failed to load XLSX library'));
      document.head.appendChild(script);
    });
  }

  /**
   * 批量解析多个文件
   */
  async parseMultiple(files, options = {}) {
    const results = [];
    const errors = [];

    for (const file of files) {
      try {
        const result = await this.parse(file, options);
        results.push(result);
      } catch (error) {
        errors.push({ file: file.name, error: error.message });
        results.push({
          type: 'error',
          name: file.name,
          error: error.message,
          text: `[解析失败: ${file.name} - ${error.message}]`
        });
      }
    }

    return { results, errors };
  }
}

// ==================== 导出 ====================

if (typeof module !== 'undefined' && module.exports) {
  module.exports = { FileParser };
} else {
  window.FileParser = FileParser;
}
