import db from '../config/database';
import { logger } from '../utils/logger';
import { CertificateService } from './CertificateService';
import {
  ComplianceRule,
  ComplianceRuleCreateInput,
  ComplianceRuleQueryOptions,
  ComplianceCheckInput,
  ComplianceCheckResult,
  PlatformType,
  ProductCategory,
  CertificateType,
  ComplianceLevel,
} from '../models/ComplianceRule';

/**
 * ComplianceCheckService - 合规检查引擎
 * 
 * [BE-COM002] 合规检查引擎
 * @description 根据平台和商品类别检查合规证书要求
 * 
 * 功能定位：
 * - 平台合规规则配置管理
 * - 商品合规检查
 * - 缺失证书提醒
 * 
 * 安全约束：
 * - 所有操作必须携带五元组追踪信息
 * - 合规检查结果必须记录日志
 * 
 * @author AI-Backend-7
 * @taskId BE-COM002
 */
export class ComplianceCheckService {
  private static readonly TABLE_NAME = 'cf_compliance_rule';
  private static readonly CHECK_LOG_TABLE = 'cf_compliance_check_log';

  /**
   * 初始化数据库表
   * 遵循幂等性原则：使用 hasTable 前置校验
   */
  static async initTable(): Promise<void> {
    const hasRuleTable = await db.schema.hasTable(this.TABLE_NAME);
    if (!hasRuleTable) {
      logger.info(`[ComplianceCheckService] Creating ${this.TABLE_NAME} table...`);
      await db.schema.createTable(this.TABLE_NAME, (table) => {
        table.string('id', 36).primary();
        table.string('tenant_id', 64).index();
        table.enum('platform', ['AMAZON', 'EBAY', 'SHOPEE', 'ALIEXPRESS', 'TIKTOK', 'TEMU']).notNullable();
        table.enum('product_category', [
          'ELECTRONICS', 'TOYS', 'COSMETICS', 'FOOD', 'MEDICAL',
          'TEXTILES', 'FURNITURE', 'SPORTS', 'AUTOMOTIVE', 'JEWELRY',
          'BOOKS', 'HOME_APPLIANCES', 'OTHER'
        ]).notNullable();
        table.string('target_market', 64);
        table.json('required_certificates').notNullable();
        table.enum('compliance_level', ['REQUIRED', 'RECOMMENDED', 'OPTIONAL']).defaultTo('REQUIRED').notNullable();
        table.text('description');
        table.boolean('is_active').defaultTo(true).notNullable();
        table.timestamp('created_at').defaultTo(db.fn.now());
        table.timestamp('updated_at').defaultTo(db.fn.now());

        table.index(['platform', 'product_category'], 'idx_rule_platform_category');
        table.index(['tenant_id', 'is_active'], 'idx_rule_tenant_active');
      });
      logger.info(`[ComplianceCheckService] Table ${this.TABLE_NAME} created`);
    }

    const hasLogTable = await db.schema.hasTable(this.CHECK_LOG_TABLE);
    if (!hasLogTable) {
      logger.info(`[ComplianceCheckService] Creating ${this.CHECK_LOG_TABLE} table...`);
      await db.schema.createTable(this.CHECK_LOG_TABLE, (table) => {
        table.string('id', 36).primary();
        table.string('tenant_id', 64).notNullable().index();
        table.string('shop_id', 64).notNullable().index();
        table.string('task_id', 64);
        table.string('trace_id', 64).notNullable();
        table.enum('business_type', ['TOC', 'TOB']).notNullable();
        table.string('product_id', 64).notNullable().index();
        table.enum('platform', ['AMAZON', 'EBAY', 'SHOPEE', 'ALIEXPRESS', 'TIKTOK', 'TEMU']).notNullable();
        table.boolean('is_compliant').notNullable();
        table.json('required_certificates');
        table.json('existing_certificates');
        table.json('missing_certificates');
        table.json('expired_certificates');
        table.text('suggestions');
        table.timestamp('checked_at').defaultTo(db.fn.now());

        table.index(['tenant_id', 'product_id'], 'idx_check_tenant_product');
        table.index(['checked_at'], 'idx_check_time');
      });
      logger.info(`[ComplianceCheckService] Table ${this.CHECK_LOG_TABLE} created`);
    }
  }

  /**
   * 创建合规规则
   * @param input 规则创建输入
   * @returns 规则ID
   */
  static async createRule(input: ComplianceRuleCreateInput): Promise<string> {
    const id = this.generateId();
    const now = new Date();

    const rule: Record<string, any> = {
      id,
      tenant_id: input.tenantId || null,
      platform: input.platform,
      product_category: input.productCategory,
      target_market: input.targetMarket || null,
      required_certificates: JSON.stringify(input.requiredCertificates),
      compliance_level: input.complianceLevel,
      description: input.description || null,
      is_active: input.isActive !== undefined ? input.isActive : true,
      created_at: now,
      updated_at: now,
    };

    await db(this.TABLE_NAME).insert(rule);

    logger.info(`[ComplianceCheckService] Rule created: id=${id}, platform=${input.platform}, category=${input.productCategory}, certificates=${input.requiredCertificates.join(',')}`);

    return id;
  }

