/**
 * [BE-ORDER-MS001] 订单聚合服务
 * 负责多店铺订单聚合、统计、同步等功能
 * AI注意: 所有订单多店铺操作必须通过此服务进行
 */

import db from '../config/database';
import { logger } from '../utils/logger';
import { EventBusService } from './EventBusService';
import { RedisService } from './RedisService';
import { DataIsolationService, DataIsolationContext } from './DataIsolationService';
import { OrderStatus } from '../types/enums';

// 订单聚合统计
export interface OrderAggregationStats {
  totalOrders: number;
  totalAmount: number;
  totalProducts: number;
  byStatus: Record<OrderStatus, { count: number; amount: number }>;
  byShop: Record<string, { count: number; amount: number; shopName: string }>;
  byPlatform: Record<string, { count: number; amount: number }>;
  pendingOrders: number;
  processingOrders: number;
  completedOrders: number;
  cancelledOrders: number;
}

// 店铺订单概览
export interface ShopOrderOverview {
  shopId: string;
  shopName: string;
  platform: string;
  totalOrders: number;
  todayOrders: number;
  pendingOrders: number;
  processingOrders: number;
  completedOrders: number;
  totalAmount: number;
  todayAmount: number;
  avgOrderValue: number;
  topProducts: Array<{
    productId: string;
    productName: string;
    quantity: number;
    amount: number;
  }>;
}

// 订单同步结果
export interface OrderSyncResult {
  shopId: string;
  shopName: string;
  platform: string;
  synced: number;
  created: number;
  updated: number;
  failed: number;
  errors: Array<{ orderId: string; error: string }>;
  syncTime: Date;
}

// 订单聚合查询参数
export interface OrderAggregationQuery {
  tenantId: string;
  departmentId?: string;
  shopIds?: string[];
  platforms?: string[];
  status?: OrderStatus[];
  dateFrom?: Date;
  dateTo?: Date;
  page?: number;
  pageSize?: number;
}

export class OrderAggregationService {
  private static readonly CACHE_PREFIX = 'order_aggregation:';
  private static readonly CACHE_TTL = 300;

  /**
   * [BE-ORDER-MS001-01] 获取多店铺订单聚合统计
   */
  static async getAggregationStats(
    context: DataIsolationContext,
    query: Partial<OrderAggregationQuery> = {}
  ): Promise<OrderAggregationStats> {
    const cacheKey = `${this.CACHE_PREFIX}stats:${context.tenantId}:${JSON.stringify(query)}`;
    const cached = await RedisService.get(cacheKey);
    if (cached) {
      return JSON.parse(cached);
    }

    let baseQuery = DataIsolationService.buildIsolationQuery('cf_order', context);

    if (query.shopIds?.length) {
      baseQuery = baseQuery.whereIn('shop_id', query.shopIds);
    }
    if (query.platforms?.length) {
      baseQuery = baseQuery.whereIn('platform', query.platforms);
    }
    if (query.status?.length) {
      baseQuery = baseQuery.whereIn('status', query.status);
    }
    if (query.dateFrom) {
      baseQuery = baseQuery.where('created_at', '>=', query.dateFrom);
    }
    if (query.dateTo) {
      baseQuery = baseQuery.where('created_at', '<=', query.dateTo);
    }

    const orders = await baseQuery.select(
      'id',
      'shop_id',
      'platform',
      'status',
      'total_amount',
      'product_count'
    );

    const shops = await db('cf_shop')
      .whereIn('id', [...new Set(orders.map(o => o.shop_id))])
      .select('id', 'name');

    const shopMap = new Map(shops.map(s => [s.id, s.name]));

    const stats: OrderAggregationStats = {
      totalOrders: orders.length,
      totalAmount: orders.reduce((sum, o) => sum + Number(o.total_amount || 0), 0),
      totalProducts: orders.reduce((sum, o) => sum + Number(o.product_count || 0), 0),
      byStatus: {} as Record<OrderStatus, { count: number; amount: number }>,
      byShop: {} as Record<string, { count: number; amount: number; shopName: string }>,
      byPlatform: {} as Record<string, { count: number; amount: number }>,
      pendingOrders: 0,
      processingOrders: 0,
      completedOrders: 0,
      cancelledOrders: 0,
    };

    orders.forEach(order => {
      const status = order.status as OrderStatus;
      const amount = Number(order.total_amount || 0);

      if (!stats.byStatus[status]) {
        stats.byStatus[status] = { count: 0, amount: 0 };
      }
      stats.byStatus[status].count++;
      stats.byStatus[status].amount += amount;

      if (!stats.byShop[order.shop_id]) {
        stats.byShop[order.shop_id] = {
          count: 0,
          amount: 0,
          shopName: shopMap.get(order.shop_id) || order.shop_id,
        };
      }
      stats.byShop[order.shop_id].count++;
      stats.byShop[order.shop_id].amount += amount;

      if (!stats.byPlatform[order.platform]) {
        stats.byPlatform[order.platform] = { count: 0, amount: 0 };
      }
      stats.byPlatform[order.platform].count++;
      stats.byPlatform[order.platform].amount += amount;

      if (status === 'PENDING' || status === 'PAID') stats.pendingOrders++;
      else if (status === 'PROCESSING') stats.processingOrders++;
      else if (status === 'DELIVERED') stats.completedOrders++;
      else if (status === 'CANCELLED' || status === 'REFUNDED') stats.cancelledOrders++;
    });

    await RedisService.set(cacheKey, JSON.stringify(stats), this.CACHE_TTL);

    return stats;
  }

