import db from '../config/database';
import { logger } from '../utils/logger';
import { AIService } from './AIService';
import { ProductService } from './ProductService';
import { PricingService } from './PricingService';
import { CompetitorService } from './CompetitorService';
import { EventBusService } from './EventBusService';

interface SelectionRule {
  id: string;
  tenant_id: string;
  shop_id: string;
  name: string;
  category: string[];
  min_roi: number;
  max_roi: number;
  min_profit: number;
  max_price: number;
  min_sales_volume: number;
  max_competition_level: 'LOW' | 'MEDIUM' | 'HIGH';
  min_rating: number;
  trend_filter: 'ALL' | 'UP' | 'STABLE';
  enabled: boolean;
  last_run_at?: Date;
  selected_count: number;
  created_at: Date;
  updated_at: Date;
}

interface ProductPool {
  id: string;
  tenant_id: string;
  shop_id: string;
  product_id: string;
  name: string;
  category: string;
  price: number;
  cost_price: number;
  profit: number;
  roi: number;
  sales_volume: number;
  rating: number;
  review_count: number;
  competition_level: 'LOW' | 'MEDIUM' | 'HIGH';
  trend: 'UP' | 'DOWN' | 'STABLE';
  source_platform: string;
  image_url: string;
  selection_score: number;
  tags: string[];
  selected_at?: Date;
  created_at: Date;
  updated_at: Date;
}

interface SelectionResult {
  rule_id: string;
  rule_name: string;
  selected_products: ProductPool[];
  total_count: number;
  execution_time: number;
  timestamp: Date;
}

export class ProductSelectionService {
  private static readonly TABLE_NAME_RULES = 'cf_selection_rules';
  private static readonly TABLE_NAME_POOL = 'cf_product_pool';
  private static readonly TABLE_NAME_SELECTED = 'cf_selected_products';

  /**
   * 初始化数据库表
   */
  static async initTables() {
    await this.initRulesTable();
    await this.initPoolTable();
    await this.initSelectedTable();
  }

  private static async initRulesTable() {
    const hasTable = await db.schema.hasTable(this.TABLE_NAME_RULES);
    if (!hasTable) {
      logger.info(`Creating ${this.TABLE_NAME_RULES} table...`);
      await db.schema.createTable(this.TABLE_NAME_RULES, (table) => {
        table.increments('id').primary();
        table.string('tenant_id', 50).notNullable().index();
        table.string('shop_id', 50).notNullable().index();
        table.string('name', 200).notNullable();
        table.json('category').notNullable();
        table.decimal('min_roi', 5, 2).notNullable();
        table.decimal('max_roi', 5, 2).notNullable();
        table.decimal('min_profit', 10, 2).notNullable();
        table.decimal('max_price', 10, 2).notNullable();
        table.integer('min_sales_volume').notNullable();
        table.enum('max_competition_level', ['LOW', 'MEDIUM', 'HIGH']).notNullable();
        table.decimal('min_rating', 3, 2).notNullable();
        table.enum('trend_filter', ['ALL', 'UP', 'STABLE']).notNullable();
        table.boolean('enabled').defaultTo(true);
        table.timestamp('last_run_at');
        table.integer('selected_count').defaultTo(0);
        table.timestamps(true, true);
        
        table.index(['tenant_id', 'shop_id', 'enabled'], 'idx_rule_tenant_shop_enabled');
      });
      logger.info(`✅ Table ${this.TABLE_NAME_RULES} created`);
    }
  }

  private static async initPoolTable() {
    const hasTable = await db.schema.hasTable(this.TABLE_NAME_POOL);
    if (!hasTable) {
      logger.info(`Creating ${this.TABLE_NAME_POOL} table...`);
      await db.schema.createTable(this.TABLE_NAME_POOL, (table) => {
        table.increments('id').primary();
        table.string('tenant_id', 50).notNullable().index();
        table.string('shop_id', 50).notNullable().index();
        table.string('product_id', 100).notNullable();
        table.string('name', 500).notNullable();
        table.string('category', 100).notNullable();
        table.decimal('price', 10, 2).notNullable();
        table.decimal('cost_price', 10, 2).notNullable();
        table.decimal('profit', 10, 2).notNullable();
        table.decimal('roi', 5, 2).notNullable();
        table.integer('sales_volume').notNullable();
        table.decimal('rating', 3, 2).notNullable();
        table.integer('review_count').notNullable();
        table.enum('competition_level', ['LOW', 'MEDIUM', 'HIGH']).notNullable();
        table.enum('trend', ['UP', 'DOWN', 'STABLE']).notNullable();
        table.string('source_platform', 50).notNullable();
        table.string('image_url', 500);
        table.decimal('selection_score', 5, 2).notNullable();
        table.json('tags');
        table.timestamp('selected_at');
        table.timestamps(true, true);
        
        table.index(['tenant_id', 'shop_id', 'selection_score'], 'idx_pool_score');
        table.index(['tenant_id', 'shop_id', 'category'], 'idx_pool_category');
        table.index(['tenant_id', 'shop_id', 'competition_level'], 'idx_pool_competition');
      });
      logger.info(`✅ Table ${this.TABLE_NAME_POOL} created`);
    }
  }