  /**
   * 获取合规规则
   * @param tenantId 租户ID（可选，为空则获取全局规则）
   * @param platform 平台类型
   * @param productCategory 商品类别
   * @param targetMarket 目标市场（可选）
   * @returns 合规规则列表
   */
  static async getRules(
    tenantId: string | undefined,
    platform: PlatformType,
    productCategory: ProductCategory,
    targetMarket?: string
  ): Promise<ComplianceRule[]> {
    let query = db(this.TABLE_NAME)
      .where('platform', platform)
      .where('product_category', productCategory)
      .where('is_active', true);

    if (tenantId) {
      query = query.where(function(this: any) {
        this.whereNull('tenant_id').orWhere('tenant_id', tenantId);
      });
    } else {
      query = query.whereNull('tenant_id');
    }

    if (targetMarket) {
      query = query.where(function(this: any) {
        this.whereNull('target_market').orWhere('target_market', targetMarket);
      });
    }

    const rows = await query.orderBy('compliance_level', 'asc');

    return rows.map(row => this.mapRowToRule(row));
  }

  /**
   * 查询合规规则列表
   * @param options 查询选项
   * @returns 规则列表和总数
   */
  static async queryRules(
    options: ComplianceRuleQueryOptions
  ): Promise<{ data: ComplianceRule[]; total: number }> {
    const { page = 1, pageSize = 20 } = options;
    const offset = (page - 1) * pageSize;

    let query = db(this.TABLE_NAME);

    if (options.tenantId) {
      query = query.where('tenant_id', options.tenantId);
    }
    if (options.platform) {
      query = query.where('platform', options.platform);
    }
    if (options.productCategory) {
      query = query.where('product_category', options.productCategory);
    }
    if (options.targetMarket) {
      query = query.where('target_market', options.targetMarket);
    }
    if (options.isActive !== undefined) {
      query = query.where('is_active', options.isActive);
    }

    const totalQuery = query.clone();
    const [{ count }] = await totalQuery.count('* as count');
    const total = Number(count);

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

    const data = rows.map(row => this.mapRowToRule(row));

    return { data, total };
  }

  /**
   * 更新合规规则
   * @param id 规则ID
   * @param input 更新输入
   * @returns 是否更新成功
   */
  static async updateRule(
    id: string,
    input: Partial<ComplianceRuleCreateInput>
  ): Promise<boolean> {
    const updateData: Record<string, any> = {
      updated_at: new Date(),
    };

    if (input.platform !== undefined) {
      updateData.platform = input.platform;
    }
    if (input.productCategory !== undefined) {
      updateData.product_category = input.productCategory;
    }
    if (input.targetMarket !== undefined) {
      updateData.target_market = input.targetMarket;
    }
    if (input.requiredCertificates !== undefined) {
      updateData.required_certificates = JSON.stringify(input.requiredCertificates);
    }
    if (input.complianceLevel !== undefined) {
      updateData.compliance_level = input.complianceLevel;
    }
    if (input.description !== undefined) {
      updateData.description = input.description;
    }
    if (input.isActive !== undefined) {
      updateData.is_active = input.isActive;
    }

    const affectedRows = await db(this.TABLE_NAME)
      .where({ id })
      .update(updateData);

    logger.info(`[ComplianceCheckService] Rule updated: id=${id}, affectedRows=${affectedRows}`);

    return affectedRows > 0;
  }

  /**
   * 删除合规规则
   * @param id 规则ID
   * @returns 是否删除成功
   */
  static async deleteRule(id: string): Promise<boolean> {
    const affectedRows = await db(this.TABLE_NAME)
      .where({ id })
      .delete();

    logger.info(`[ComplianceCheckService] Rule deleted: id=${id}, affectedRows=${affectedRows}`);

    return affectedRows > 0;
  }

