/**
 * [BE-MID-001] 通用AI决策中间件
 * 提供通用的AI介入决策框架，支持多种业务场景
 * AI注意: 所有需要AI介入判断的业务必须通过此中间件
 * 复用: BatchOperationAIMiddleware (批量操作AI决策)
 */

import { NextFunction, Request, Response } from 'express';
import { logger } from '../../utils/logger';

export enum DecisionType {
  BATCH_OPERATION = 'BATCH_OPERATION',
  PRICING = 'PRICING',
  INVENTORY = 'INVENTORY',
  ORDER_FULFILLMENT = 'ORDER_FULFILLMENT',
  AFTER_SALES = 'AFTER_SALES',
  RISK_CONTROL = 'RISK_CONTROL',
  FREIGHT = 'FREIGHT',
  SUPPLIER = 'SUPPLIER',
  PROCUREMENT = 'PROCUREMENT',
  CUSTOM = 'CUSTOM',
}

export enum DecisionResult {
  AUTO_EXECUTE = 'AUTO_EXECUTE',
  PENDING_REVIEW = 'PENDING_REVIEW',
  HUMAN_ONLY = 'HUMAN_ONLY',
}

export enum RiskLevel {
  LOW = 'LOW',
  MEDIUM = 'MEDIUM',
  HIGH = 'HIGH',
  CRITICAL = 'CRITICAL',
}

export enum SubscriptionLevel {
  FREE = 'FREE',
  BASIC = 'BASIC',
  PROFESSIONAL = 'PROFESSIONAL',
  ENTERPRISE = 'ENTERPRISE',
}

interface DecisionConfig {
  decisionType: DecisionType;
  subscriptionLevel: SubscriptionLevel;
  autoExecuteConfidence: number;
  pendingReviewConfidence: number;
  allowedRiskLevels: RiskLevel[];
  maxAutoQuantity?: number;
  maxAutoBudget?: number;
  operationMeta?: Record<string, any>;
}

interface DecisionContext {
  tenantId: string;
  shopId?: string;
  operatorId: string;
  businessType: DecisionType;
  operationType: string;
  targetIds?: string[];
  targetData?: Record<string, any>;
  estimatedImpact?: {
    amount?: number;
    quantity?: number;
  };
  customParams?: Record<string, any>;
}

interface AIDecision {
  allowed: boolean;
  autoExecute: boolean;
  reason: string;
  confidence: number;
  riskLevel: RiskLevel;
  requiredAction: DecisionResult;
  subscriptionLevel: SubscriptionLevel;
  businessType: DecisionType;
  warnings: string[];
  metadata?: Record<string, any>;
  nextReviewAt?: Date;
  expiresAt?: Date;
}

declare global {
  namespace Express {
    interface Request {
      aiDecision?: AIDecision;
      decisionContext?: DecisionContext;
    }
  }
}

const SUBSCRIPTION_CONFIG: Record<SubscriptionLevel, {
  autoExecuteConfidence: number;
  pendingReviewConfidence: number;
  allowedRiskLevels: RiskLevel[];
  maxAutoQuantity: number;
  maxAutoBudget: number;
}> = {
  [SubscriptionLevel.FREE]: {
    autoExecuteConfidence: 0.95,
    pendingReviewConfidence: 0.8,
    allowedRiskLevels: [RiskLevel.LOW],
    maxAutoQuantity: 10,
    maxAutoBudget: 1000,
  },
  [SubscriptionLevel.BASIC]: {
    autoExecuteConfidence: 0.85,
    pendingReviewConfidence: 0.7,
    allowedRiskLevels: [RiskLevel.LOW, RiskLevel.MEDIUM],
    maxAutoQuantity: 50,
    maxAutoBudget: 10000,
  },
  [SubscriptionLevel.PROFESSIONAL]: {
    autoExecuteConfidence: 0.75,
    pendingReviewConfidence: 0.6,
    allowedRiskLevels: [RiskLevel.LOW, RiskLevel.MEDIUM, RiskLevel.HIGH],
    maxAutoQuantity: 200,
    maxAutoBudget: 50000,
  },
  [SubscriptionLevel.ENTERPRISE]: {
    autoExecuteConfidence: 0.6,
    pendingReviewConfidence: 0.5,
    allowedRiskLevels: [RiskLevel.LOW, RiskLevel.MEDIUM, RiskLevel.HIGH, RiskLevel.CRITICAL],
    maxAutoQuantity: 1000,
    maxAutoBudget: 500000,
  },
};