  private static async initSelectedTable() {
    const hasTable = await db.schema.hasTable(this.TABLE_NAME_SELECTED);
    if (!hasTable) {
      logger.info(`Creating ${this.TABLE_NAME_SELECTED} table...`);
      await db.schema.createTable(this.TABLE_NAME_SELECTED, (table) => {
        table.increments('id').primary();
        table.string('tenant_id', 50).notNullable().index();
        table.string('shop_id', 50).notNullable().index();
        table.string('product_id', 100).notNullable();
        table.string('rule_id').notNullable();
        table.decimal('selection_score', 5, 2).notNullable();
        table.enum('status', ['PENDING', 'APPROVED', 'REJECTED']).defaultTo('PENDING');
        table.json('selection_reason');
        table.timestamps(true, true);
        
        table.index(['tenant_id', 'shop_id', 'status'], 'idx_selected_status');
        table.index(['tenant_id', 'shop_id', 'rule_id'], 'idx_selected_rule');
      });
      logger.info(`✅ Table ${this.TABLE_NAME_SELECTED} created`);
    }
  }

  /**
   * 创建选品规则
   */
  static async createRule(rule: Omit<SelectionRule, 'id' | 'selected_count' | 'created_at' | 'updated_at'>): Promise<SelectionRule> {
    const [id] = await db(this.TABLE_NAME_RULES).insert({
      ...rule,
      category: JSON.stringify(rule.category),
      selected_count: 0,
      created_at: new Date(),
      updated_at: new Date(),
    }).returning('id');

    return {
      ...rule,
      id: id.toString(),
      selected_count: 0,
      created_at: new Date(),
      updated_at: new Date(),
    };
  }

  /**
   * 更新选品规则
   */
  static async updateRule(ruleId: string, updates: Partial<SelectionRule>): Promise<void> {
    const updateData: any = { ...updates, updated_at: new Date() };
    if (updates.category) {
      updateData.category = JSON.stringify(updates.category);
    }
    await db(this.TABLE_NAME_RULES).where({ id: ruleId }).update(updateData);
  }

  /**
   * 删除选品规则
   */
  static async deleteRule(ruleId: string): Promise<void> {
    await db(this.TABLE_NAME_RULES).where({ id: ruleId }).delete();
  }

  /**
   * 切换规则启用状态
   */
  static async toggleRule(ruleId: string): Promise<SelectionRule | null> {
    const rule = await db(this.TABLE_NAME_RULES).where({ id: ruleId }).first();
    if (!rule) return null;

    const updated = await db(this.TABLE_NAME_RULES).where({ id: ruleId }).update({
      enabled: !rule.enabled,
      updated_at: new Date(),
    }).returning('*');

    return {
      ...updated[0],
      category: JSON.parse(updated[0].category),
    };
  }

  /**
   * 获取租户的所有选品规则
   */
  static async getRules(tenantId: string, shopId?: string): Promise<SelectionRule[]> {
    const query = db(this.TABLE_NAME_RULES).where({ tenant_id: tenantId });
    if (shopId) {
      query.where({ shop_id: shopId });
    }
    const rules = await query.orderBy('created_at', 'desc');
    return rules.map(rule => ({
      ...rule,
      category: JSON.parse(rule.category),
    }));
  }

  /**
   * 添加商品到选品池
   */
  static async addToPool(product: Omit<ProductPool, 'id' | 'created_at' | 'updated_at'>): Promise<ProductPool> {
    const [id] = await db(this.TABLE_NAME_POOL).insert({
      ...product,
      tags: JSON.stringify(product.tags || []),
      created_at: new Date(),
      updated_at: new Date(),
    }).returning('id');

    return {
      ...product,
      id: id.toString(),
      created_at: new Date(),
      updated_at: new Date(),
    };
  }

  /**
   * 批量添加商品到选品池
   */
  static async batchAddToPool(products: Omit<ProductPool, 'id' | 'created_at' | 'updated_at'>[]): Promise<void> {
    const now = new Date();
    const records = products.map(product => ({
      ...product,
      tags: JSON.stringify(product.tags || []),
      created_at: now,
      updated_at: now,
    }));
    await db(this.TABLE_NAME_POOL).insert(records);
  }

