import db from '../../config/database';
import { logger } from '../../utils/logger';
import { AuditService } from '../../services/utils/AuditService';

export interface AbandonedCartInfo {
  userId: string;
  cartId: string;
  productId: string;
  abandonedAt: Date;
  recoveryEmailSent?: boolean;
}

export interface AdPlan {
  id: string;
  tenantId: string;
  name: string;
  budget: number;
  startDate: Date;
  endDate: Date;
  platforms: string[];
  targetAudience: Record<string, any>;
  status: 'DRAFT' | 'ACTIVE' | 'PAUSED' | 'COMPLETED';
  roi: number;
  createdAt: Date;
  updatedAt: Date;
}

export interface CreateAdPlanInput {
  tenantId: string;
  name: string;
  budget: number;
  startDate: Date;
  endDate: Date;
  platforms: string[];
  targetAudience: Record<string, any>;
  businessType: 'TOC' | 'TOB';
}

export interface AdPerformance {
  planId: string;
  platform: string;
  impressions: number;
  clicks: number;
  conversions: number;
  spend: number;
  revenue: number;
  roi: number;
  date: Date;
}

/**
 * MarketingService: 广告计划与营销闭环
 * 实现广告计划制定、跨平台投放、效果分析与优化
 */
export class MarketingService {
  private static TABLE_CART = 'cf_cart';
  private static TABLE_AD_PLAN = 'cf_ad_plan';
  private static TABLE_AD_PERFORMANCE = 'cf_ad_performance';

  /**
   * 初始化表结构
   */
  static async initializeTables(): Promise<void> {
    if (!(await db.schema.hasTable(this.TABLE_AD_PLAN))) {
      await db.schema.createTable(this.TABLE_AD_PLAN, (table) => {
        table.string('id').primary();
        table.string('tenant_id').notNullable();
        table.string('name').notNullable();
        table.decimal('budget', 10, 2).notNullable();
        table.timestamp('start_date').notNullable();
        table.timestamp('end_date').notNullable();
        table.json('platforms').notNullable();
        table.json('target_audience').notNullable();
        table.enum('status', ['DRAFT', 'ACTIVE', 'PAUSED', 'COMPLETED']).defaultTo('DRAFT');
        table.decimal('roi', 10, 2).defaultTo(0);
        table.timestamp('created_at').defaultTo(db.fn.now());
        table.timestamp('updated_at').defaultTo(db.fn.now());
        
        table.index(['tenant_id']);
        table.index(['status']);
      });
      logger.info('[MarketingService] Created cf_ad_plan table');
    }

    if (!(await db.schema.hasTable(this.TABLE_AD_PERFORMANCE))) {
      await db.schema.createTable(this.TABLE_AD_PERFORMANCE, (table) => {
        table.string('id').primary();
        table.string('plan_id').notNullable();
        table.string('platform').notNullable();
        table.integer('impressions').defaultTo(0);
        table.integer('clicks').defaultTo(0);
        table.integer('conversions').defaultTo(0);
        table.decimal('spend', 10, 2).defaultTo(0);
        table.decimal('revenue', 10, 2).defaultTo(0);
        table.decimal('roi', 10, 2).defaultTo(0);
        table.date('date').notNullable();
        
        table.foreign('plan_id').references('cf_ad_plan.id');
        table.index(['plan_id']);
        table.index(['platform']);
        table.index(['date']);
      });
      logger.info('[MarketingService] Created cf_ad_performance table');
    }
  }

