/**
 * BowongTextVideoAgent 工具函数
 * 提供错误处理、重试机制、日志记录、缓存和性能优化等辅助功能
 */

import {
  TaskStatus,
  TaskStatusResponse,
  NetworkError,
  ValidationError,
  TaskTimeoutError,
  TaskFailedError,
} from '../types/bowongTextVideoAgent';

/**
 * 重试配置
 */
export interface RetryConfig {
  maxAttempts: number;
  baseDelay: number;
  maxDelay: number;
  backoffFactor: number;
  retryCondition?: (error: any) => boolean;
}

/**
 * 默认重试配置
 */
export const DEFAULT_RETRY_CONFIG: RetryConfig = {
  maxAttempts: 3,
  baseDelay: 1000,
  maxDelay: 10000,
  backoffFactor: 2,
  retryCondition: (error: any) => {
    // 网络错误和超时错误可以重试
    return error instanceof NetworkError || 
           error instanceof TaskTimeoutError ||
           (error.message && error.message.includes('网络'));
  },
};

/**
 * 指数退避重试函数
 */
export async function retryWithBackoff<T>(
  operation: () => Promise<T>,
  config: Partial<RetryConfig> = {}
): Promise<T> {
  const finalConfig = { ...DEFAULT_RETRY_CONFIG, ...config };
  let lastError: any;

  for (let attempt = 1; attempt <= finalConfig.maxAttempts; attempt++) {
    try {
      return await operation();
    } catch (error) {
      lastError = error;

      // 如果是最后一次尝试，直接抛出错误
      if (attempt === finalConfig.maxAttempts) {
        break;
      }

      // 检查是否应该重试
      if (finalConfig.retryCondition && !finalConfig.retryCondition(error)) {
        break;
      }

      // 计算延迟时间（指数退避）
      const delay = Math.min(
        finalConfig.baseDelay * Math.pow(finalConfig.backoffFactor, attempt - 1),
        finalConfig.maxDelay
      );

      console.warn(`操作失败，${delay}ms后重试 (尝试 ${attempt}/${finalConfig.maxAttempts}):`, error instanceof Error ? error.message : String(error));
      
      // 等待延迟
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }

  throw lastError;
}

/**
 * 任务轮询配置
 */
export interface PollConfig {
  maxWaitTime: number;
  pollInterval: number;
  onProgress?: (status: TaskStatusResponse) => void;
  onError?: (error: any) => void;
  shouldContinue?: (status: TaskStatusResponse) => boolean;
}

/**
 * 默认轮询配置
 */
export const DEFAULT_POLL_CONFIG: PollConfig = {
  maxWaitTime: 300000, // 5分钟
  pollInterval: 2000,  // 2秒
  shouldContinue: (status) => {
    return status.status === TaskStatus.PENDING || status.status === TaskStatus.RUNNING;
  },
};

/**
 * 通用任务轮询函数
 */
export async function pollTaskStatus<T extends TaskStatusResponse>(
  taskId: string,
  statusChecker: (taskId: string) => Promise<T>,
  config: Partial<PollConfig> = {}
): Promise<T> {
  const finalConfig = { ...DEFAULT_POLL_CONFIG, ...config };
  const startTime = Date.now();

  while (Date.now() - startTime < finalConfig.maxWaitTime) {
    try {
      const status = await statusChecker(taskId);

      // 调用进度回调
      if (finalConfig.onProgress) {
        finalConfig.onProgress(status);
      }

      // 检查任务是否完成
      if (status.status === TaskStatus.SUCCESS) {
        return status;
      }

      if (status.status === TaskStatus.FAILED) {
        throw new TaskFailedError(
          `任务失败: ${status.error || '未知错误'}`,
          taskId,
          status
        );
      }

      if (status.status === TaskStatus.CANCELLED) {
        throw new TaskFailedError(`任务已取消`, taskId, status);
      }

      // 检查是否应该继续轮询
      if (finalConfig.shouldContinue && !finalConfig.shouldContinue(status)) {
        throw new TaskFailedError(`任务状态异常: ${status.status}`, taskId, status);
      }

      // 等待下次轮询
      await new Promise(resolve => setTimeout(resolve, finalConfig.pollInterval));
    } catch (error) {
      if (error instanceof TaskFailedError) {
        throw error;
      }

      // 调用错误回调
      if (finalConfig.onError) {
        finalConfig.onError(error);
      }

      // 其他错误继续轮询
      console.warn(`轮询任务状态时出错: ${error}`);
      await new Promise(resolve => setTimeout(resolve, finalConfig.pollInterval));
    }
  }

  throw new TaskTimeoutError(`任务轮询超时`, taskId);
}

/**
 * 错误分类器
 */
export class ErrorClassifier {
  /**
   * 判断是否为网络错误
   */
  static isNetworkError(error: any): boolean {
    return error instanceof NetworkError ||
           error.code === 'NETWORK_ERROR' ||
           error.message?.includes('网络') ||
           error.message?.includes('连接') ||
           error.message?.includes('timeout') ||
           error.message?.includes('ECONNREFUSED') ||
           error.message?.includes('ENOTFOUND');
  }

  /**
   * 判断是否为验证错误
   */
  static isValidationError(error: any): boolean {
    return error instanceof ValidationError ||
           error.code === 'VALIDATION_ERROR' ||
           error.statusCode === 422 ||
           error.message?.includes('验证');
  }

  /**
   * 判断是否为超时错误
   */
  static isTimeoutError(error: any): boolean {
    return error instanceof TaskTimeoutError ||
           error.code === 'TASK_TIMEOUT' ||
           error.message?.includes('超时') ||
           error.message?.includes('timeout');
  }

  /**
   * 判断是否为任务失败错误
   */
  static isTaskFailedError(error: any): boolean {
    return error instanceof TaskFailedError ||
           error.code === 'TASK_FAILED';
  }

  /**
   * 判断是否可以重试
   */
  static isRetryable(error: any): boolean {
    return this.isNetworkError(error) || this.isTimeoutError(error);
  }

  /**
   * 获取错误类型
   */
  static getErrorType(error: any): string {
    if (this.isNetworkError(error)) return 'NETWORK_ERROR';
    if (this.isValidationError(error)) return 'VALIDATION_ERROR';
    if (this.isTimeoutError(error)) return 'TIMEOUT_ERROR';
    if (this.isTaskFailedError(error)) return 'TASK_FAILED_ERROR';
    return 'UNKNOWN_ERROR';
  }
}

/**
 * 日志级别
 */
export enum LogLevel {
  DEBUG = 0,
  INFO = 1,
  WARN = 2,
  ERROR = 3,
}

/**
 * 简单日志记录器
 */
export class Logger {
  private static level: LogLevel = LogLevel.INFO;

  static setLevel(level: LogLevel): void {
    this.level = level;
  }

  static debug(message: string, ...args: any[]): void {
    if (this.level <= LogLevel.DEBUG) {
      console.debug(`[DEBUG] ${new Date().toISOString()} ${message}`, ...args);
    }
  }

  static info(message: string, ...args: any[]): void {
    if (this.level <= LogLevel.INFO) {
      console.info(`[INFO] ${new Date().toISOString()} ${message}`, ...args);
    }
  }

  static warn(message: string, ...args: any[]): void {
    if (this.level <= LogLevel.WARN) {
      console.warn(`[WARN] ${new Date().toISOString()} ${message}`, ...args);
    }
  }

  static error(message: string, ...args: any[]): void {
    if (this.level <= LogLevel.ERROR) {
      console.error(`[ERROR] ${new Date().toISOString()} ${message}`, ...args);
    }
  }
}

/**
 * 性能监控器
 */
export class PerformanceMonitor {
  private static timers: Map<string, number> = new Map();

  /**
   * 开始计时
   */
  static start(name: string): void {
    this.timers.set(name, Date.now());
  }

  /**
   * 结束计时并返回耗时
   */
  static end(name: string): number {
    const startTime = this.timers.get(name);
    if (!startTime) {
      Logger.warn(`计时器 ${name} 未找到`);
      return 0;
    }

    const duration = Date.now() - startTime;
    this.timers.delete(name);
    
    Logger.debug(`${name} 耗时: ${duration}ms`);
    return duration;
  }

  /**
   * 测量函数执行时间
   */
  static async measure<T>(name: string, fn: () => Promise<T>): Promise<T> {
    this.start(name);
    try {
      const result = await fn();
      this.end(name);
      return result;
    } catch (error) {
      this.end(name);
      throw error;
    }
  }
}

/**
 * 文件大小格式化
 */
export function formatFileSize(bytes: number): string {
  if (bytes === 0) return '0 Bytes';

  const k = 1024;
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));

  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}

