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

interface ListingTask {
  id: string;
  tenant_id: string;
  shop_id: string;
  product_id: string;
  product_name: string;
  target_platforms: string[];
  status: 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED';
  progress: number;
  error_message?: string;
  created_at: Date;
  completed_at?: Date;
  updated_at: Date;
}

interface AutoListingConfig {
  id: string;
  tenant_id: string;
  shop_id: string;
  enabled: boolean;
  batch_size: number;
  interval_hours: number;
  target_platforms: string[];
  auto_pricing: boolean;
  auto_inventory: boolean;
  auto_description: boolean;
  auto_images: boolean;
  created_at: Date;
  updated_at: Date;
}

interface ListingResult {
  task_id: string;
  product_id: string;
  platform: string;
  success: boolean;
  error?: string;
  platform_product_id?: string;
  listing_url?: string;
}

export class AutoListingService {
  private static readonly TABLE_NAME_TASKS = 'cf_listing_tasks';
  private static readonly TABLE_NAME_CONFIG = 'cf_auto_listing_config';
  private static readonly TABLE_NAME_RESULTS = 'cf_listing_results';

  /**
   * 初始化数据库表
   */
  static async initTables() {
    await this.initTasksTable();
    await this.initConfigTable();
    await this.initResultsTable();
  }

  private static async initTasksTable() {
    const hasTable = await db.schema.hasTable(this.TABLE_NAME_TASKS);
    if (!hasTable) {
      logger.info(`Creating ${this.TABLE_NAME_TASKS} table...`);
      await db.schema.createTable(this.TABLE_NAME_TASKS, (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('product_name', 500).notNullable();
        table.json('target_platforms').notNullable();
        table.enum('status', ['PENDING', 'PROCESSING', 'COMPLETED', 'FAILED']).defaultTo('PENDING');
        table.integer('progress').defaultTo(0);
        table.text('error_message');
        table.timestamps(true, true);
        table.timestamp('completed_at');
        
        table.index(['tenant_id', 'shop_id', 'status'], 'idx_tasks_status');
        table.index(['tenant_id', 'shop_id', 'created_at'], 'idx_tasks_created');
      });
      logger.info(`✅ Table ${this.TABLE_NAME_TASKS} created`);
    }
  }

  private static async initConfigTable() {
    const hasTable = await db.schema.hasTable(this.TABLE_NAME_CONFIG);
    if (!hasTable) {
      logger.info(`Creating ${this.TABLE_NAME_CONFIG} table...`);
      await db.schema.createTable(this.TABLE_NAME_CONFIG, (table) => {
        table.increments('id').primary();
        table.string('tenant_id', 50).notNullable().unique();
        table.string('shop_id', 50).notNullable();
        table.boolean('enabled').defaultTo(false);
        table.integer('batch_size').defaultTo(10);
        table.integer('interval_hours').defaultTo(6);
        table.json('target_platforms').notNullable();
        table.boolean('auto_pricing').defaultTo(true);
        table.boolean('auto_inventory').defaultTo(true);
        table.boolean('auto_description').defaultTo(true);
        table.boolean('auto_images').defaultTo(true);
        table.timestamps(true, true);
        
        table.index(['tenant_id', 'shop_id', 'enabled'], 'idx_config_enabled');
      });
      logger.info(`✅ Table ${this.TABLE_NAME_CONFIG} created`);
    }
  }

  private static async initResultsTable() {
    const hasTable = await db.schema.hasTable(this.TABLE_NAME_RESULTS);
    if (!hasTable) {
      logger.info(`Creating ${this.TABLE_NAME_RESULTS} table...`);
      await db.schema.createTable(this.TABLE_NAME_RESULTS, (table) => {
        table.increments('id').primary();
        table.string('task_id').notNullable().index();
        table.string('product_id', 100).notNullable();
        table.string('platform', 50).notNullable();
        table.boolean('success').notNullable();
        table.text('error');
        table.string('platform_product_id', 100);
        table.string('listing_url', 500);
        table.timestamps(true, true);
        
        table.index(['task_id', 'platform'], 'idx_results_task_platform');
        table.index(['product_id', 'platform'], 'idx_results_product_platform');
      });
      logger.info(`✅ Table ${this.TABLE_NAME_RESULTS} created`);
    }
  }

  /**
   * 获取或创建自动上架配置
   */
  static async getConfig(tenantId: string, shopId: string): Promise<AutoListingConfig | null> {
    const config = await db(this.TABLE_NAME_CONFIG)
      .where({ tenant_id: tenantId, shop_id: shopId })
      .first();

    if (!config) return null;

    return {
      ...config,
      target_platforms: JSON.parse(config.target_platforms),
    };
  }

