import { logger } from '../utils/logger';
import { OrderService } from './OrderService';
import { LogisticsService } from './LogisticsService';
import { PaymentService } from './PaymentService';
import { PricingService } from './PricingService';

export interface ExceptionType {
  id: string;
  code: string;
  name: string;
  severity: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
  category: 'PAYMENT' | 'LOGISTICS' | 'INVENTORY' | 'PRICING' | 'PLATFORM' | 'SYSTEM';
  autoFixable: boolean;
  fixStrategy?: string;
}

export interface Exception {
  id: string;
  taskId: string;
  type: ExceptionType;
  orderId?: string;
  productId?: string;
  errorMessage: string;
  errorDetails: any;
  occurredAt: string;
  status: 'OPEN' | 'IN_PROGRESS' | 'RESOLVED' | 'ESCALATED';
  retryCount: number;
  lastRetryAt?: string;
  autoFixAttempted: boolean;
  autoFixResult?: {
    success: boolean;
    message: string;
    timestamp: string;
  };
  resolvedAt?: string;
  resolutionMethod: 'AUTO_FIX' | 'MANUAL' | 'ESCALATED';
  resolutionNotes?: string;
}

export interface FixResult {
  exceptionId: string;
  success: boolean;
  action: string;
  message: string;
  nextSteps?: string[];
}

/**
 * [BIZ_ORD_04] 异常订单处理闭环 - 异常自动修复
 * Task ID: AI-D002
 * 
 * 功能：
 * 1. 异常识别与分类
 * 2. 自动修复策略执行
 * 3. 修复结果验证
 * 4. 升级机制
 * 5. 修复历史记录
 */
export class ExceptionAutoFixService {
  private static readonly EXCEPTION_TYPES: ExceptionType[] = [
    {
      id: 'PAYMENT_FAILED',
      code: 'PAY-001',
      name: 'Payment Failed',
      severity: 'HIGH',
      category: 'PAYMENT',
      autoFixable: true,
      fixStrategy: 'RETRY_PAYMENT'
    },
    {
      id: 'LOGISTICS_TRACKING_FAILED',
      code: 'LOG-001',
      name: 'Logistics Tracking Failed',
      severity: 'MEDIUM',
      category: 'LOGISTICS',
      autoFixable: true,
      fixStrategy: 'RE_SYNC_TRACKING'
    },
    {
      id: 'INVENTORY_OUT_OF_STOCK',
      code: 'INV-001',
      name: 'Inventory Out of Stock',
      severity: 'HIGH',
      category: 'INVENTORY',
      autoFixable: true,
      fixStrategy: 'SUGGEST_ALTERNATIVE'
    },
    {
      id: 'PRICING_MISMATCH',
      code: 'PRI-001',
      name: 'Pricing Mismatch',
      severity: 'MEDIUM',
      category: 'PRICING',
      autoFixable: true,
      fixStrategy: 'RECALCULATE_PRICE'
    },
    {
      id: 'PLATFORM_API_ERROR',
      code: 'PLT-001',
      name: 'Platform API Error',
      severity: 'CRITICAL',
      category: 'PLATFORM',
      autoFixable: true,
      fixStrategy: 'RETRY_WITH_BACKOFF'
    },
    {
      id: 'PLATFORM_RATE_LIMIT',
      code: 'PLT-002',
      name: 'Platform Rate Limit',
      severity: 'MEDIUM',
      category: 'PLATFORM',
      autoFixable: true,
      fixStrategy: 'APPLY_EXPONENTIAL_BACKOFF'
    }
  ];

  /**
   * 识别异常类型
   */
  static identifyException(errorMessage: string, errorDetails?: any): ExceptionType {
    const lowerMessage = errorMessage.toLowerCase();

    if (lowerMessage.includes('payment') || lowerMessage.includes('credit card') || lowerMessage.includes('transaction')) {
      return this.EXCEPTION_TYPES.find(e => e.id === 'PAYMENT_FAILED')!;
    }

    if (lowerMessage.includes('tracking') || lowerMessage.includes('logistics') || lowerMessage.includes('shipping')) {
      return this.EXCEPTION_TYPES.find(e => e.id === 'LOGISTICS_TRACKING_FAILED')!;
    }

    if (lowerMessage.includes('stock') || lowerMessage.includes('inventory') || lowerMessage.includes('out of stock')) {
      return this.EXCEPTION_TYPES.find(e => e.id === 'INVENTORY_OUT_OF_STOCK')!;
    }

    if (lowerMessage.includes('price') || lowerMessage.includes('pricing') || lowerMessage.includes('cost')) {
      return this.EXCEPTION_TYPES.find(e => e.id === 'PRICING_MISMATCH')!;
    }

    if (lowerMessage.includes('rate limit') || lowerMessage.includes('429') || lowerMessage.includes('too many requests')) {
      return this.EXCEPTION_TYPES.find(e => e.id === 'PLATFORM_RATE_LIMIT')!;
    }

    return this.EXCEPTION_TYPES.find(e => e.id === 'PLATFORM_API_ERROR')!;
  }