const BUSINESS_TYPE_LABELS: Record<DecisionType, string> = {
  [DecisionType.BATCH_OPERATION]: '批量操作',
  [DecisionType.PRICING]: '定价',
  [DecisionType.INVENTORY]: '库存',
  [DecisionType.ORDER_FULFILLMENT]: '订单履约',
  [DecisionType.AFTER_SALES]: '售后',
  [DecisionType.RISK_CONTROL]: '风控',
  [DecisionType.FREIGHT]: '运费',
  [DecisionType.SUPPLIER]: '供应商',
  [DecisionType.PROCUREMENT]: '采购',
  [DecisionType.CUSTOM]: '自定义',
};

const calculateRiskLevel = (
  businessType: DecisionType,
  operationType: string,
  context: DecisionContext
): RiskLevel => {
  const { targetIds, estimatedImpact, customParams } = context;
  const targetCount = targetIds?.length || 0;

  if (customParams?.riskLevel) {
    return customParams.riskLevel as RiskLevel;
  }

  if (businessType === DecisionType.AFTER_SALES) {
    if (customParams?.isMalicious || customParams?.repeated) return RiskLevel.CRITICAL;
    if (customParams?.amount > 1000 || customParams?.isHighValue) return RiskLevel.HIGH;
    if (customParams?.amount > 200) return RiskLevel.MEDIUM;
  }

  if (businessType === DecisionType.RISK_CONTROL) {
    if (customParams?.isHighRisk || customParams?.fraudScore > 0.8) return RiskLevel.CRITICAL;
    if (customParams?.fraudScore > 0.5) return RiskLevel.HIGH;
    if (customParams?.fraudScore > 0.3) return RiskLevel.MEDIUM;
  }

  if (estimatedImpact?.amount) {
    if (estimatedImpact.amount > 100000) return RiskLevel.CRITICAL;
    if (estimatedImpact.amount > 50000) return RiskLevel.HIGH;
    if (estimatedImpact.amount > 10000) return RiskLevel.MEDIUM;
  }

  if (targetCount > 500) return RiskLevel.CRITICAL;
  if (targetCount > 200) return RiskLevel.HIGH;
  if (targetCount > 100) return RiskLevel.MEDIUM;

  return RiskLevel.LOW;
};

const calculateConfidence = (
  businessType: DecisionType,
  operationType: string,
  context: DecisionContext,
  subscriptionLevel: SubscriptionLevel
): number => {
  let baseConfidence = 0.8;

  switch (businessType) {
    case DecisionType.BATCH_OPERATION:
      if (['BATCH_EDIT_PRICE', 'BATCH_EDIT_INVENTORY'].includes(operationType)) {
        baseConfidence = 0.95;
      } else if (['BATCH_LISTING', 'BATCH_DELIST'].includes(operationType)) {
        baseConfidence = 0.8;
      } else {
        baseConfidence = 0.7;
      }
      break;

    case DecisionType.PRICING:
      if (['AUTO_PRICE_ADJUST', 'COMPETITOR_MATCH'].includes(operationType)) {
        baseConfidence = 0.9;
      } else {
        baseConfidence = 0.75;
      }
      break;

    case DecisionType.INVENTORY:
      if (['STOCK_ADJUST', 'REPLENISH'].includes(operationType)) {
        baseConfidence = 0.9;
      } else {
        baseConfidence = 0.75;
      }
      break;

    case DecisionType.AFTER_SALES:
      if (context.customParams?.hasHistory && context.customParams?.historySuccessRate > 0.9) {
        baseConfidence = 0.95;
      } else if (context.customParams?.isSimpleCase) {
        baseConfidence = 0.85;
      } else {
        baseConfidence = 0.65;
      }
      break;

    case DecisionType.RISK_CONTROL:
      if (context.customParams?.fraudScore > 0.9 || context.customParams?.isObviousFraud) {
        baseConfidence = 0.98;
      } else if (context.customParams?.fraudScore > 0.7) {
        baseConfidence = 0.85;
      } else {
        baseConfidence = 0.6;
      }
      break;

    case DecisionType.ORDER_FULFILLMENT:
      if (['NORMAL_ORDER', 'STANDARD_SHIPPING'].includes(operationType)) {
        baseConfidence = 0.9;
      } else {
        baseConfidence = 0.7;
      }
      break;

    default:
      baseConfidence = 0.7;
  }

  const targetCount = context.targetIds?.length || 0;
  if (targetCount > 100) baseConfidence -= 0.15;
  else if (targetCount > 50) baseConfidence -= 0.1;
  else if (targetCount > 20) baseConfidence -= 0.05;

  const levelBonus: Record<SubscriptionLevel, number> = {
    [SubscriptionLevel.ENTERPRISE]: 0.1,
    [SubscriptionLevel.PROFESSIONAL]: 0.05,
    [SubscriptionLevel.BASIC]: 0,
    [SubscriptionLevel.FREE]: -0.15,
  };

  return Math.min(1, Math.max(0, baseConfidence + levelBonus[subscriptionLevel]));
};