  /**
   * 从选品池获取商品
   */
  static async getFromPool(
    tenantId: string,
    shopId: string,
    filters?: {
      category?: string;
      min_roi?: number;
      max_roi?: number;
      competition_level?: 'LOW' | 'MEDIUM' | 'HIGH';
      trend?: 'UP' | 'DOWN' | 'STABLE';
      min_score?: number;
    },
    limit: number = 50,
    offset: number = 0
  ): Promise<ProductPool[]> {
    let query = db(this.TABLE_NAME_POOL)
      .where({ tenant_id: tenantId, shop_id: shopId });

    if (filters?.category) {
      query = query.where({ category: filters.category });
    }
    if (filters?.min_roi) {
      query = query.where('roi', '>=', filters.min_roi);
    }
    if (filters?.max_roi) {
      query = query.where('roi', '<=', filters.max_roi);
    }
    if (filters?.competition_level) {
      query = query.where({ competition_level: filters.competition_level });
    }
    if (filters?.trend) {
      query = query.where({ trend: filters.trend });
    }
    if (filters?.min_score) {
      query = query.where('selection_score', '>=', filters.min_score);
    }

    const products = await query
      .orderBy('selection_score', 'desc')
      .limit(limit)
      .offset(offset);

    return products.map(product => ({
      ...product,
      tags: product.tags ? JSON.parse(product.tags) : [],
    }));
  }

  /**
   * 执行选品规则
   */
  static async executeRule(ruleId: string): Promise<SelectionResult> {
    const startTime = Date.now();
    const rule = await db(this.TABLE_NAME_RULES).where({ id: ruleId }).first();
    if (!rule) {
      throw new Error(`Rule ${ruleId} not found`);
    }

    const ruleData = {
      ...rule,
      category: JSON.parse(rule.category),
    };

    const selectedProducts = await this.getFromPool(
      ruleData.tenant_id,
      ruleData.shop_id,
      {
        category: ruleData.category.length > 0 ? undefined : undefined,
        min_roi: ruleData.min_roi,
        max_roi: ruleData.max_roi,
        competition_level: ruleData.max_competition_level,
        trend: ruleData.trend_filter === 'ALL' ? undefined : ruleData.trend_filter,
      },
      100
    );

    const filteredProducts = selectedProducts.filter(product => {
      if (ruleData.category.length > 0 && !ruleData.category.includes(product.category)) {
        return false;
      }
      if (product.profit < ruleData.min_profit) return false;
      if (product.price > ruleData.max_price) return false;
      if (product.sales_volume < ruleData.min_sales_volume) return false;
      if (product.rating < ruleData.min_rating) return false;
      return true;
    });

    const now = new Date();
    for (const product of filteredProducts) {
      await db(this.TABLE_NAME_SELECTED).insert({
        tenant_id: ruleData.tenant_id,
        shop_id: ruleData.shop_id,
        product_id: product.product_id,
        rule_id: ruleId,
        selection_score: product.selection_score,
        status: 'PENDING',
        selection_reason: JSON.stringify({
          rule_name: ruleData.name,
          roi: product.roi,
          profit: product.profit,
          sales_volume: product.sales_volume,
          rating: product.rating,
        }),
        created_at: now,
        updated_at: now,
      });
    }

    await db(this.TABLE_NAME_RULES).where({ id: ruleId }).update({
      last_run_at: now,
      selected_count: ruleData.selected_count + filteredProducts.length,
      updated_at: now,
    });

    const executionTime = Date.now() - startTime;

    const result: SelectionResult = {
      rule_id: ruleId,
      rule_name: ruleData.name,
      selected_products: filteredProducts,
      total_count: filteredProducts.length,
      execution_time,
      timestamp: now,
    };

    logger.info(`Rule ${ruleId} executed: ${filteredProducts.length} products selected in ${executionTime}ms`);

    return result;
  }

  /**
   * 执行所有启用的规则
   */
  static async executeAllRules(tenantId: string, shopId?: string): Promise<SelectionResult[]> {
    const query = db(this.TABLE_NAME_RULES).where({ tenant_id: tenantId, enabled: true });
    if (shopId) {
      query.where({ shop_id: shopId });
    }
    const rules = await query;

    const results: SelectionResult[] = [];
    for (const rule of rules) {
      try {
        const result = await this.executeRule(rule.id);
        results.push(result);
      } catch (error) {
        logger.error(`Failed to execute rule ${rule.id}:`, error);
      }
    }

    return results;
  }