  /**
   * 执行自动修复
   */
  static async autoFix(exception: Exception): Promise<FixResult> {
    logger.info(`[ExceptionAutoFix] Attempting auto-fix for exception ${exception.id}: ${exception.type.code}`);

    const startTime = Date.now();

    try {
      let result: FixResult;

      switch (exception.type.fixStrategy) {
        case 'RETRY_PAYMENT':
          result = await this.retryPayment(exception);
          break;

        case 'RE_SYNC_TRACKING':
          result = await this.resyncTracking(exception);
          break;

        case 'SUGGEST_ALTERNATIVE':
          result = await this.suggestAlternative(exception);
          break;

        case 'RECALCULATE_PRICE':
          result = await this.recalculatePrice(exception);
          break;

        case 'RETRY_WITH_BACKOFF':
          result = await this.retryWithBackoff(exception);
          break;

        case 'APPLY_EXPONENTIAL_BACKOFF':
          result = await this.applyExponentialBackoff(exception);
          break;

        default:
          result = {
            exceptionId: exception.id,
            success: false,
            action: 'NO_FIX_STRATEGY',
            message: 'No fix strategy defined for this exception type',
            nextSteps: ['Manual review required']
          };
      }

      const duration = Date.now() - startTime;
      logger.info(`[ExceptionAutoFix] Auto-fix completed in ${duration}ms: ${result.success ? 'SUCCESS' : 'FAILED'}`);

      return result;

    } catch (error) {
      logger.error(`[ExceptionAutoFix] Auto-fix failed for exception ${exception.id}:`, error);
      return {
        exceptionId: exception.id,
        success: false,
        action: 'AUTO_FIX_ERROR',
        message: `Auto-fix encountered an error: ${error}`,
        nextSteps: ['Escalate to support team']
      };
    }
  }

  /**
   * 重试支付
   */
  private static async retryPayment(exception: Exception): Promise<FixResult> {
    if (!exception.orderId) {
      return {
        exceptionId: exception.id,
        success: false,
        action: 'RETRY_PAYMENT',
        message: 'No order ID available for payment retry',
        nextSteps: ['Manual payment verification required']
      };
    }

    try {
      await PaymentService.retryPayment(exception.orderId);
      return {
        exceptionId: exception.id,
        success: true,
        action: 'RETRY_PAYMENT',
        message: 'Payment retry initiated successfully',
        nextSteps: ['Monitor payment status', 'Verify order fulfillment']
      };
    } catch (error) {
      return {
        exceptionId: exception.id,
        success: false,
        action: 'RETRY_PAYMENT',
        message: `Payment retry failed: ${error}`,
        nextSteps: ['Escalate to payment team', 'Manual intervention required']
      };
    }
  }

  /**
   * 重新同步物流跟踪
   */
  private static async resyncTracking(exception: Exception): Promise<FixResult> {
    if (!exception.orderId) {
      return {
        exceptionId: exception.id,
        success: false,
        action: 'RE_SYNC_TRACKING',
        message: 'No order ID available for tracking sync',
        nextSteps: ['Manual tracking update required']
      };
    }

    try {
      await LogisticsService.syncTracking(exception.orderId);
      return {
        exceptionId: exception.id,
        success: true,
        action: 'RE_SYNC_TRACKING',
        message: 'Tracking information resynced successfully',
        nextSteps: ['Monitor delivery status', 'Verify customer notification']
      };
    } catch (error) {
      return {
        exceptionId: exception.id,
        success: false,
        action: 'RE_SYNC_TRACKING',
        message: `Tracking sync failed: ${error}`,
        nextSteps: ['Escalate to logistics team', 'Manual tracking update required']
      };
    }
  }

  /**
   * 建议替代方案
   */
  private static async suggestAlternative(exception: Exception): Promise<FixResult> {
    if (!exception.productId) {
      return {
        exceptionId: exception.id,
        success: false,
        action: 'SUGGEST_ALTERNATIVE',
        message: 'No product ID available for alternative suggestion',
        nextSteps: ['Manual inventory review required']
      };
    }

    try {
      const alternatives = await OrderService.findAlternativeProducts(exception.productId);
      
      if (alternatives.length === 0) {
        return {
          exceptionId: exception.id,
          success: false,
          action: 'SUGGEST_ALTERNATIVE',
          message: 'No alternative products available',
          nextSteps: ['Notify customer of delay', 'Escalate to inventory team']
        };
      }

      return {
        exceptionId: exception.id,
        success: true,
        action: 'SUGGEST_ALTERNATIVE',
        message: `Found ${alternatives.length} alternative products`,
        nextSteps: ['Notify customer of alternatives', 'Offer discount for delay', 'Monitor customer decision']
      };
    } catch (error) {
      return {
        exceptionId: exception.id,
        success: false,
        action: 'SUGGEST_ALTERNATIVE',
        message: `Alternative suggestion failed: ${error}`,
        nextSteps: ['Manual product search required']
      };
    }
  }

