import { Injectable, Logger } from '@nestjs/common';
import { Settlement, Order, Merchant } from '@prisma/client';
import { PrismaService } from '../../config/database';

interface SettlementData {
  id: string;
  merchantId: string;
  periodStart: Date;
  periodEnd: Date;
  totalAmount: number;
  status: 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED';
  createdAt: Date;
  updatedAt: Date;
}

interface FeeData {
  feeType: string;
  amount: number;
  description: string;
  merchantId: string;
  createdAt: Date;
}

interface OptimizationResult {
  settlementId: string;
  merchantId: string;
  originalAmount: number;
  optimizedAmount: number;
  savings: number;
  optimizationRate: number;
  recommendations: {
    type: string;
    description: string;
    potentialSavings: number;
    priority: 'high' | 'medium' | 'low';
  }[];
  feeBreakdown: {
    originalFees: FeeData[];
    optimizedFees: FeeData[];
  };
  confidence: number;
}

@Injectable()
export class SettlementOptimizationService {
  private readonly logger = new Logger(SettlementOptimizationService.name);

  constructor(private readonly prisma: PrismaService) {}

  /**
   * 优化商户结算
   * @param settlementId 结算单ID
   * @param traceId 链路追踪ID
   * @returns 结算优化结果
   */
  async optimizeSettlement(settlementId: string, traceId: string): Promise<OptimizationResult> {
    this.logger.log(`开始优化结算: ${settlementId}`, { traceId, settlementId });

    try {
      // 获取结算单信息
      const settlement = await this.prisma.settlement.findUnique({
        where: { id: settlementId },
      });

      if (!settlement) {
        throw new Error(`结算单不存在: ${settlementId}`);
      }

      // 获取商户信息
      const merchant = await this.prisma.merchant.findUnique({
        where: { id: settlement.merchantId },
      });

      if (!merchant) {
        throw new Error(`商户不存在: ${settlement.merchantId}`);
      }

      // 获取结算周期内的订单数据
      const orders = await this.prisma.order.findMany({
        where: {
          merchantId: settlement.merchantId,
          createdAt: {
            gte: settlement.periodStart,
            lte: settlement.periodEnd,
          },
        },
      });

      // 获取结算周期内的费用数据
      const fees = await this.getFeeData(settlement.merchantId, settlement.periodStart, settlement.periodEnd);

      // 分析结算数据
      const analysis = this.analyzeSettlementData(settlement, orders, fees);

      // 生成优化建议
      const recommendations = this.generateOptimizationRecommendations(analysis, merchant);

      // 计算优化后的金额
      const optimizedAmount = this.calculateOptimizedAmount(settlement.totalAmount, recommendations);

      // 计算节省金额和优化率
      const savings = settlement.totalAmount - optimizedAmount;
      const optimizationRate = settlement.totalAmount > 0 ? (savings / settlement.totalAmount) * 100 : 0;

      // 生成优化后的费用明细
      const optimizedFees = this.generateOptimizedFees(fees, recommendations);

      // 计算置信度
      const confidence = this.calculateConfidence(recommendations);

      const result: OptimizationResult = {
        settlementId,
        merchantId: settlement.merchantId,
        originalAmount: settlement.totalAmount,
        optimizedAmount,
        savings,
        optimizationRate: Math.round(optimizationRate * 100) / 100,
        recommendations,
        feeBreakdown: {
          originalFees: fees,
          optimizedFees,
        },
        confidence,
      };

      this.logger.log(`结算优化完成: ${settlementId}, 节省: ${savings}, 优化率: ${optimizationRate}%`, { traceId, result });

      return result;
    } catch (error) {
      this.logger.error(`结算优化失败: ${error.message}`, { traceId, settlementId, error });
      throw error;
    }
  }

  /**
   * 批量优化商户结算
   * @param settlementIds 结算单ID列表
   * @param traceId 链路追踪ID
   * @returns 结算优化结果列表
   */
  async batchOptimizeSettlements(settlementIds: string[], traceId: string): Promise<OptimizationResult[]> {
    this.logger.log(`开始批量优化结算, 数量: ${settlementIds.length}`, { traceId });

    const results: OptimizationResult[] = [];

    for (const settlementId of settlementIds) {
      try {
        const result = await this.optimizeSettlement(settlementId, traceId);
        results.push(result);
      } catch (error) {
        this.logger.error(`批量优化结算失败: ${settlementId}, 错误: ${error.message}`, { traceId, settlementId });
      }
    }

    this.logger.log(`批量优化结算完成, 成功: ${results.length}/${settlementIds.length}`, { traceId });

    return results;
  }