/**
 * 时间格式化
 */
export function formatDuration(ms: number): string {
  if (ms < 1000) return `${ms}ms`;
  if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
  if (ms < 3600000) return `${(ms / 60000).toFixed(1)}m`;
  return `${(ms / 3600000).toFixed(1)}h`;
}

/**
 * 任务状态中文映射
 */
export const TASK_STATUS_LABELS: Record<TaskStatus, string> = {
  [TaskStatus.PENDING]: '等待中',
  [TaskStatus.RUNNING]: '运行中',
  [TaskStatus.SUCCESS]: '成功',
  [TaskStatus.FAILED]: '失败',
  [TaskStatus.CANCELLED]: '已取消',
};

/**
 * 获取任务状态标签
 */
export function getTaskStatusLabel(status: TaskStatus): string {
  return TASK_STATUS_LABELS[status] || '未知';
}

/**
 * 验证文件类型
 */
export function validateFileType(file: File, allowedTypes: string[]): boolean {
  return allowedTypes.some(type => {
    if (type.includes('*')) {
      const baseType = type.split('/')[0];
      return file.type.startsWith(baseType);
    }
    return file.type === type;
  });
}

/**
 * 验证文件大小
 */
export function validateFileSize(file: File, maxSizeBytes: number): boolean {
  return file.size <= maxSizeBytes;
}