  /**
   * [BE-ORDER-MS001-02] 获取店铺订单概览
   */
  static async getShopOrderOverview(
    shopId: string,
    context: DataIsolationContext
  ): Promise<ShopOrderOverview> {
    const cacheKey = `${this.CACHE_PREFIX}shop_overview:${shopId}`;
    const cached = await RedisService.get(cacheKey);
    if (cached) {
      return JSON.parse(cached);
    }

    const shop = await db('cf_shop')
      .where('id', shopId)
      .where('tenant_id', context.tenantId)
      .first('id', 'name', 'platform');

    if (!shop) {
      throw new Error('店铺不存在');
    }

    const today = new Date();
    today.setHours(0, 0, 0, 0);

    const orders = await db('cf_order')
      .where('shop_id', shopId)
      .where('tenant_id', context.tenantId)
      .whereNull('deleted_at')
      .select('id', 'status', 'total_amount', 'created_at');

    const todayOrders = orders.filter(o => new Date(o.created_at) >= today);

    const orderItems = await db('cf_order_item')
      .whereIn('order_id', orders.map(o => o.id))
      .select('product_id', 'product_name', 'quantity', 'total_price');

    const productStats = new Map<string, { name: string; quantity: number; amount: number }>();
    orderItems.forEach(item => {
      const existing = productStats.get(item.product_id) || {
        name: item.product_name,
        quantity: 0,
        amount: 0,
      };
      existing.quantity += Number(item.quantity);
      existing.amount += Number(item.total_price);
      productStats.set(item.product_id, existing);
    });

    const topProducts = Array.from(productStats.entries())
      .map(([productId, stats]) => ({
        productId,
        productName: stats.name,
        quantity: stats.quantity,
        amount: stats.amount,
      }))
      .sort((a, b) => b.amount - a.amount)
      .slice(0, 5);

    const overview: ShopOrderOverview = {
      shopId: shop.id,
      shopName: shop.name,
      platform: shop.platform,
      totalOrders: orders.length,
      todayOrders: todayOrders.length,
      pendingOrders: orders.filter(o => o.status === 'PENDING' || o.status === 'PAID').length,
      processingOrders: orders.filter(o => o.status === 'PROCESSING').length,
      completedOrders: orders.filter(o => o.status === 'DELIVERED').length,
      totalAmount: orders.reduce((sum, o) => sum + Number(o.total_amount || 0), 0),
      todayAmount: todayOrders.reduce((sum, o) => sum + Number(o.total_amount || 0), 0),
      avgOrderValue: orders.length > 0
        ? orders.reduce((sum, o) => sum + Number(o.total_amount || 0), 0) / orders.length
        : 0,
      topProducts,
    };

    await RedisService.set(cacheKey, JSON.stringify(overview), this.CACHE_TTL);

    return overview;
  }

  /**
   * [BE-ORDER-MS001-03] 批量获取店铺订单概览
   */
  static async batchGetShopOverviews(
    context: DataIsolationContext,
    shopIds?: string[]
  ): Promise<ShopOrderOverview[]> {
    let query = db('cf_shop')
      .where('tenant_id', context.tenantId)
      .where('status', 'ACTIVE')
      .whereNull('deleted_at');

    if (shopIds?.length) {
      query = query.whereIn('id', shopIds);
    } else if (context.shopId) {
      query = query.where('id', context.shopId);
    } else if (context.departmentId) {
      query = query.where('department_id', context.departmentId);
    }

    const shops = await query.select('id');

    const overviews = await Promise.all(
      shops.map(shop => this.getShopOrderOverview(shop.id, context))
    );

    return overviews;
  }