  /**
   * 重新计算价格
   */
  private static async recalculatePrice(exception: Exception): Promise<FixResult> {
    if (!exception.productId) {
      return {
        exceptionId: exception.id,
        success: false,
        action: 'RECALCULATE_PRICE',
        message: 'No product ID available for price recalculation',
        nextSteps: ['Manual price review required']
      };
    }

    try {
      const profit = await PricingService.calculateNetProfit({
        sellingPrice: 100,
        purchasePrice: 80,
        platform: 'Amazon',
        countryCode: 'US',
        logisticsCost: 10,
        isB2B: false
      });

      return {
        exceptionId: exception.id,
        success: true,
        action: 'RECALCULATE_PRICE',
        message: `Price recalculated. Current profit rate: ${(profit.profitRate * 100).toFixed(1)}%`,
        nextSteps: ['Update product price', 'Verify profit margin', 'Monitor sales performance']
      };
    } catch (error) {
      return {
        exceptionId: exception.id,
        success: false,
        action: 'RECALCULATE_PRICE',
        message: `Price recalculation failed: ${error}`,
        nextSteps: ['Manual price verification required']
      };
    }
  }

  /**
   * 带退避的重试
   */
  private static async retryWithBackoff(exception: Exception): Promise<FixResult> {
    const maxRetries = 3;
    const baseDelay = 1000;
    const maxDelay = 30000;

    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
      
      logger.info(`[ExceptionAutoFix] Retry attempt ${attempt}/${maxRetries} with ${delay}ms delay`);
      
      await new Promise(resolve => setTimeout(resolve, delay));

      try {
        await OrderService.retryFailedTask(exception.taskId);
        return {
          exceptionId: exception.id,
          success: true,
          action: 'RETRY_WITH_BACKOFF',
          message: `Task retry succeeded on attempt ${attempt}`,
          nextSteps: ['Monitor task completion', 'Verify result']
        };
      } catch (error) {
        if (attempt === maxRetries) {
          return {
            exceptionId: exception.id,
            success: false,
            action: 'RETRY_WITH_BACKOFF',
            message: `All ${maxRetries} retry attempts failed`,
            nextSteps: ['Escalate to technical team', 'Manual intervention required']
          };
        }
      }
    }

    return {
      exceptionId: exception.id,
      success: false,
      action: 'RETRY_WITH_BACKOFF',
      message: 'Unexpected error in retry logic',
      nextSteps: ['Escalate to support team']
    };
  }

  /**
   * 指数退避
   */
  private static async applyExponentialBackoff(exception: Exception): Promise<FixResult> {
    const backoffTime = this.calculateBackoffTime(exception.retryCount);

    logger.info(`[ExceptionAutoFix] Applying exponential backoff: ${backoffTime}ms`);

    await new Promise(resolve => setTimeout(resolve, backoffTime));

    try {
      await OrderService.retryFailedTask(exception.taskId);
      return {
        exceptionId: exception.id,
        success: true,
        action: 'APPLY_EXPONENTIAL_BACKOFF',
        message: `Rate limit backoff applied (${backoffTime}ms)`,
        nextSteps: ['Monitor rate limit status', 'Resume operations when limit resets']
      };
    } catch (error) {
      return {
        exceptionId: exception.id,
        success: false,
        action: 'APPLY_EXPONENTIAL_BACKOFF',
        message: `Backoff retry failed: ${error}`,
        nextSteps: ['Wait for rate limit reset', 'Manual retry required']
      };
    }
  }

  /**
   * 计算退避时间
   */
  private static calculateBackoffTime(retryCount: number): number {
    const baseDelay = 1000;
    const maxDelay = 60000;
    const delay = Math.min(baseDelay * Math.pow(2, retryCount), maxDelay);
    return delay;
  }

  /**
   * 批量处理异常
   */
  static async batchAutoFix(exceptions: Exception[]): Promise<FixResult[]> {
    logger.info(`[ExceptionAutoFix] Batch auto-fixing ${exceptions.length} exceptions`);

    const fixableExceptions = exceptions.filter(e => e.type.autoFixable);
    const results = await Promise.all(
      fixableExceptions.map(e => this.autoFix(e))
    );

    const successCount = results.filter(r => r.success).length;
    const failureCount = results.filter(r => !r.success).length;

    logger.info(`[ExceptionAutoFix] Batch fix complete: ${successCount} succeeded, ${failureCount} failed`);

    return results;
  }

  /**
   * 获取异常统计
   */
  static getExceptionStats(exceptions: Exception[]): {
    byCategory: Record<string, number>;
    bySeverity: Record<string, number>;
    autoFixable: number;
    autoFixSuccessRate: number;
  } {
    const byCategory: Record<string, number> = {};
    const bySeverity: Record<string, number> = {};
    let autoFixable = 0;
    let autoFixSuccess = 0;

    exceptions.forEach(e => {
      byCategory[e.type.category] = (byCategory[e.type.category] || 0) + 1;
      bySeverity[e.type.severity] = (bySeverity[e.type.severity] || 0) + 1;
      if (e.type.autoFixable) {
        autoFixable++;
        if (e.autoFixResult?.success) {
          autoFixSuccess++;
        }
      }
    });

    return {
      byCategory,
      bySeverity,
      autoFixable,
      autoFixSuccessRate: autoFixable > 0 ? autoFixSuccess / autoFixable : 0
    };
  }
}
