import axios, { AxiosError } from 'axios'
import type { AxiosInstance } from 'axios'
import type {
  LoginRequest,
  LoginResponse,
  UploadResponse,
  ProcessRequest,
  ProcessResponse,
  BatchStatus,
  OCRResult,
  ExportRequest,
  ExportRule,
  CSSTemplate,
  TranslateRequest,
  TranslateResponse,
  ApiError,
} from '@/types/api'

/**
 * API Client Configuration
 * - In Docker: VITE_API_BASE_URL is empty string, use relative path
 * - In development: Use VITE_API_BASE_URL from .env or default to localhost:8000
 */
const envApiBaseUrl = import.meta.env.VITE_API_BASE_URL
const API_BASE_URL = envApiBaseUrl !== undefined ? envApiBaseUrl : 'http://localhost:8000'
const API_VERSION = 'v2'

class ApiClient {
  private client: AxiosInstance
  private token: string | null = null

  constructor() {
    this.client = axios.create({
      baseURL: `${API_BASE_URL}/api/${API_VERSION}`,
      timeout: 30000,
      headers: {
        'Content-Type': 'application/json',
      },
    })

    // Request interceptor to add auth token
    this.client.interceptors.request.use(
      (config) => {
        if (this.token) {
          config.headers.Authorization = `Bearer ${this.token}`
        }
        return config
      },
      (error) => Promise.reject(error)
    )

    // Response interceptor for error handling
    this.client.interceptors.response.use(
      (response) => response,
      (error: AxiosError<ApiError>) => {
        if (error.response?.status === 401) {
          // Token expired or invalid
          this.clearToken()
          window.location.href = '/login'
        }
        return Promise.reject(error)
      }
    )

    // Load token from localStorage
    this.loadToken()
  }

  /**
   * Set authentication token
   */
  setToken(token: string) {
    this.token = token
    localStorage.setItem('auth_token', token)
  }

  /**
   * Clear authentication token
   */
  clearToken() {
    this.token = null
    localStorage.removeItem('auth_token')
  }

  /**
   * Load token from localStorage
   */
  private loadToken() {
    const token = localStorage.getItem('auth_token')
    if (token) {
      this.token = token
    }
  }

  /**
   * Check if user is authenticated
   */
  isAuthenticated(): boolean {
    return this.token !== null
  }

  // ==================== Authentication ====================

  /**
   * Login
   */
  async login(data: LoginRequest): Promise<LoginResponse> {
    const response = await this.client.post<LoginResponse>('/auth/login', {
      username: data.username,
      password: data.password,
    })

    this.setToken(response.data.access_token)
    return response.data
  }

  /**
   * Logout
   */
  logout() {
    this.clearToken()
  }

  // ==================== File Upload ====================

  /**
   * Upload files
   */
  async uploadFiles(files: File[]): Promise<UploadResponse> {
    const formData = new FormData()
    files.forEach((file) => {
      formData.append('files', file)
    })

    const response = await this.client.post<UploadResponse>('/upload', formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    })

    return response.data
  }

  // ==================== OCR Processing ====================

  /**
   * Process OCR
   */
  async processOCR(data: ProcessRequest): Promise<ProcessResponse> {
    const response = await this.client.post<ProcessResponse>('/ocr/process', data)
    return response.data
  }

  /**
   * Get OCR result by file ID
   * Note: Backend uses file-level tracking, not task-level
   */
  async getOCRResult(fileId: number): Promise<OCRResult> {
    const response = await this.client.get<OCRResult>(`/ocr/result/${fileId}`)
    return response.data
  }

  /**
   * Get batch status
   */
  async getBatchStatus(batchId: number): Promise<BatchStatus> {
    const response = await this.client.get<BatchStatus>(`/batch/${batchId}/status`)
    return response.data
  }

  // ==================== Export ====================

  /**
   * Export results
   */
  async exportResults(data: ExportRequest): Promise<Blob> {
    const response = await this.client.post('/export', data, {
      responseType: 'blob',
    })
    return response.data
  }

  /**
   * Generate and download PDF
   */
  async exportPDF(fileId: number, cssTemplate?: string): Promise<Blob> {
    const params = cssTemplate ? { css_template: cssTemplate } : {}
    const response = await this.client.get(`/export/pdf/${fileId}`, {
      params,
      responseType: 'blob',
    })
    return response.data
  }

  /**
   * Get export rules
   */
  async getExportRules(): Promise<ExportRule[]> {
    const response = await this.client.get<ExportRule[]>('/export/rules')
    return response.data
  }

  /**
   * Create export rule
   */
  async createExportRule(rule: Omit<ExportRule, 'id' | 'created_at'>): Promise<ExportRule> {
    const response = await this.client.post<ExportRule>('/export/rules', rule)
    return response.data
  }

  /**
   * Update export rule
   */
  async updateExportRule(ruleId: number, rule: Partial<ExportRule>): Promise<ExportRule> {
    const response = await this.client.put<ExportRule>(`/export/rules/${ruleId}`, rule)
    return response.data
  }

  /**
   * Delete export rule
   */
  async deleteExportRule(ruleId: number): Promise<void> {
    await this.client.delete(`/export/rules/${ruleId}`)
  }

  /**
   * Get CSS templates
   */
  async getCSSTemplates(): Promise<CSSTemplate[]> {
    const response = await this.client.get<CSSTemplate[]>('/export/css-templates')
    return response.data
  }

  // ==================== Translation (FUTURE FEATURE - STUB) ====================

  /**
   * Translate document (STUB - Not yet implemented)
   * This is a placeholder for future translation functionality
   * @throws Will throw error with status 501 (Not Implemented)
   */
  async translateDocument(data: TranslateRequest): Promise<TranslateResponse> {
    // This endpoint is expected to return 501 Not Implemented until Phase 5
    const response = await this.client.post<TranslateResponse>('/translate/document', data)
    return response.data
  }

  /**
   * Get translation configs (NOT IMPLEMENTED)
   * This endpoint does not exist on backend - configs will be part of Phase 5
   * @deprecated Backend endpoint does not exist - will return 404
   */
  // async getTranslationConfigs(): Promise<TranslationConfig[]> {
  //   const response = await this.client.get<TranslationConfig[]>('/translate/configs')
  //   return response.data
  // }

  /**
   * Create translation config (NOT IMPLEMENTED)
   * This endpoint does not exist on backend - configs will be part of Phase 5
   * @deprecated Backend endpoint does not exist - will return 404
   */
  // async createTranslationConfig(
  //   config: Omit<TranslationConfig, 'id' | 'created_at'>
  // ): Promise<TranslationConfig> {
  //   const response = await this.client.post<TranslationConfig>('/translate/configs', config)
  //   return response.data
  // }
}

// Export singleton instance
export const apiClient = new ApiClient()