  /**
   * [BE-ORDER-MS001-04] 同步店铺订单
   */
  static async syncShopOrders(
    shopId: string,
    context: DataIsolationContext
  ): Promise<OrderSyncResult> {
    const shop = await db('cf_shop')
      .where('id', shopId)
      .where('tenant_id', context.tenantId)
      .first('id', 'name', 'platform');

    if (!shop) {
      throw new Error('店铺不存在');
    }

    const result: OrderSyncResult = {
      shopId: shop.id,
      shopName: shop.name,
      platform: shop.platform,
      synced: 0,
      created: 0,
      updated: 0,
      failed: 0,
      errors: [],
      syncTime: new Date(),
    };

    try {
      // 模拟从平台API获取订单
      const platformOrders = await this.fetchPlatformOrders(shop.platform, shop.id);

      for (const platformOrder of platformOrders) {
        try {
          const existingOrder = await db('cf_order')
            .where('platform_order_id', platformOrder.id)
            .where('shop_id', shopId)
            .first();

          if (existingOrder) {
            await db('cf_order')
              .where('id', existingOrder.id)
              .update({
                status: platformOrder.status,
                total_amount: platformOrder.total_amount,
                updated_at: new Date(),
              });
            result.updated++;
          } else {
            await db('cf_order').insert({
              id: `ORD-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
              tenant_id: context.tenantId,
              shop_id: shopId,
              platform: shop.platform,
              platform_order_id: platformOrder.id,
              status: platformOrder.status,
              total_amount: platformOrder.total_amount,
              product_count: platformOrder.items.length,
              customer_name: platformOrder.customer_name,
              customer_phone: platformOrder.customer_phone,
              shipping_address: JSON.stringify(platformOrder.shipping_address),
              created_at: new Date(platformOrder.created_at),
              updated_at: new Date(),
            });
            result.created++;
          }
          result.synced++;
        } catch (error) {
          result.failed++;
          result.errors.push({
            orderId: platformOrder.id,
            error: error instanceof Error ? error.message : 'Unknown error',
          });
        }
      }

      await EventBusService.publish('order.sync.completed', {
        shopId,
        tenantId: context.tenantId,
        result,
        timestamp: new Date(),
      });

      logger.info(`[OrderAggregation] Synced ${result.synced} orders for shop ${shopId}`);
    } catch (error) {
      logger.error(`[OrderAggregation] Sync failed for shop ${shopId}:`, error);
      throw error;
    }

    return result;
  }

  /**
   * [BE-ORDER-MS001-05] 批量同步多店铺订单
   */
  static async batchSyncOrders(
    context: DataIsolationContext,
    shopIds?: string[]
  ): Promise<OrderSyncResult[]> {
    let query = db('cf_shop')
      .where('tenant_id', context.tenantId)
      .where('status', 'ACTIVE')
      .whereNull('deleted_at');

    if (shopIds?.length) {
      query = query.whereIn('id', shopIds);
    } else if (context.shopId) {
      query = query.where('id', context.shopId);
    } else if (context.departmentId) {
      query = query.where('department_id', context.departmentId);
    }

    const shops = await query.select('id');

    const results = await Promise.all(
      shops.map(shop => this.syncShopOrders(shop.id, context))
    );

    return results;
  }

  /**
   * [BE-ORDER-MS001-06] 获取跨店铺订单列表
   */
  static async getMultiShopOrders(
    context: DataIsolationContext,
    query: OrderAggregationQuery
  ): Promise<{ orders: any[]; total: number }> {
    let baseQuery = DataIsolationService.buildIsolationQuery('cf_order', context);

    if (query.shopIds?.length) {
      baseQuery = baseQuery.whereIn('shop_id', query.shopIds);
    }
    if (query.platforms?.length) {
      baseQuery = baseQuery.whereIn('platform', query.platforms);
    }
    if (query.status?.length) {
      baseQuery = baseQuery.whereIn('status', query.status);
    }
    if (query.dateFrom) {
      baseQuery = baseQuery.where('created_at', '>=', query.dateFrom);
    }
    if (query.dateTo) {
      baseQuery = baseQuery.where('created_at', '<=', query.dateTo);
    }

    const total = await baseQuery.clone().count('id as count').first();

    const page = query.page || 1;
    const pageSize = query.pageSize || 20;
    const offset = (page - 1) * pageSize;

    const orders = await baseQuery
      .clone()
      .orderBy('created_at', 'desc')
      .limit(pageSize)
      .offset(offset)
      .select('*');

    const shopIds = [...new Set(orders.map(o => o.shop_id))];
    const shops = await db('cf_shop')
      .whereIn('id', shopIds)
      .select('id', 'name', 'platform');

    const shopMap = new Map(shops.map(s => [s.id, { name: s.name, platform: s.platform }]));

    const enrichedOrders = orders.map(order => ({
      ...order,
      shop_name: shopMap.get(order.shop_id)?.name || order.shop_id,
      shop_platform: shopMap.get(order.shop_id)?.platform || order.platform,
    }));

    return {
      orders: enrichedOrders,
      total: Number(total?.count || 0),
    };
  }

  /**
   * [BE-ORDER-MS001-07] 获取订单趋势数据
   */
  static async getOrderTrend(
    context: DataIsolationContext,
    days: number = 7,
    shopIds?: string[]
  ): Promise<Array<{ date: string; count: number; amount: number }>> {
    const cacheKey = `${this.CACHE_PREFIX}trend:${context.tenantId}:${days}:${shopIds?.join(',') || 'all'}`;
    const cached = await RedisService.get(cacheKey);
    if (cached) {
      return JSON.parse(cached);
    }

    const startDate = new Date();
    startDate.setDate(startDate.getDate() - days);
    startDate.setHours(0, 0, 0, 0);

    let query = db('cf_order')
      .where('tenant_id', context.tenantId)
      .where('created_at', '>=', startDate)
      .whereNull('deleted_at');

    if (shopIds?.length) {
      query = query.whereIn('shop_id', shopIds);
    } else if (context.shopId) {
      query = query.where('shop_id', context.shopId);
    } else if (context.departmentId) {
      const deptShops = await db('cf_shop')
        .where('department_id', context.departmentId)
        .pluck('id');
      query = query.whereIn('shop_id', deptShops);
    }

    const orders = await query.select('created_at', 'total_amount');

    const trendMap = new Map<string, { count: number; amount: number }>();

    for (let i = 0; i < days; i++) {
      const date = new Date(startDate);
      date.setDate(date.getDate() + i);
      const dateStr = date.toISOString().split('T')[0];
      trendMap.set(dateStr, { count: 0, amount: 0 });
    }

    orders.forEach(order => {
      const dateStr = new Date(order.created_at).toISOString().split('T')[0];
      const existing = trendMap.get(dateStr);
      if (existing) {
        existing.count++;
        existing.amount += Number(order.total_amount || 0);
      }
    });

    const trend = Array.from(trendMap.entries())
      .map(([date, stats]) => ({
        date,
        count: stats.count,
        amount: stats.amount,
      }))
      .sort((a, b) => a.date.localeCompare(b.date));

    await RedisService.set(cacheKey, JSON.stringify(trend), this.CACHE_TTL);

    return trend;
  }

  /**
   * [BE-ORDER-MS001-08] 清除聚合缓存
   */
  static async clearAggregationCache(
    tenantId: string,
    shopId?: string
  ): Promise<void> {
    const pattern = shopId
      ? `${this.CACHE_PREFIX}*:${tenantId}:*${shopId}*`
      : `${this.CACHE_PREFIX}*:${tenantId}*`;

    await RedisService.deletePattern(pattern);
    logger.info(`[OrderAggregation] Cleared cache for tenant ${tenantId}`);
  }

  /**
   * 模拟从平台获取订单
   */
  private static async fetchPlatformOrders(platform: string, shopId: string): Promise<any[]> {
    // 模拟平台API调用
    await new Promise(resolve => setTimeout(resolve, 100));

    const mockOrders = [
      {
        id: `${platform}-${Date.now()}-001`,
        status: 'PAID',
        total_amount: 199.99,
        items: [{ product_id: 'P001', quantity: 1 }],
        customer_name: '测试客户',
        customer_phone: '13800138000',
        shipping_address: { province: '上海', city: '上海市', district: '浦东新区', address: '测试地址' },
        created_at: new Date().toISOString(),
      },
      {
        id: `${platform}-${Date.now()}-002`,
        status: 'PROCESSING',
        total_amount: 299.99,
        items: [{ product_id: 'P002', quantity: 2 }],
        customer_name: '测试客户2',
        customer_phone: '13800138001',
        shipping_address: { province: '北京', city: '北京市', district: '朝阳区', address: '测试地址2' },
        created_at: new Date().toISOString(),
      },
    ];

    return mockOrders;
  }
}
