import { Request, Response } from 'express';
import { FingerprintEngine } from '../../core/ai/FingerprintEngine';
import { isValidProductStatusTransition } from '../../core/guards/state-transition.guard';
import { PipelineEngine } from '../../core/pipeline/PipelineEngine';
import { StepStatus } from '../../core/pipeline/PipelineTypes';
import { AIService } from '../../services/AIService';
import { AuditService } from '../../services/AuditService';
import { CompetitorPulseService } from '../../services/CompetitorPulseService';
import { ConfigService } from '../../services/ConfigService';
import { CrawlerService } from '../../services/CrawlerService';
import { DynamicPricingService } from '../../services/DynamicPricingService';
import { ProductService } from '../../services/ProductService';
import { SupplierInquiryService } from '../../services/SupplierInquiryService';
import { SupplyChainService } from '../../services/SupplyChainService';
import { CrawlerWorker } from '../../workers/CrawlerWorker';


export class ProductController {
  /**
   * [BIZ_MKT_30] 触发动态调价
   */
  static async triggerDynamicPricing(req: Request, res: Response) {
    const { id } = req.params;
    const { tenantId, shopId } = (req as any).traceContext;

    try {
      // 使用 generatePricingDecision 替代 applyDynamicPricing
      const result = await DynamicPricingService.generatePricingDecision(tenantId, shopId, id as string);
      res.json({ success: true, data: result });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }
  /**
   * [CORE_AUTO_01] 启动自治上架流水线
   */
  static async startAutonomousListing(req: Request, res: Response) {
    const { url, targetPlatforms } = req.body;
    const { tenantId, shopId, traceId, userId } = (req as any).traceContext;

    try {
      const instanceId = await PipelineEngine.start({
        id: 'IAT-LISTING-FLOW',
        name: 'Autonomous Listing Flow',
        steps: [
          { id: 'crawl', type: 'CRAWL', config: { url }, status: StepStatus.PENDING },
          { id: 'optimize', type: 'AI_OPTIMIZE', config: {}, status: StepStatus.PENDING, dependsOn: ['crawl'] },
          { id: 'publish', type: 'MULTI_PUBLISH', config: { platforms: targetPlatforms }, status: StepStatus.PENDING, dependsOn: ['optimize'] }
        ]
      }, {
        tenantId,
        shopId: shopId || '',
        traceId,
        userId,
        variables: { url, targetPlatforms }
      });

      res.json({ success: true, data: { instanceId } });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  /**
   * [CORE_WORK_01] 异步采集接口
   */
  static async collectAsync(req: Request, res: Response) {
    const { url, sandbox } = req.body;
    const { tenantId, shopId, taskId, traceId, userId } = (req as any).traceContext;

    try {
      const job = await CrawlerWorker.submit({
        url,
        sandbox: sandbox === true,
        traceContext: (req as any).traceContext
      });

      await AuditService.log({
        tenantId,
        shopId,
        taskId,
        traceId,
        userId,
        module: 'SYNC',
        action: 'CRAWLER_ASYNC_SUBMIT',
        resourceType: 'product',
        resourceId: url,
        afterSnapshot: { jobId: job.taskId, url },
        result: 'success',
        source: 'console'
      });

      res.json({ success: true, data: { jobId: job.taskId } });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  static async getAll(req: Request, res: Response) {
    const { tenantId } = (req as any).traceContext;
    try {
      const { platform, status } = req.query;
      const products = await ProductService.getAll(tenantId, {
        platform: platform as string,
        status: status as string,
      });
      res.json({ success: true, data: products });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  /**
   * [UX_REVIEW_01] 审核商品
   */
  static async approve(req: Request, res: Response) {
    const { id } = req.params;
    const { decision, reason } = req.body; // decision: 'APPROVE' | 'REJECT'
    const { tenantId, userId, traceId } = (req as any).traceContext;

    try {
      const status = decision === 'APPROVE' ? 'APPROVED' : 'REJECTED';
      await ProductService.update(tenantId, Number(id), { status });

      await AuditService.log({
        tenantId,
        userId,
        traceId,
        module: 'PRODUCT',
        action: 'REVIEW_PRODUCT',
        resourceType: 'product',
        resourceId: id as string,
        metadata: { decision, reason },
        result: 'success',
        source: 'console'
      });

      res.json({ success: true, message: `Product ${decision.toLowerCase()}d successfully` });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  static async getById(req: Request, res: Response) {
    const { tenantId } = (req as any).traceContext;
    try {
      const product = await ProductService.getById(tenantId, Number(req.params.id));
      if (!product) return res.status(404).json({ success: false, error: 'Product not found' });
      res.json({ success: true, data: product });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  static async create(req: Request, res: Response) {
    const { tenantId, shopId, taskId, traceId, userId } = (req as any).traceContext;
    try {
      const id = await ProductService.create(tenantId, req.body);

      await AuditService.log({
        tenantId,
        shopId,
        taskId,
        traceId,
        userId,
        module: 'PRODUCT',
        action: 'CREATE_PRODUCT',
        resourceType: 'product',
        resourceId: String(id),
        afterSnapshot: req.body,
        result: 'success',
        source: 'console'
      });

      res.status(201).json({ success: true, data: { id } });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  static async update(req: Request, res: Response) {
    const id = Number(req.params.id);
    const updateData = req.body;
    const { tenantId, shopId, taskId, traceId, userId, roleCode } = (req as any).traceContext;

    try {
      const beforeSnapshot = await ProductService.getById(tenantId, id);
      if (!beforeSnapshot) {
        return res.status(404).json({ success: false, error: 'Product not found' });
      }

      if (updateData.status) {
        const previousStatus = String(beforeSnapshot.status || 'DRAFTED');
        const nextStatus = String(updateData.status);
        const validTransition = isValidProductStatusTransition(previousStatus, nextStatus);
        if (!validTransition) {
          await AuditService.log({
            tenantId,
            shopId,
            taskId,
            traceId,
            userId,
            roleCode,
            module: 'PRODUCT',
            action: 'INVALID_STATUS_TRANSITION',
            resourceType: 'product',
            resourceId: String(id),
            beforeSnapshot: { status: previousStatus },
            afterSnapshot: { status: nextStatus },
            result: 'failed',
            errorCode: 'INVALID_STATUS_TRANSITION',
            errorMessage: `Invalid status transition: ${previousStatus} -> ${nextStatus}`,
            source: 'console',
          });
          return res.status(400).json({
            success: false,
            error: `Invalid status transition: ${previousStatus} -> ${nextStatus}`,
          });
        }
      }

      await ProductService.update(tenantId, id, updateData);

      const afterSnapshot = await ProductService.getById(tenantId, id);
      await AuditService.logDiff({
        tenantId,
        shopId,
        taskId,
        traceId,
        userId,
        module: 'PRODUCT',
        action: 'UPDATE_PRODUCT',
        resourceType: 'product',
        resourceId: String(id),
        beforeSnapshot,
        afterSnapshot,
        source: 'console'
      });

      res.json({ success: true, data: afterSnapshot });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  static async delete(req: Request, res: Response) {
    const id = Number(req.params.id);
    const { tenantId, shopId, taskId, traceId, userId } = (req as any).traceContext;
    try {
      const beforeSnapshot = await ProductService.getById(tenantId, id);
      if (!beforeSnapshot) return res.status(404).json({ success: false, error: 'Product not found' });

      await ProductService.delete(tenantId, id);

      await AuditService.log({
        tenantId,
        shopId,
        taskId,
        traceId,
        userId,
        module: 'PRODUCT',
        action: 'DELETE_PRODUCT',
        resourceType: 'product',
        resourceId: String(id),
        beforeSnapshot,
        result: 'success',
        source: 'console'
      });

      res.json({ success: true });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  /**
   * [CORE_AI_15] 采集、优化并生成复合指纹
   */
  static async collectAndOptimize(req: Request, res: Response) {
    const { url, sandbox: forceSandbox } = req.query;
    const { tenantId, traceId, userId } = (req as any).traceContext;

    try {
      const configMultiModal = await ConfigService.getConfig('ENABLE_MULTI_MODAL_AI');
      const configSandbox = await ConfigService.getConfig('ENABLE_SANDBOX_CRAWLER');

      const isMultiModalEnabled = configMultiModal?.value === 'true';
      const isSandboxEnabled = forceSandbox === 'true' || configSandbox?.value === 'true';

      const crawler = new CrawlerService();
      let productData = await crawler.crawl(url as string, isSandboxEnabled);

      if (isMultiModalEnabled) {
        const optimized = await AIService.optimizeProduct(productData.title || '', productData.attributes || {});
        productData = { ...productData, title: optimized };
      }

      // 生成复合指纹
      const fingerprint = await FingerprintEngine.generateCompositeFingerprint({
        title: productData.title || '',
        description: productData.description || '',
        mainImage: productData.mainImage || ''
      });

      const id = await ProductService.create(tenantId, { 
        ...productData, 
        phash: fingerprint.phash,
        semantic_hash: fingerprint.semanticHash,
        vector_embedding: JSON.stringify(fingerprint.vectorEmbedding)
      });

      res.json({ success: true, data: { id, ...productData, ...fingerprint, sandboxUsed: isSandboxEnabled } });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  /**
   * [BIZ_PROD_12] 商品全自动清洗与本地化 (Washer)
   */
  static async washAndLocalize(req: Request, res: Response) {
    const id = Number(req.params.id);
    const { targetMarket, targetLang } = req.body;
    const { tenantId, shopId, traceId, userId } = (req as any).traceContext;

    try {
      const result = await ProductService.washAndLocalize(tenantId, id, targetMarket, targetLang);

      await AuditService.log({
        tenantId,
        shopId,
        traceId,
        userId,
        module: 'PRODUCT',
        action: 'PRODUCT_WASH_AND_LOCALIZE',
        resourceType: 'product',
        resourceId: String(id),
        afterSnapshot: result,
        result: 'success',
        source: 'console'
      });

      res.json({ success: true, data: result });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  /**
   * [BIZ_EXT_10] 供应链溯源
   */
  static async traceSource(req: Request, res: Response) {
    const { imageUrl } = req.body;
    const { tenantId } = (req as any).traceContext;
    try {
      const sources = await SupplyChainService.traceSourceFactory(tenantId, '', imageUrl);
      res.json({ success: true, data: sources });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  /**
   * [CORE_AI_50] 利润链路分析
   */
  static async analyzeProfit(req: Request, res: Response) {
    const { productId, consumerPrice } = req.body;
    try {
      const analysis = await SupplyChainService.analyzeProfitChain(Number(productId), Number(consumerPrice));
      res.json({ success: true, data: analysis });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  /**
   * [BIZ_EXT_07] 套利机会分析
   */
  static async analyzeArbitrage(req: Request, res: Response) {
    const { tenantId } = (req as any).traceContext;
    const { id } = req.params;
    try {
      const result = await ProductService.analyzeProductArbitrage(tenantId, Number(id));
      res.json({ success: true, data: result });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  /**
   * 获取动态调价建议
   */
  static async getPriceAdvice(req: Request, res: Response) {
    const id = String(req.params.id);
    const { tenantId, shopId, taskId, traceId, userId } = (req as any).traceContext;
    try {
      // 使用 generatePricingDecision 替代 calculateOptimalPrice
      const advice = await DynamicPricingService.generatePricingDecision(tenantId, shopId, id);

      await AuditService.log({
        tenantId,
        shopId,
        taskId,
        traceId,
        userId,
        module: 'PRODUCT',
        action: 'GET_PRICE_ADVICE',
        resourceType: 'product',
        resourceId: String(id),
        afterSnapshot: advice,
        result: 'success',
        source: 'console'
      });

      res.json({ success: true, data: advice });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  /**
   * 同行竞态检查
   */
  static async checkPulse(req: Request, res: Response) {
    const id = Number(req.params.id);
    const { tenantId, shopId, taskId, traceId, userId } = (req as any).traceContext;
    try {
      const result = await CompetitorPulseService.pulseCheck(id);
      
      await AuditService.log({
        tenantId,
        shopId,
        taskId,
        traceId,
        userId,
        module: 'PRODUCT',
        action: 'CHECK_PULSE',
        resourceType: 'product',
        resourceId: String(id),
        afterSnapshot: result,
        result: 'success',
        source: 'console'
      });

      res.json({ success: true, data: result });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  /**
   * 生成询价单
   */
  static async generateInquiry(req: Request, res: Response) {
    const id = Number(req.params.id);
    const { quantity } = req.body;
    const { tenantId, shopId, taskId, traceId, userId } = (req as any).traceContext;
    try {
      const product = await ProductService.getById(tenantId, id);
      if (!product) return res.status(404).json({ success: false, error: 'Product not found' });

      const inquiry = await SupplierInquiryService.generateInquiry({
        productTitle: product.title || '',
        attributes: product.attributes || {},
        targetQuantity: quantity || 100,
        platform: product.platform
      });

      await AuditService.log({
        tenantId,
        shopId,
        taskId,
        traceId,
        userId,
        module: 'TRADE',
        action: 'GENERATE_INQUIRY',
        resourceType: 'product',
        resourceId: String(id),
        afterSnapshot: inquiry,
        result: 'success',
        source: 'console'
      });

      res.json({ success: true, data: inquiry });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }

  /**
   * 视觉匹配相似产品
   */
  static async findSimilar(req: Request, res: Response) {
    const { imageUrl } = req.query;
    const { tenantId } = (req as any).traceContext;
    try {
      if (!imageUrl) {
        return res.status(400).json({ success: false, error: 'imageUrl is required' });
      }

      const fingerprint = await FingerprintEngine.generateCompositeFingerprint({
        title: '',
        description: '',
        mainImage: imageUrl as string
      });

      const similarProducts = await ProductService.findByFingerprint(tenantId, fingerprint);

      res.json({ success: true, data: similarProducts });
    } catch (err: any) {
      res.status(500).json({ success: false, error: err.message });
    }
  }
}