const generateDecisionReason = (
  businessType: DecisionType,
  operationType: string,
  decision: AIDecision,
  context: DecisionContext
): string => {
  const targetCount = context.targetIds?.length || 0;
  const businessLabel = BUSINESS_TYPE_LABELS[businessType];

  switch (decision.requiredAction) {
    case DecisionResult.AUTO_EXECUTE:
      return `AI自动执行 ${businessLabel}：${operationType}，` +
        `置信度 ${(decision.confidence * 100).toFixed(1)}% >= ${(SUBSCRIPTION_CONFIG[decision.subscriptionLevel].autoExecuteConfidence * 100).toFixed(1)}%，` +
        `风险等级 ${decision.riskLevel} 在允许范围内，` +
        `影响 ${targetCount} 个目标`;

    case DecisionResult.PENDING_REVIEW:
      return `需要人工确认 ${businessLabel}：${operationType}，` +
        `置信度 ${(decision.confidence * 100).toFixed(1)}% < ${(SUBSCRIPTION_CONFIG[decision.subscriptionLevel].autoExecuteConfidence * 100).toFixed(1)}% ` +
        `或风险等级 ${decision.riskLevel} 不在允许范围内`;

    case DecisionResult.HUMAN_ONLY:
      return `${businessLabel} 操作 ${operationType} 仅支持人工处理，` +
        `不满足AI自动执行条件`;

    default:
      return `${businessLabel} 决策完成：${decision.reason}`;
  }
};

export const makeAIDecision = (context: DecisionContext): AIDecision => {
  const {
    tenantId,
    operatorId,
    businessType,
    operationType,
    targetIds,
    estimatedImpact,
    customParams,
  } = context;

  if (!tenantId || !operatorId || !businessType || !operationType) {
    throw new Error('缺少必要字段: tenantId, operatorId, businessType, operationType');
  }

  const subscriptionLevel = (customParams?.subscriptionLevel as SubscriptionLevel) || SubscriptionLevel.FREE;
  const config = SUBSCRIPTION_CONFIG[subscriptionLevel];

  const riskLevel = calculateRiskLevel(businessType, operationType, context);
  const confidence = calculateConfidence(businessType, operationType, context, subscriptionLevel);

  const warnings: string[] = [];
  const targetCount = targetIds?.length || 0;

  if (config.maxAutoQuantity && targetCount > config.maxAutoQuantity) {
    warnings.push(`操作数量 ${targetCount} 超过最大自动执行数量 ${config.maxAutoQuantity}`);
  }

  if (config.maxAutoBudget && estimatedImpact?.amount && estimatedImpact.amount > config.maxAutoBudget) {
    warnings.push(`操作金额 ${estimatedImpact.amount} 超过最大自动执行预算 ${config.maxAutoBudget}`);
  }

  if (!config.allowedRiskLevels.includes(riskLevel)) {
    warnings.push(`风险等级 ${riskLevel} 不在允许范围内`);
  }

  let requiredAction: DecisionResult;
  let autoExecute = false;

  if (confidence >= config.autoExecuteConfidence && config.allowedRiskLevels.includes(riskLevel)) {
    requiredAction = DecisionResult.AUTO_EXECUTE;
    autoExecute = true;
  } else if (confidence >= config.pendingReviewConfidence) {
    requiredAction = DecisionResult.PENDING_REVIEW;
  } else {
    requiredAction = DecisionResult.PENDING_REVIEW;
  }

  if (customParams?.requireHumanApproval) {
    requiredAction = DecisionResult.PENDING_REVIEW;
    autoExecute = false;
    warnings.push('业务规则要求人工确认');
  }

  const decision: AIDecision = {
    allowed: true,
    autoExecute,
    reason: '',
    confidence,
    riskLevel,
    requiredAction,
    subscriptionLevel,
    businessType,
    warnings,
    metadata: {
      operationType,
      targetCount,
      estimatedImpact,
      configSnapshot: {
        autoExecuteConfidence: config.autoExecuteConfidence,
        pendingReviewConfidence: config.pendingReviewConfidence,
        allowedRiskLevels: config.allowedRiskLevels,
      },
    },
  };

  decision.reason = generateDecisionReason(businessType, operationType, decision, context);
  decision.expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000);
  decision.nextReviewAt = requiredAction === DecisionResult.PENDING_REVIEW
    ? new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
    : undefined;

  logger.info(`[AIDecisionMiddleware] Decision made: ${JSON.stringify({
    businessType,
    operationType,
    requiredAction,
    confidence,
    riskLevel,
    targetCount,
  })}`);

  return decision;
};