  /**
   * 创建自动上架配置
   */
  static async createConfig(config: Omit<AutoListingConfig, 'id' | 'created_at' | 'updated_at'>): Promise<AutoListingConfig> {
    const [id] = await db(this.TABLE_NAME_CONFIG).insert({
      ...config,
      target_platforms: JSON.stringify(config.target_platforms),
      created_at: new Date(),
      updated_at: new Date(),
    }).returning('id');

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

  /**
   * 更新自动上架配置
   */
  static async updateConfig(
    tenantId: string,
    shopId: string,
    updates: Partial<AutoListingConfig>
  ): Promise<void> {
    const updateData: any = { ...updates, updated_at: new Date() };
    if (updates.target_platforms) {
      updateData.target_platforms = JSON.stringify(updates.target_platforms);
    }
    await db(this.TABLE_NAME_CONFIG)
      .where({ tenant_id: tenantId, shop_id: shopId })
      .update(updateData);
  }

  /**
   * 切换自动上架启用状态
   */
  static async toggleAutoListing(tenantId: string, shopId: string): Promise<boolean> {
    const config = await this.getConfig(tenantId, shopId);
    if (!config) {
      throw new Error('Auto listing config not found');
    }

    const newEnabled = !config.enabled;
    await this.updateConfig(tenantId, shopId, { enabled: newEnabled });

    if (newEnabled) {
      await this.scheduleNextRun(tenantId, shopId);
    } else {
      await this.cancelScheduledRun(tenantId, shopId);
    }

    return newEnabled;
  }

  /**
   * 创建上架任务
   */
  static async createListingTask(
    tenantId: string,
    shopId: string,
    productId: string,
    productName: string,
    targetPlatforms: string[]
  ): Promise<ListingTask> {
    const [id] = await db(this.TABLE_NAME_TASKS).insert({
      tenant_id: tenantId,
      shop_id: shopId,
      product_id: productId,
      product_name: productName,
      target_platforms: JSON.stringify(targetPlatforms),
      status: 'PENDING',
      progress: 0,
      created_at: new Date(),
      updated_at: new Date(),
    }).returning('id');

    return {
      id: id.toString(),
      tenant_id: tenantId,
      shop_id: shopId,
      product_id: productId,
      product_name: productName,
      target_platforms: targetPlatforms,
      status: 'PENDING',
      progress: 0,
      created_at: new Date(),
      updated_at: new Date(),
    };
  }

  /**
   * 批量创建上架任务
   */
  static async batchCreateListingTasks(
    tenantId: string,
    shopId: string,
    products: Array<{ product_id: string; product_name: string }>,
    targetPlatforms: string[]
  ): Promise<ListingTask[]> {
    const now = new Date();
    const tasks = products.map(product => ({
      tenant_id: tenantId,
      shop_id: shopId,
      product_id: product.product_id,
      product_name: product.product_name,
      target_platforms: JSON.stringify(targetPlatforms),
      status: 'PENDING',
      progress: 0,
      created_at: now,
      updated_at: now,
    }));

    const ids = await db(this.TABLE_NAME_TASKS).insert(tasks).returning('id');
    return tasks.map((task, index) => ({
      ...task,
      id: ids[index].toString(),
      target_platforms: targetPlatforms,
    }));
  }

  /**
   * 获取上架任务
   */
  static async getListingTask(taskId: string): Promise<ListingTask | null> {
    const task = await db(this.TABLE_NAME_TASKS).where({ id: taskId }).first();
    if (!task) return null;

    return {
      ...task,
      target_platforms: JSON.parse(task.target_platforms),
    };
  }

  /**
   * 获取租户的上架任务列表
   */
  static async getListingTasks(
    tenantId: string,
    shopId: string,
    status?: 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED',
    limit: number = 50,
    offset: number = 0
  ): Promise<ListingTask[]> {
    let query = db(this.TABLE_NAME_TASKS)
      .where({ tenant_id: tenantId, shop_id: shopId });

    if (status) {
      query = query.where({ status });
    }

    const tasks = await query
      .orderBy('created_at', 'desc')
      .limit(limit)
      .offset(offset);

    return tasks.map(task => ({
      ...task,
      target_platforms: JSON.parse(task.target_platforms),
    }));
  }

  /**
   * 执行上架任务
   */
  static async executeListingTask(taskId: string): Promise<void> {
    const task = await this.getListingTask(taskId);
    if (!task) {
      throw new Error(`Task ${taskId} not found`);
    }

    if (task.status !== 'PENDING') {
      throw new Error(`Task ${taskId} is not in PENDING status`);
    }

    await db(this.TABLE_NAME_TASKS).where({ id: taskId }).update({
      status: 'PROCESSING',
      progress: 0,
      updated_at: new Date(),
    });

    try {
      const config = await this.getConfig(task.tenant_id, task.shop_id);
      if (!config || !config.enabled) {
        throw new Error('Auto listing is not enabled');
      }

      const totalPlatforms = task.target_platforms.length;
      const results: ListingResult[] = [];

      for (let i = 0; i < task.target_platforms.length; i++) {
        const platform = task.target_platforms[i];
        const progress = Math.round(((i + 1) / totalPlatforms) * 100);

        try {
          const result = await this.listToPlatform(
            task.tenant_id,
            task.shop_id,
            task.product_id,
            platform,
            config
          );
          results.push(result);

          await db(this.TABLE_NAME_TASKS).where({ id: taskId }).update({
            progress,
            updated_at: new Date(),
          });
        } catch (error) {
          logger.error(`Failed to list product ${task.product_id} to ${platform}:`, error);
          results.push({
            task_id: taskId,
            product_id: task.product_id,
            platform,
            success: false,
            error: error.message,
          });
        }
      }

      const allSuccess = results.every(r => r.success);
      const status = allSuccess ? 'COMPLETED' : 'FAILED';

      await db(this.TABLE_NAME_TASKS).where({ id: taskId }).update({
        status,
        progress: 100,
        completed_at: new Date(),
        updated_at: new Date(),
      });

      for (const result of results) {
        await db(this.TABLE_NAME_RESULTS).insert({
          task_id: taskId,
          product_id: result.product_id,
          platform: result.platform,
          success: result.success,
          error: result.error,
          platform_product_id: result.platform_product_id,
          listing_url: result.listing_url,
          created_at: new Date(),
          updated_at: new Date(),
        });
      }

      await EventBusService.emit('listing.task.completed', {
        task_id: taskId,
        status,
        results,
      });

    } catch (error) {
      logger.error(`Failed to execute listing task ${taskId}:`, error);
      await db(this.TABLE_NAME_TASKS).where({ id: taskId }).update({
        status: 'FAILED',
        progress: 0,
        error_message: error.message,
        updated_at: new Date(),
      });
      throw error;
    }
  }

  /**
   * 将商品上架到指定平台
   */
  private static async listToPlatform(
    tenantId: string,
    shopId: string,
    productId: string,
    platform: string,
    config: AutoListingConfig
  ): Promise<ListingResult> {
    const product = await ProductService.getProductById(productId);
    if (!product) {
      throw new Error(`Product ${productId} not found`);
    }

    let listingData: any = {
      title: product.title,
      description: product.description,
      price: parseFloat(product.price),
      currency: product.currency,
      images: product.images ? JSON.parse(product.images) : [],
      attributes: product.attributes ? JSON.parse(product.attributes) : {},
    };

    if (config.auto_pricing) {
      const pricing = await PricingService.calculateOptimalPrice(productId, platform);
      listingData.price = pricing.price;
      listingData.currency = pricing.currency;
    }

    if (config.auto_description) {
      const enhancedDescription = await AIService.enhanceProductDescription(
        product.title,
        product.description || '',
        platform
      );
      listingData.description = enhancedDescription;
    }

    if (config.auto_images) {
      const optimizedImages = await AIService.optimizeProductImages(
        product.images ? JSON.parse(product.images) : [],
        platform
      );
      listingData.images = optimizedImages;
    }

    const result = await PublishService.publishToPlatform(
      tenantId,
      shopId,
      productId,
      platform,
      listingData
    );

    return {
      task_id: '',
      product_id: productId,
      platform,
      success: result.success,
      error: result.error,
      platform_product_id: result.platform_product_id,
      listing_url: result.listing_url,
    };
  }

  /**
   * 重试失败的上架任务
   */
  static async retryListingTask(taskId: string): Promise<void> {
    const task = await this.getListingTask(taskId);
    if (!task) {
      throw new Error(`Task ${taskId} not found`);
    }

    if (task.status !== 'FAILED') {
      throw new Error(`Task ${taskId} is not in FAILED status`);
    }

    await db(this.TABLE_NAME_TASKS).where({ id: taskId }).update({
      status: 'PENDING',
      progress: 0,
      error_message: null,
      updated_at: new Date(),
    });

    await this.executeListingTask(taskId);
  }

  /**
   * 删除上架任务
   */
  static async deleteListingTask(taskId: string): Promise<void> {
    await db(this.TABLE_NAME_TASKS).where({ id: taskId }).delete();
    await db(this.TABLE_NAME_RESULTS).where({ task_id: taskId }).delete();
  }

  /**
   * 执行自动上架（批量）
   */
  static async executeAutoListing(tenantId: string, shopId: string): Promise<number> {
    const config = await this.getConfig(tenantId, shopId);
    if (!config || !config.enabled) {
      throw new Error('Auto listing is not enabled');
    }

    const selectedProducts = await ProductSelectionService.getFromPool(
      tenantId,
      shopId,
      undefined,
      config.batch_size,
      0
    );

    if (selectedProducts.length === 0) {
      logger.info(`No products to list for tenant ${tenantId}, shop ${shopId}`);
      return 0;
    }

    const tasks = await this.batchCreateListingTasks(
      tenantId,
      shopId,
      selectedProducts.map(p => ({
        product_id: p.product_id,
        product_name: p.name,
      })),
      config.target_platforms
    );

    for (const task of tasks) {
      await BullMQService.addJob('listing.execute', {
        task_id: task.id,
      });
    }

    logger.info(`Created ${tasks.length} listing tasks for tenant ${tenantId}, shop ${shopId}`);

    return tasks.length;
  }

  /**
   * 调度下次自动上架运行
   */
  private static async scheduleNextRun(tenantId: string, shopId: string): Promise<void> {
    const config = await this.getConfig(tenantId, shopId);
    if (!config) return;

    const delay = config.interval_hours * 60 * 60 * 1000;

    await BullMQService.addJob('auto-listing.run', {
      tenant_id: tenantId,
      shop_id: shopId,
    }, {
      delay,
      jobId: `auto-listing-${tenantId}-${shopId}`,
    });

    logger.info(`Scheduled next auto listing run for tenant ${tenantId}, shop ${shopId} in ${config.interval_hours} hours`);
  }

  /**
   * 取消计划的自动上架运行
   */
  private static async cancelScheduledRun(tenantId: string, shopId: string): Promise<void> {
    const jobId = `auto-listing-${tenantId}-${shopId}`;
    await BullMQService.removeJob(jobId);
    logger.info(`Cancelled scheduled auto listing run for tenant ${tenantId}, shop ${shopId}`);
  }

  /**
   * 获取上架统计
   */
  static async getListingStats(tenantId: string, shopId: string): Promise<{
    totalTasks: number;
    pendingTasks: number;
    processingTasks: number;
    completedTasks: number;
    failedTasks: number;
    totalListings: number;
    successListings: number;
    failedListings: number;
  }> {
    const [taskStats] = await db(this.TABLE_NAME_TASKS)
      .where({ tenant_id: tenantId, shop_id: shopId })
      .select(
        db.raw('COUNT(*) as total'),
        db.raw('SUM(CASE WHEN status = ? THEN 1 ELSE 0 END) as pending', ['PENDING']),
        db.raw('SUM(CASE WHEN status = ? THEN 1 ELSE 0 END) as processing', ['PROCESSING']),
        db.raw('SUM(CASE WHEN status = ? THEN 1 ELSE 0 END) as completed', ['COMPLETED']),
        db.raw('SUM(CASE WHEN status = ? THEN 1 ELSE 0 END) as failed', ['FAILED'])
      );

    const [listingStats] = await db(this.TABLE_NAME_RESULTS)
      .join(this.TABLE_NAME_TASKS, `${this.TABLE_NAME_TASKS}.id`, `${this.TABLE_NAME_RESULTS}.task_id`)
      .where(`${this.TABLE_NAME_TASKS}.tenant_id`, tenantId)
      .where(`${this.TABLE_NAME_TASKS}.shop_id`, shopId)
      .select(
        db.raw('COUNT(*) as total'),
        db.raw('SUM(CASE WHEN success = ? THEN 1 ELSE 0 END) as success', [true]),
        db.raw('SUM(CASE WHEN success = ? THEN 1 ELSE 0 END) as failed', [false])
      );

    return {
      totalTasks: taskStats.total || 0,
      pendingTasks: taskStats.pending || 0,
      processingTasks: taskStats.processing || 0,
      completedTasks: taskStats.completed || 0,
      failedTasks: taskStats.failed || 0,
      totalListings: listingStats.total || 0,
      successListings: listingStats.success || 0,
      failedListings: listingStats.failed || 0,
    };
  }

  /**
   * 获取上架结果
   */
  static async getListingResults(taskId: string): Promise<ListingResult[]> {
    const results = await db(this.TABLE_NAME_RESULTS).where({ task_id: taskId });
    return results;
  }

  /**
   * 清理旧的上架任务
   */
  static async cleanupOldTasks(days: number = 30): Promise<number> {
    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - days);

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

    logger.info(`Cleaned up ${deleted} old completed listing tasks`);
    return deleted;
  }
}