  /**
   * 获取费用数据
   */
  private async getFeeData(merchantId: string, startDate: Date, endDate: Date): Promise<FeeData[]> {
    // 这里模拟获取费用数据
    // 实际项目中应该从数据库或API获取
    return [
      {
        feeType: 'platform_fee',
        amount: 100.00,
        description: '平台服务费',
        merchantId,
        createdAt: new Date(),
      },
      {
        feeType: 'transaction_fee',
        amount: 50.00,
        description: '交易手续费',
        merchantId,
        createdAt: new Date(),
      },
      {
        feeType: 'logistics_fee',
        amount: 80.00,
        description: '物流费用',
        merchantId,
        createdAt: new Date(),
      },
      {
        feeType: 'marketing_fee',
        amount: 30.00,
        description: '营销费用',
        merchantId,
        createdAt: new Date(),
      },
    ];
  }

  /**
   * 分析结算数据
   */
  private analyzeSettlementData(settlement: SettlementData, orders: Order[], fees: FeeData[]) {
    // 计算订单相关指标
    const orderCount = orders.length;
    const totalOrderAmount = orders.reduce((sum, order) => sum + order.totalAmount, 0);
    const averageOrderValue = orderCount > 0 ? totalOrderAmount / orderCount : 0;

    // 计算费用相关指标
    const totalFees = fees.reduce((sum, fee) => sum + fee.amount, 0);
    const feeToSalesRatio = totalOrderAmount > 0 ? (totalFees / totalOrderAmount) * 100 : 0;

    // 分析费用结构
    const feeStructure = fees.reduce((acc, fee) => {
      acc[fee.feeType] = (acc[fee.feeType] || 0) + fee.amount;
      return acc;
    }, {} as Record<string, number>);

    return {
      orderCount,
      totalOrderAmount,
      averageOrderValue,
      totalFees,
      feeToSalesRatio,
      feeStructure,
      settlementAmount: settlement.totalAmount,
    };
  }

  /**
   * 生成优化建议
   */
  private generateOptimizationRecommendations(analysis: any, merchant: Merchant) {
    const recommendations: OptimizationResult['recommendations'] = [];

    // 平台服务费优化
    if (analysis.feeStructure.platform_fee && analysis.feeStructure.platform_fee > 50) {
      recommendations.push({
        type: 'platform_fee',
        description: '建议升级商户等级，享受平台服务费折扣',
        potentialSavings: analysis.feeStructure.platform_fee * 0.2, // 假设可节省20%
        priority: 'high',
      });
    }

    // 交易手续费优化
    if (analysis.feeStructure.transaction_fee && analysis.feeStructure.transaction_fee > 30) {
      recommendations.push({
        type: 'transaction_fee',
        description: '建议优化支付方式，降低交易手续费',
        potentialSavings: analysis.feeStructure.transaction_fee * 0.15, // 假设可节省15%
        priority: 'medium',
      });
    }

    // 物流费用优化
    if (analysis.feeStructure.logistics_fee && analysis.feeStructure.logistics_fee > 60) {
      recommendations.push({
        type: 'logistics_fee',
        description: '建议与物流商协商折扣，优化物流方案',
        potentialSavings: analysis.feeStructure.logistics_fee * 0.25, // 假设可节省25%
        priority: 'high',
      });
    }

    // 营销费用优化
    if (analysis.feeStructure.marketing_fee && analysis.feeStructure.marketing_fee > 20) {
      recommendations.push({
        type: 'marketing_fee',
        description: '建议优化营销策略，提高营销ROI',
        potentialSavings: analysis.feeStructure.marketing_fee * 0.3, // 假设可节省30%
        priority: 'medium',
      });
    }

    // 订单量优化
    if (analysis.orderCount < 50) {
      recommendations.push({
        type: 'order_volume',
        description: '建议增加订单量，分摊固定成本',
        potentialSavings: analysis.totalFees * 0.1, // 假设可节省10%
        priority: 'low',
      });
    }

    // 平均订单价值优化
    if (analysis.averageOrderValue < 100) {
      recommendations.push({
        type: 'average_order_value',
        description: '建议提高平均订单价值，增加利润率',
        potentialSavings: analysis.totalFees * 0.05, // 假设可节省5%
        priority: 'low',
      });
    }

    return recommendations;
  }

  /**
   * 计算优化后的金额
   */
  private calculateOptimizedAmount(originalAmount: number, recommendations: OptimizationResult['recommendations']): number {
    const totalSavings = recommendations.reduce((sum, rec) => sum + rec.potentialSavings, 0);
    const optimizedAmount = originalAmount - totalSavings;
    return Math.max(0, optimizedAmount);
  }

