import FormData from 'form-data';
import axios from 'axios';

/**
 * Extraction Service Client
 * 调用Python微服务进行文档提取
 */

const EXTRACTION_SERVICE_URL = process.env.EXTRACTION_SERVICE_URL || 'http://localhost:8000';

export interface ExtractionResult {
  success: boolean;
  method: string; // pymupdf/nougat/mammoth/direct
  text: string;
  quality?: number;
  encoding?: string;
  language?: string;
  metadata: {
    filename: string;
    char_count?: number;
    line_count?: number;
    file_size?: number;
    page_count?: number;
    has_tables?: boolean;
    [key: string]: any;
  };
  error?: string;
}

class ExtractionClient {
  private baseUrl: string;

  constructor(baseUrl: string = EXTRACTION_SERVICE_URL) {
    this.baseUrl = baseUrl;
  }

  /**
   * 健康检查
   */
  async health(): Promise<{
    status: string;
    checks: any;
    timestamp: string;
  }> {
    try {
      const response = await axios.get(`${this.baseUrl}/api/health`);
      return response.data;
    } catch (error) {
      console.error('[ExtractionClient] Health check failed:', error);
      throw new Error('Extraction service is unavailable');
    }
  }

  /**
   * 通用文档提取接口
   * 自动检测文件类型并调用相应的提取方法
   */
  async extractDocument(
    file: Buffer,
    filename: string
  ): Promise<ExtractionResult> {
    try {
      const formData = new FormData();
      formData.append('file', file, filename);

      const response = await axios.post<ExtractionResult>(
        `${this.baseUrl}/api/extract`,
        formData,
        {
          headers: {
            ...formData.getHeaders(),
          },
          timeout: 120000, // 2分钟超时
        }
      );

      return response.data;
    } catch (error) {
      console.error('[ExtractionClient] Extract failed:', error);
      
      if (axios.isAxiosError(error) && error.response) {
        throw new Error(`Extraction failed: ${error.response.data.detail || error.message}`);
      }
      
      throw new Error('Document extraction failed');
    }
  }

  /**
   * PDF专用提取接口
   */
  async extractPdf(
    file: Buffer,
    filename: string,
    method?: 'auto' | 'nougat' | 'pymupdf'
  ): Promise<ExtractionResult> {
    try {
      const formData = new FormData();
      formData.append('file', file, filename);
      
      if (method) {
        formData.append('method', method);
      }

      const response = await axios.post<ExtractionResult>(
        `${this.baseUrl}/api/extract/pdf`,
        formData,
        {
          headers: {
            ...formData.getHeaders(),
          },
          timeout: 180000, // 3分钟超时（Nougat较慢）
        }
      );

      return response.data;
    } catch (error) {
      console.error('[ExtractionClient] PDF extract failed:', error);
      
      if (axios.isAxiosError(error) && error.response) {
        throw new Error(`PDF extraction failed: ${error.response.data.detail || error.message}`);
      }
      
      throw new Error('PDF extraction failed');
    }
  }

  /**
   * Docx专用提取接口
   */
  async extractDocx(
    file: Buffer,
    filename: string
  ): Promise<ExtractionResult> {
    try {
      const formData = new FormData();
      formData.append('file', file, filename);

      const response = await axios.post<ExtractionResult>(
        `${this.baseUrl}/api/extract/docx`,
        formData,
        {
          headers: {
            ...formData.getHeaders(),
          },
          timeout: 60000, // 1分钟超时
        }
      );

      return response.data;
    } catch (error) {
      console.error('[ExtractionClient] Docx extract failed:', error);
      
      if (axios.isAxiosError(error) && error.response) {
        throw new Error(`Docx extraction failed: ${error.response.data.detail || error.message}`);
      }
      
      throw new Error('Docx extraction failed');
    }
  }

  /**
   * Txt专用提取接口
   */
  async extractTxt(
    file: Buffer,
    filename: string
  ): Promise<ExtractionResult> {
    try {
      const formData = new FormData();
      formData.append('file', file, filename);

      const response = await axios.post<ExtractionResult>(
        `${this.baseUrl}/api/extract/txt`,
        formData,
        {
          headers: {
            ...formData.getHeaders(),
          },
          timeout: 30000, // 30秒超时
        }
      );

      return response.data;
    } catch (error) {
      console.error('[ExtractionClient] Txt extract failed:', error);
      
      if (axios.isAxiosError(error) && error.response) {
        throw new Error(`Txt extraction failed: ${error.response.data.detail || error.message}`);
      }
      
      throw new Error('Txt extraction failed');
    }
  }

  /**
   * 检测PDF语言
   */
  async detectLanguage(
    file: Buffer,
    filename: string
  ): Promise<{
    language: string;
    chinese_ratio: number;
    chinese_chars: number;
    total_chars: number;
  }> {
    try {
      const formData = new FormData();
      formData.append('file', file, filename);

      const response = await axios.post(
        `${this.baseUrl}/api/detect-language`,
        formData,
        {
          headers: {
            ...formData.getHeaders(),
          },
          timeout: 30000,
        }
      );

      return response.data;
    } catch (error) {
      console.error('[ExtractionClient] Language detection failed:', error);
      throw new Error('Language detection failed');
    }
  }

  /**
   * 获取PDF处理策略
   */
  async getPdfStrategy(
    file: Buffer,
    filename: string
  ): Promise<{
    detected_language: string;
    recommended_method: string;
    reason: string;
    nougat_available: boolean;
  }> {
    try {
      const formData = new FormData();
      formData.append('file', file, filename);

      const response = await axios.post(
        `${this.baseUrl}/api/pdf-strategy`,
        formData,
        {
          headers: {
            ...formData.getHeaders(),
          },
          timeout: 30000,
        }
      );

      return response.data;
    } catch (error) {
      console.error('[ExtractionClient] Get PDF strategy failed:', error);
      throw new Error('Get PDF strategy failed');
    }
  }
}

// 导出单例
export const extractionClient = new ExtractionClient();