// ==================== 性能优化功能 ====================

/**
 * 缓存项接口
 */
interface CacheItem<T> {
  data: T;
  timestamp: number;
  ttl: number;
}

/**
 * 内存缓存管理器
 */
export class MemoryCache {
  private cache = new Map<string, CacheItem<any>>();
  private maxSize: number;
  private defaultTTL: number;

  constructor(maxSize = 1000, defaultTTL = 5 * 60 * 1000) { // 默认5分钟TTL
    this.maxSize = maxSize;
    this.defaultTTL = defaultTTL;
  }

  /**
   * 设置缓存
   */
  set<T>(key: string, data: T, ttl?: number): void {
    // 如果缓存已满，删除最旧的项
    if (this.cache.size >= this.maxSize) {
      const oldestKey = this.cache.keys().next().value;
      if (oldestKey) {
        this.cache.delete(oldestKey);
      }
    }

    this.cache.set(key, {
      data,
      timestamp: Date.now(),
      ttl: ttl || this.defaultTTL,
    });
  }

  /**
   * 获取缓存
   */
  get<T>(key: string): T | null {
    const item = this.cache.get(key);
    if (!item) return null;

    const now = Date.now();
    if (now - item.timestamp > item.ttl) {
      this.cache.delete(key);
      return null;
    }

    return item.data;
  }

  /**
   * 删除缓存
   */
  delete(key: string): boolean {
    return this.cache.delete(key);
  }

  /**
   * 清空缓存
   */
  clear(): void {
    this.cache.clear();
  }

  /**
   * 获取缓存统计信息
   */
  getStats(): { size: number; maxSize: number; hitRate?: number } {
    return {
      size: this.cache.size,
      maxSize: this.maxSize,
    };
  }

  /**
   * 清理过期缓存
   */
  cleanup(): void {
    const now = Date.now();
    for (const [key, item] of this.cache.entries()) {
      if (now - item.timestamp > item.ttl) {
        this.cache.delete(key);
      }
    }
  }
}

/**
 * 全局缓存实例
 */
export const globalCache = new MemoryCache();

/**
 * 缓存装饰器函数
 */
export function withCache<T extends any[], R>(
  fn: (...args: T) => Promise<R>,
  keyGenerator: (...args: T) => string,
  ttl?: number
): (...args: T) => Promise<R> {
  return async (...args: T): Promise<R> => {
    const key = keyGenerator(...args);
    const cached = globalCache.get<R>(key);

    if (cached !== null) {
      Logger.debug(`缓存命中: ${key}`);
      return cached;
    }

    Logger.debug(`缓存未命中，执行函数: ${key}`);
    const result = await fn(...args);
    globalCache.set(key, result, ttl);
    return result;
  };
}

/**
 * 并发控制器
 */
export class ConcurrencyController {
  private running = 0;
  private queue: Array<() => void> = [];

  constructor(private maxConcurrency: number) {}

  /**
   * 执行任务
   */
  async execute<T>(task: () => Promise<T>): Promise<T> {
    return new Promise<T>((resolve, reject) => {
      const executeTask = async () => {
        this.running++;
        try {
          const result = await task();
          resolve(result);
        } catch (error) {
          reject(error);
        } finally {
          this.running--;
          this.processQueue();
        }
      };

      if (this.running < this.maxConcurrency) {
        executeTask();
      } else {
        this.queue.push(executeTask);
      }
    });
  }

  private processQueue(): void {
    if (this.queue.length > 0 && this.running < this.maxConcurrency) {
      const nextTask = this.queue.shift();
      if (nextTask) {
        nextTask();
      }
    }
  }

  /**
   * 获取状态
   */
  getStatus(): { running: number; queued: number; maxConcurrency: number } {
    return {
      running: this.running,
      queued: this.queue.length,
      maxConcurrency: this.maxConcurrency,
    };
  }
}

/**
 * 全局并发控制器
 */
export const globalConcurrencyController = new ConcurrencyController(5);

/**
 * 防抖函数
 */
export function debounce<T extends any[]>(
  fn: (...args: T) => void,
  delay: number
): (...args: T) => void {
  let timeoutId: NodeJS.Timeout;

  return (...args: T) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => fn(...args), delay);
  };
}

/**
 * 节流函数
 */
export function throttle<T extends any[]>(
  fn: (...args: T) => void,
  delay: number
): (...args: T) => void {
  let lastCall = 0;

  return (...args: T) => {
    const now = Date.now();
    if (now - lastCall >= delay) {
      lastCall = now;
      fn(...args);
    }
  };
}