  /**
   * 执行合规检查
   * @param input 检查输入
   * @returns 合规检查结果
   */
  static async checkCompliance(input: ComplianceCheckInput): Promise<ComplianceCheckResult> {
    const {
      tenantId,
      shopId,
      taskId,
      traceId,
      businessType,
      productId,
      platform,
      productCategory = 'OTHER',
      targetMarket,
    } = input;

    logger.info(`[ComplianceCheckService] Starting compliance check: productId=${productId}, platform=${platform}, traceId=${traceId}`);

    const rules = await this.getRules(tenantId, platform, productCategory, targetMarket);

    let requiredCertificates: CertificateType[] = [];
    let complianceLevel: ComplianceLevel = 'REQUIRED';

    if (rules.length > 0) {
      const primaryRule = rules.find(r => r.complianceLevel === 'REQUIRED') || rules[0];
      requiredCertificates = primaryRule.requiredCertificates;
      complianceLevel = primaryRule.complianceLevel;
    }

    const certificateResult = await CertificateService.checkCompliance(
      tenantId,
      productId,
      requiredCertificates
    );

    const existingCertificates = certificateResult.certificates
      .filter(cert => cert.status === 'APPROVED' && new Date(cert.expiryDate) > new Date())
      .map(cert => cert.certificateType);

    const expiredCertificates = certificateResult.certificates
      .filter(cert => cert.status === 'APPROVED' && new Date(cert.expiryDate) <= new Date())
      .map(cert => cert.certificateType);

    const missingCertificates = certificateResult.missing;

    const suggestions = this.generateSuggestions(
      missingCertificates,
      expiredCertificates,
      complianceLevel
    );

    const isCompliant = missingCertificates.length === 0 && expiredCertificates.length === 0;

    const result: ComplianceCheckResult = {
      isCompliant,
      productId,
      platform,
      checkedAt: new Date(),
      requiredCertificates,
      existingCertificates,
      missingCertificates,
      expiredCertificates,
      complianceLevel,
      suggestions,
      traceId,
    };

    await this.saveCheckLog({
      tenantId,
      shopId,
      taskId,
      traceId,
      businessType,
      result,
    });

    logger.info(`[ComplianceCheckService] Compliance check completed: productId=${productId}, isCompliant=${isCompliant}, missing=${missingCertificates.length}, expired=${expiredCertificates.length}, traceId=${traceId}`);

    return result;
  }

  /**
   * 批量合规检查
   * @param inputs 检查输入列表
   * @returns 检查结果列表
   */
  static async batchCheckCompliance(
    inputs: ComplianceCheckInput[]
  ): Promise<ComplianceCheckResult[]> {
    const results: ComplianceCheckResult[] = [];

    for (const input of inputs) {
      try {
        const result = await this.checkCompliance(input);
        results.push(result);
      } catch (error: any) {
        logger.error(`[ComplianceCheckService] Batch check failed: productId=${input.productId}, error=${error.message}`);
        results.push({
          isCompliant: false,
          productId: input.productId,
          platform: input.platform,
          checkedAt: new Date(),
          requiredCertificates: [],
          existingCertificates: [],
          missingCertificates: [],
          expiredCertificates: [],
          complianceLevel: 'REQUIRED',
          suggestions: [`检查失败: ${error.message}`],
          traceId: input.traceId,
        });
      }
    }

    return results;
  }

  /**
   * 获取商品合规状态摘要
   * @param tenantId 租户ID
   * @param productIds 商品ID列表
   * @returns 合规状态摘要
   */
  static async getComplianceSummary(
    tenantId: string,
    productIds: string[]
  ): Promise<Record<string, { isCompliant: boolean; missingCount: number; expiredCount: number }>> {
    const summary: Record<string, { isCompliant: boolean; missingCount: number; expiredCount: number }> = {};

    for (const productId of productIds) {
      const certificates = await CertificateService.getByProductId(tenantId, productId);
      const validCerts = certificates.filter(
        cert => cert.status === 'APPROVED' && new Date(cert.expiryDate) > new Date()
      );
      const expiredCerts = certificates.filter(
        cert => cert.status === 'APPROVED' && new Date(cert.expiryDate) <= new Date()
      );

      summary[productId] = {
        isCompliant: expiredCerts.length === 0,
        missingCount: 0,
        expiredCount: expiredCerts.length,
      };
    }

    return summary;
  }