  /**
   * 创建广告计划
   */
  static async createAdPlan(input: CreateAdPlanInput): Promise<AdPlan> {
    const { tenantId, name, budget, startDate, endDate, platforms, targetAudience, businessType } = input;

    logger.info(`[MarketingService] Creating ad plan - name: ${name}, tenantId: ${tenantId}`);

    const planId = `AD-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;

    try {
      await db(this.TABLE_AD_PLAN).insert({
        id: planId,
        tenant_id: tenantId,
        name,
        budget,
        start_date: startDate,
        end_date: endDate,
        platforms: JSON.stringify(platforms),
        target_audience: JSON.stringify(targetAudience),
        status: 'DRAFT',
        roi: 0,
        created_at: new Date(),
        updated_at: new Date(),
      });

      const createdPlan = await db(this.TABLE_AD_PLAN)
        .where('id', planId)
        .first();

      logger.info(`[MarketingService] Ad plan created successfully - planId: ${planId}`);

      return {
        ...createdPlan,
        platforms: JSON.parse(createdPlan.platforms),
        targetAudience: JSON.parse(createdPlan.target_audience),
      };
    } catch (error: any) {
      logger.error(`[MarketingService] Failed to create ad plan - error: ${error.message}`);
      throw error;
    }
  }

  /**
   * 启动广告计划
   */
  static async activateAdPlan(planId: string, tenantId: string): Promise<AdPlan> {
    logger.info(`[MarketingService] Activating ad plan - planId: ${planId}, tenantId: ${tenantId}`);

    try {
      await db(this.TABLE_AD_PLAN)
        .where({ id: planId, tenant_id: tenantId })
        .update({
          status: 'ACTIVE',
          updated_at: new Date(),
        });

      const updatedPlan = await db(this.TABLE_AD_PLAN)
        .where({ id: planId, tenant_id: tenantId })
        .first();

      logger.info(`[MarketingService] Ad plan activated - planId: ${planId}`);

      return {
        ...updatedPlan,
        platforms: JSON.parse(updatedPlan.platforms),
        targetAudience: JSON.parse(updatedPlan.target_audience),
      };
    } catch (error: any) {
      logger.error(`[MarketingService] Failed to activate ad plan - error: ${error.message}`);
      throw error;
    }
  }

  /**
   * 跨平台投放广告
   */
  static async deployAd(planId: string, tenantId: string): Promise<void> {
    logger.info(`[MarketingService] Deploying ad plan - planId: ${planId}, tenantId: ${tenantId}`);

    try {
      const plan = await db(this.TABLE_AD_PLAN)
        .where({ id: planId, tenant_id: tenantId })
        .first();

      if (!plan) {
        throw new Error(`Ad plan not found: ${planId}`);
      }

      if (plan.status !== 'ACTIVE') {
        throw new Error(`Ad plan is not active: ${planId}, current status: ${plan.status}`);
      }

      const platforms = JSON.parse(plan.platforms);

      for (const platform of platforms) {
        // 模拟跨平台投放逻辑
        logger.info(`[MarketingService] Deploying ad to ${platform} for plan ${planId}`);
        
        // 记录投放日志
        await AuditService.log({
          module: 'MARKETING',
          action: 'AD_DEPLOYED',
          userId: 'SYSTEM',
          tenantId,
          traceId: `DEPLOY-${Date.now()}`,
          resourceType: 'ad_plan',
          resourceId: planId,
          afterSnapshot: { platform, planName: plan.name },
          source: 'node',
          result: 'success'
        });
      }

      logger.info(`[MarketingService] Ad plan deployed to ${platforms.length} platforms - planId: ${planId}`);
    } catch (error: any) {
      logger.error(`[MarketingService] Failed to deploy ad plan - error: ${error.message}`);
      throw error;
    }
  }

  /**
   * 分析广告效果
   */
  static async analyzeAdPerformance(planId: string, tenantId: string, timeRange: { start: Date; end: Date }): Promise<AdPerformance[]> {
    logger.info(`[MarketingService] Analyzing ad performance - planId: ${planId}, tenantId: ${tenantId}`);

    try {
      const performanceData = await db(this.TABLE_AD_PERFORMANCE)
        .where({ plan_id: planId })
        .whereBetween('date', [timeRange.start, timeRange.end])
        .select('*');

      // 计算总体ROI
      const totalSpend = performanceData.reduce((sum, data) => sum + parseFloat(data.spend.toString()), 0);
      const totalRevenue = performanceData.reduce((sum, data) => sum + parseFloat(data.revenue.toString()), 0);
      const overallRoi = totalSpend > 0 ? totalRevenue / totalSpend : 0;

      // 更新计划ROI
      await db(this.TABLE_AD_PLAN)
        .where({ id: planId, tenant_id: tenantId })
        .update({ roi: overallRoi });

      // 检查ROI是否小于1，如果是则停止投放
      if (overallRoi < 1) {
        await db(this.TABLE_AD_PLAN)
          .where({ id: planId, tenant_id: tenantId })
          .update({ status: 'PAUSED' });

        logger.warn(`[MarketingService] Ad plan paused due to low ROI (${overallRoi.toFixed(2)}) - planId: ${planId}`);
      }

      logger.info(`[MarketingService] Ad performance analyzed - planId: ${planId}, ROI: ${overallRoi.toFixed(2)}`);

      return performanceData;
    } catch (error: any) {
      logger.error(`[MarketingService] Failed to analyze ad performance - error: ${error.message}`);
      throw error;
    }
  }

  /**
   * 扫描 24 小时前未下单的加购记录并触发挽留
   */
  static async processAbandonedCarts(): Promise<void> {
    try {
      const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000);
      const dayBeforeYesterday = new Date(Date.now() - 48 * 60 * 60 * 1000);

      // 获取 24-48 小时内未结账且未发送挽留邮件的记录
      const abandonedCarts = await db(this.TABLE_CART)
        .where({ status: 'ABANDONED', recoverySent: false })
        .whereBetween('updated_at', [dayBeforeYesterday, yesterday])
        .select('*');

      for (const cart of abandonedCarts) {
        await this.triggerRecoveryStrategy(cart);
      }
    } catch (error: any) {
      logger.error(`[AbandonedRecovery] Failed to process carts: ${error.message}`);
    }
  }

  /**
   * 执行阶梯优惠挽留策略
   */
  private static async triggerRecoveryStrategy(cart: any): Promise<void> {
    try {
      // 1. 获取用户历史价值 (LTV) 评分
      const customerScore = await this.getCustomerScore(cart.userId);
      
      let discountCode: string;
      let emailContent: string;

      // 2. 阶梯策略：根据用户价值决定优惠力度
      if (customerScore > 80) {
        discountCode = 'VIP_RECOVER_20'; // 8折
        emailContent = `[VIP Exclusive] Still thinking about it? Here's 20% off just for you!`;
      } else if (customerScore > 50) {
        discountCode = 'SAVE_10_NOW'; // 9折
        emailContent = `We noticed you left something behind. Enjoy 10% off if you order now!`;
      } else {
        discountCode = 'COME_BACK_5'; // 95折
        emailContent = `Complete your purchase and get 5% off!`;
      }