  /**
   * 生成优化后的费用明细
   */
  private generateOptimizedFees(originalFees: FeeData[], recommendations: OptimizationResult['recommendations']): FeeData[] {
    const optimizedFees = [...originalFees];

    // 应用优化建议到费用明细
    recommendations.forEach(rec => {
      const feeIndex = optimizedFees.findIndex(fee => fee.feeType === rec.type);
      if (feeIndex !== -1) {
        optimizedFees[feeIndex] = {
          ...optimizedFees[feeIndex],
          amount: Math.max(0, optimizedFees[feeIndex].amount - rec.potentialSavings),
          description: `${optimizedFees[feeIndex].description} (优化后)`,
        };
      }
    });

    return optimizedFees;
  }

  /**
   * 计算置信度
   */
  private calculateConfidence(recommendations: OptimizationResult['recommendations']): number {
    // 基于建议数量和优先级计算置信度
    const highPriorityCount = recommendations.filter(r => r.priority === 'high').length;
    const mediumPriorityCount = recommendations.filter(r => r.priority === 'medium').length;

    const confidence = 70 + (highPriorityCount * 5) + (mediumPriorityCount * 3);
    return Math.min(95, confidence); // 最高95%
  }

  /**
   * 获取商户结算优化报告
   * @param merchantId 商户ID
   * @param period 时间周期（如：'monthly', 'quarterly', 'yearly'）
   * @param traceId 链路追踪ID
   * @returns 结算优化报告
   */
  async getSettlementOptimizationReport(merchantId: string, period: string, traceId: string) {
    this.logger.log(`获取商户结算优化报告: ${merchantId}, 周期: ${period}`, { traceId, merchantId, period });

    try {
      // 计算时间范围
      const endDate = new Date();
      let startDate = new Date();

      switch (period) {
        case 'monthly':
          startDate.setMonth(startDate.getMonth() - 1);
          break;
        case 'quarterly':
          startDate.setMonth(startDate.getMonth() - 3);
          break;
        case 'yearly':
          startDate.setFullYear(startDate.getFullYear() - 1);
          break;
        default:
          startDate.setMonth(startDate.getMonth() - 1);
      }

      // 获取时间范围内的结算单
      const settlements = await this.prisma.settlement.findMany({
        where: {
          merchantId,
          periodStart: {
            gte: startDate,
          },
          periodEnd: {
            lte: endDate,
          },
        },
      });

      // 批量优化结算单
      const settlementIds = settlements.map(s => s.id);
      const optimizationResults = await this.batchOptimizeSettlements(settlementIds, traceId);

      // 计算总体优化效果
      const totalOriginalAmount = optimizationResults.reduce((sum, result) => sum + result.originalAmount, 0);
      const totalOptimizedAmount = optimizationResults.reduce((sum, result) => sum + result.optimizedAmount, 0);
      const totalSavings = totalOriginalAmount - totalOptimizedAmount;
      const totalOptimizationRate = totalOriginalAmount > 0 ? (totalSavings / totalOriginalAmount) * 100 : 0;

      // 汇总建议
      const allRecommendations = optimizationResults.flatMap(result => result.recommendations);
      const recommendationCounts = allRecommendations.reduce((acc, rec) => {
        acc[rec.type] = (acc[rec.type] || 0) + 1;
        return acc;
      }, {} as Record<string, number>);

      const topRecommendations = Object.entries(recommendationCounts)
        .sort(([,a], [,b]) => b - a)
        .slice(0, 3)
        .map(([type, count]) => {
          const recommendation = allRecommendations.find(rec => rec.type === type);
          return {
            type,
            count,
            description: recommendation?.description || '',
            potentialSavings: recommendation?.potentialSavings || 0,
          };
        });

      const report = {
        merchantId,
        period,
        timeRange: {
          start: startDate,
          end: endDate,
        },
        totalOriginalAmount,
        totalOptimizedAmount,
        totalSavings,
        totalOptimizationRate: Math.round(totalOptimizationRate * 100) / 100,
        settlementCount: settlements.length,
        optimizationResults,
        topRecommendations,
      };

      this.logger.log(`获取商户结算优化报告完成: ${merchantId}`, { traceId, report });

      return report;
    } catch (error) {
      this.logger.error(`获取商户结算优化报告失败: ${error.message}`, { traceId, merchantId, period, error });
      throw error;
    }
  }
}