export const validateAIDecision = (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  try {
    const context: DecisionContext = {
      tenantId: req.body.tenantId,
      shopId: req.body.shopId,
      operatorId: req.body.operatorId,
      businessType: req.body.businessType,
      operationType: req.body.operationType,
      targetIds: req.body.targetIds,
      targetData: req.body.targetData,
      estimatedImpact: req.body.estimatedImpact,
      customParams: req.body.customParams,
    };

    const decision = makeAIDecision(context);

    req.aiDecision = decision;
    req.decisionContext = context;

    logger.info(`[AIDecisionMiddleware] Validation result: ${JSON.stringify(req.aiDecision)}`);

    next();
  } catch (error) {
    logger.error('[AIDecisionMiddleware] Validation error:', error);
    return res.status(500).json({
      success: false,
      error: 'AI_DECISION_ERROR',
      message: 'AI决策失败',
      details: error instanceof Error ? error.message : 'Unknown error',
    });
  }
};

export const requireAIDecision = (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  const decision = req.aiDecision;

  if (!decision) {
    return res.status(400).json({
      success: false,
      error: 'MISSING_DECISION',
      message: '缺少AI决策信息，请先通过 validateAIDecision 中间件',
    });
  }

  if (decision.requiredAction === DecisionResult.AUTO_EXECUTE) {
    return res.status(200).json({
      success: true,
      autoExecute: true,
      message: decision.reason,
      confidence: decision.confidence,
      riskLevel: decision.riskLevel,
      expiresAt: decision.expiresAt,
    });
  }

  if (decision.requiredAction === DecisionResult.HUMAN_ONLY) {
    return res.status(403).json({
      success: false,
      error: 'AI_NOT_ALLOWED',
      message: decision.reason,
      subscriptionLevel: decision.subscriptionLevel,
      riskLevel: decision.riskLevel,
    });
  }

  next();
};

export const checkSubscriptionLevel = (
  requiredLevel: SubscriptionLevel
) => {
  const levelOrder: Record<SubscriptionLevel, number> = {
    [SubscriptionLevel.FREE]: 0,
    [SubscriptionLevel.BASIC]: 1,
    [SubscriptionLevel.PROFESSIONAL]: 2,
    [SubscriptionLevel.ENTERPRISE]: 3,
  };

  return (req: Request, res: Response, next: NextFunction) => {
    const userLevel = req.aiDecision?.subscriptionLevel || SubscriptionLevel.FREE;

    if ((levelOrder[userLevel] || 0) < (levelOrder[requiredLevel] || 0)) {
      return res.status(403).json({
        success: false,
        error: 'INSUFFICIENT_SUBSCRIPTION',
        message: `此操作需要 ${requiredLevel} 级别或更高订阅`,
        currentLevel: userLevel,
        requiredLevel,
      });
    }

    next();
  };
};

export const getAIDecisionSummary = (decision: AIDecision): {
  canAutoExecute: boolean;
  needsConfirmation: boolean;
  riskLabel: string;
  confidencePercent: string;
  warnings: string[];
} => {
  return {
    canAutoExecute: decision.autoExecute,
    needsConfirmation: decision.requiredAction === DecisionResult.PENDING_REVIEW,
    riskLabel: decision.riskLevel,
    confidencePercent: `${(decision.confidence * 100).toFixed(1)}%`,
    warnings: decision.warnings,
  };
};

export { SUBSCRIPTION_CONFIG, BUSINESS_TYPE_LABELS };
export type { DecisionContext, AIDecision, DecisionConfig };