      // 3. 记录审计并标记已发送 (Mock 邮件发送逻辑)
      logger.info(`[AbandonedRecovery] Sending ${discountCode} to user ${cart.userId} for cart ${cart.id}`);
      
      await db(this.TABLE_CART).where({ id: cart.id }).update({
        recoverySent: true,
        recoveryStrategy: discountCode,
        recovery_at: new Date()
      });

      // 发送审计日志 (BIZ_DEV_04)
      await AuditService.log({
        module: 'MARKETING',
        action: 'RECOVERY_SENT',
        userId: cart.userId,
        tenantId: 'SYSTEM', // 实际应从用户上下文获取
        traceId: `RECOVER-${Date.now()}`,
        resourceType: 'cart',
        resourceId: String(cart.id),
        afterSnapshot: { discountCode, emailContent },
        source: 'node',
        result: 'success'
      });
    } catch (error: any) {
      logger.error(`[AbandonedRecovery] Strategy failed for user ${cart.userId}: ${error.message}`);
    }
  }

  private static async getCustomerScore(userId: string): Promise<number> {
    // 模拟根据历史 LTV 获取的用户得分 (0-100)
    return Math.floor(Math.random() * 100);
  }

  /**
   * 发送挽回邮件
   */
  static async sendRecoveryEmail(params: {
    tenantId: string;
    templateId: string;
    delayHours: number;
  }): Promise<void> {
    logger.info(`[MarketingService] Sending recovery email with template: ${params.templateId}, delay: ${params.delayHours}h`);
    
    // 模拟发送邮件逻辑
    await db('cf_email_queue').insert({
      tenant_id: params.tenantId,
      template_id: params.templateId,
      scheduled_at: new Date(Date.now() + params.delayHours * 60 * 60 * 1000),
      status: 'PENDING',
      created_at: new Date()
    });
  }
}