  /**
   * 初始化默认合规规则
   */
  static async initDefaultRules(): Promise<void> {
    const defaultRules: ComplianceRuleCreateInput[] = [
      {
        platform: 'AMAZON',
        productCategory: 'ELECTRONICS',
        requiredCertificates: ['CE', 'FCC', 'ROHS'],
        complianceLevel: 'REQUIRED',
        description: 'Amazon电子产品合规要求：CE(欧盟)、FCC(美国)、RoHS',
      },
      {
        platform: 'AMAZON',
        productCategory: 'TOYS',
        requiredCertificates: ['CE', 'FDA'],
        complianceLevel: 'REQUIRED',
        description: 'Amazon玩具产品合规要求：CE(欧盟)、FDA(美国)',
      },
      {
        platform: 'AMAZON',
        productCategory: 'COSMETICS',
        requiredCertificates: ['FDA'],
        complianceLevel: 'REQUIRED',
        description: 'Amazon化妆品合规要求：FDA',
      },
      {
        platform: 'EBAY',
        productCategory: 'ELECTRONICS',
        requiredCertificates: ['CE', 'FCC'],
        complianceLevel: 'REQUIRED',
        description: 'eBay电子产品合规要求：CE(欧盟)、FCC(美国)',
      },
      {
        platform: 'SHOPEE',
        productCategory: 'ELECTRONICS',
        requiredCertificates: ['CE', 'ROHS'],
        complianceLevel: 'REQUIRED',
        description: 'Shopee电子产品合规要求：CE、RoHS',
      },
      {
        platform: 'SHOPEE',
        productCategory: 'COSMETICS',
        requiredCertificates: ['FDA'],
        complianceLevel: 'RECOMMENDED',
        description: 'Shopee化妆品建议认证：FDA',
      },
      {
        platform: 'ALIEXPRESS',
        productCategory: 'ELECTRONICS',
        requiredCertificates: ['CE', 'CCC'],
        complianceLevel: 'REQUIRED',
        description: 'AliExpress电子产品合规要求：CE、CCC(中国)',
      },
      {
        platform: 'TIKTOK',
        productCategory: 'ELECTRONICS',
        requiredCertificates: ['CE', 'FCC', 'ROHS'],
        complianceLevel: 'REQUIRED',
        description: 'TikTok Shop电子产品合规要求：CE、FCC、RoHS',
      },
      {
        platform: 'TEMU',
        productCategory: 'ELECTRONICS',
        requiredCertificates: ['CE', 'FCC'],
        complianceLevel: 'REQUIRED',
        description: 'Temu电子产品合规要求：CE、FCC',
      },
    ];

    for (const rule of defaultRules) {
      const existing = await db(this.TABLE_NAME)
        .where({
          platform: rule.platform,
          product_category: rule.productCategory,
        })
        .whereNull('tenant_id')
        .first();

      if (!existing) {
        await this.createRule(rule);
      }
    }

    logger.info(`[ComplianceCheckService] Default rules initialized: count=${defaultRules.length}`);
  }

  /**
   * 保存检查日志
   */
  private static async saveCheckLog(params: {
    tenantId: string;
    shopId: string;
    taskId?: string;
    traceId: string;
    businessType: 'TOC' | 'TOB';
    result: ComplianceCheckResult;
  }): Promise<void> {
    const id = this.generateId();

    await db(this.CHECK_LOG_TABLE).insert({
      id,
      tenant_id: params.tenantId,
      shop_id: params.shopId,
      task_id: params.taskId || null,
      trace_id: params.traceId,
      business_type: params.businessType,
      product_id: params.result.productId,
      platform: params.result.platform,
      is_compliant: params.result.isCompliant ? 1 : 0,
      required_certificates: JSON.stringify(params.result.requiredCertificates),
      existing_certificates: JSON.stringify(params.result.existingCertificates),
      missing_certificates: JSON.stringify(params.result.missingCertificates),
      expired_certificates: JSON.stringify(params.result.expiredCertificates),
      suggestions: params.result.suggestions.join('\n'),
      checked_at: params.result.checkedAt,
    });
  }

  /**
   * 生成建议
   */
  private static generateSuggestions(
    missing: CertificateType[],
    expired: CertificateType[],
    level: ComplianceLevel
  ): string[] {
    const suggestions: string[] = [];

    if (missing.length > 0) {
      if (level === 'REQUIRED') {
        suggestions.push(`【必须】缺少以下证书: ${missing.join(', ')}，请尽快办理`);
      } else if (level === 'RECOMMENDED') {
        suggestions.push(`【建议】缺少以下证书: ${missing.join(', ')}，建议办理以提高产品可信度`);
      } else {
        suggestions.push(`【可选】可考虑办理以下证书: ${missing.join(', ')}`);
      }
    }

    if (expired.length > 0) {
      suggestions.push(`【紧急】以下证书已过期: ${expired.join(', ')}，请立即续期`);
    }

    if (missing.length === 0 && expired.length === 0) {
      suggestions.push('产品合规状态良好，所有必需证书齐全且有效');
    }

    return suggestions;
  }

  /**
   * 生成唯一ID
   */
  private static generateId(): string {
    return `RULE-${Date.now()}-${Math.random().toString(36).substring(2, 10)}`;
  }

  /**
   * 将数据库行映射为规则对象
   */
  private static mapRowToRule(row: Record<string, any>): ComplianceRule {
    return {
      id: row.id,
      tenantId: row.tenant_id,
      platform: row.platform,
      productCategory: row.product_category,
      targetMarket: row.target_market,
      requiredCertificates: JSON.parse(row.required_certificates),
      complianceLevel: row.compliance_level,
      description: row.description,
      isActive: Boolean(row.is_active),
      createdAt: row.created_at,
      updatedAt: row.updated_at,
    };
  }
}