  /**
   * 计算商品选品评分
   */
  static async calculateSelectionScore(product: any): Promise<number> {
    let score = 0;

    const roiScore = Math.min(product.roi / 100, 1) * 30;
    score += roiScore;

    const profitScore = Math.min(product.profit / 100, 1) * 20;
    score += profitScore;

    const salesScore = Math.min(product.sales_volume / 1000, 1) * 15;
    score += salesScore;

    const ratingScore = (product.rating / 5) * 15;
    score += ratingScore;

    const competitionScore = {
      LOW: 10,
      MEDIUM: 5,
      HIGH: 0,
    }[product.competition_level] || 0;
    score += competitionScore;

    const trendScore = {
      UP: 10,
      STABLE: 5,
      DOWN: 0,
    }[product.trend] || 0;
    score += trendScore;

    return Math.min(score, 100);
  }

  /**
   * 分析竞争水平
   */
  static async analyzeCompetitionLevel(productId: string, platform: string): Promise<'LOW' | 'MEDIUM' | 'HIGH'> {
    const competitors = await CompetitorService.getCompetitors(productId, platform);
    const count = competitors.length;

    if (count < 10) return 'LOW';
    if (count < 30) return 'MEDIUM';
    return 'HIGH';
  }

  /**
   * 分析销售趋势
   */
  static async analyzeSalesTrend(productId: string, platform: string): Promise<'UP' | 'DOWN' | 'STABLE'> {
    const salesHistory = await CompetitorService.getSalesHistory(productId, platform);
    if (salesHistory.length < 2) return 'STABLE';

    const recent = salesHistory.slice(-7).reduce((sum, h) => sum + h.sales, 0);
    const previous = salesHistory.slice(-14, -7).reduce((sum, h) => sum + h.sales, 0);

    if (previous === 0) return 'STABLE';

    const growthRate = ((recent - previous) / previous) * 100;

    if (growthRate > 10) return 'UP';
    if (growthRate < -10) return 'DOWN';
    return 'STABLE';
  }

  /**
   * 从外部平台同步商品到选品池
   */
  static async syncProductsFromPlatform(
    tenantId: string,
    shopId: string,
    platform: string,
    category?: string
  ): Promise<number> {
    const products = await ProductService.getProductsByPlatform(platform, category);
    let syncedCount = 0;

    for (const product of products) {
      const competitionLevel = await this.analyzeCompetitionLevel(product.productId, platform);
      const trend = await this.analyzeSalesTrend(product.productId, platform);
      const selectionScore = await this.calculateSelectionScore(product);

      const poolProduct: Omit<ProductPool, 'id' | 'created_at' | 'updated_at'> = {
        tenant_id: tenantId,
        shop_id: shopId,
        product_id: product.productId,
        name: product.title,
        category: category || '未分类',
        price: parseFloat(product.price),
        cost_price: parseFloat(product.price) * 0.5,
        profit: parseFloat(product.price) * 0.5,
        roi: 100,
        sales_volume: product.sales || 0,
        rating: product.rating || 0,
        review_count: 0,
        competition_level: competitionLevel,
        trend: trend,
        source_platform: platform,
        image_url: product.mainImage,
        selection_score: selectionScore,
        tags: [],
      };

      await this.addToPool(poolProduct);
      syncedCount++;
    }

    logger.info(`Synced ${syncedCount} products from ${platform} to pool`);
    return syncedCount;
  }

  /**
   * 获取选品统计
   */
  static async getSelectionStats(tenantId: string, shopId: string): Promise<{
    totalPool: number;
    totalSelected: number;
    avgROI: number;
    avgScore: number;
    lowCompetition: number;
    upTrend: number;
  }> {
    const [poolStats] = await db(this.TABLE_NAME_POOL)
      .where({ tenant_id: tenantId, shop_id: shopId })
      .select(
        db.raw('COUNT(*) as total'),
        db.raw('AVG(roi) as avg_roi'),
        db.raw('AVG(selection_score) as avg_score'),
        db.raw('SUM(CASE WHEN competition_level = ? THEN 1 ELSE 0 END) as low_competition', ['LOW']),
        db.raw('SUM(CASE WHEN trend = ? THEN 1 ELSE 0 END) as up_trend', ['UP'])
      );

    const [selectedStats] = await db(this.TABLE_NAME_SELECTED)
      .where({ tenant_id: tenantId, shop_id: shopId })
      .select(db.raw('COUNT(*) as total'));

    return {
      totalPool: poolStats.total || 0,
      totalSelected: selectedStats.total || 0,
      avgROI: poolStats.avg_roi || 0,
      avgScore: poolStats.avg_score || 0,
      lowCompetition: poolStats.low_competition || 0,
      upTrend: poolStats.up_trend || 0,
    };
  }

  /**
   * 清理过期的选品池商品
   */
  static async cleanupOldPoolProducts(days: number = 30): Promise<number> {
    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - days);

    const deleted = await db(this.TABLE_NAME_POOL)
      .where('created_at', '<', cutoffDate)
      .delete();

    logger.info(`Cleaned up ${deleted} old products from pool`);
    return deleted;
  }
}
