import db from '../config/database';
import { logger } from '../utils/logger';
import {
  Merchant,
  MerchantInfo,
  MerchantDocument,
  MerchantFeature,
  FeatureModule,
  Settlement,
  FeeDetail,
  VerifyResult,
  MerchantStatus,
  MerchantTier,
} from '../models/Merchant';

/**
 * [BE-MV001~BE-MV008] 多商户管理服务
 * @description 实现商户注册、认证、功能模块管理、结算等核心功能
 * @taskId BE-MV001, BE-MV002, BE-MV003, BE-MV004, BE-MV005, BE-MV006, BE-MV007, BE-MV008
 * @version 1.0
 */
export class MerchantService {
  private static generateId(prefix: string): string {
    return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }

  private static generateTraceId(): string {
    return `trace_${Date.now()}_${Math.random().toString(36).substr(2, 12)}`;
  }

  /**
   * [BE-MV001] 商户注册与认证
   * @description 注册新商户，状态初始化为 PENDING
   * @param tenantId 租户ID
   * @param info 商户信息
   * @returns 注册成功的商户信息
   */
  static async registerMerchant(
    tenantId: string,
    info: MerchantInfo
  ): Promise<Merchant> {
    const traceId = this.generateTraceId();

    logger.info('[MerchantService] Registering merchant', {
      tenantId,
      companyName: info.companyName,
      traceId,
    });

    try {
      const merchantId = this.generateId('merchant');
      const tier = info.tier || 'BASIC';

      const [merchant] = await db('cf_merchant')
        .insert({
          id: merchantId,
          tenant_id: tenantId,
          company_name: info.companyName,
          business_license: info.businessLicense || null,
          contact_email: info.contactEmail,
          contact_phone: info.contactPhone || null,
          status: 'PENDING',
          tier: tier,
          trace_id: traceId,
          created_at: new Date(),
          updated_at: new Date(),
        })
        .returning('*');

      logger.info('[MerchantService] Merchant registered successfully', {
        merchantId,
        tenantId,
        traceId,
      });

      return this.mapToMerchant(merchant);
    } catch (error: any) {
      logger.error('[MerchantService] Merchant registration failed', {
        tenantId,
        traceId,
        error: error.message,
      });
      throw error;
    }
  }

  /**
   * [BE-MV001] 商户认证验证
   * @description 验证商户资质文件，更新状态
   * @param merchantId 商户ID
   * @param documents 资质文件列表
   * @param reviewerId 审核人ID
   */
  static async verifyMerchant(
    merchantId: string,
    documents: Array<{
      docType: MerchantDocument['docType'];
      docUrl: string;
    }>,
    reviewerId: string
  ): Promise<VerifyResult> {
    const traceId = this.generateTraceId();

    logger.info('[MerchantService] Verifying merchant', {
      merchantId,
      traceId,
      reviewerId,
    });

    try {
      const merchant = await db('cf_merchant').where({ id: merchantId }).first();
      if (!merchant) {
        return {
          success: false,
          merchantId,
          status: 'PENDING',
          message: 'Merchant not found',
        };
      }

      for (const doc of documents) {
        await db('cf_merchant_document').insert({
          id: this.generateId('doc'),
          merchant_id: merchantId,
          doc_type: doc.docType,
          doc_url: doc.docUrl,
          status: 'PENDING',
          trace_id: traceId,
          created_at: new Date(),
        });
      }

      const allDocsApproved = documents.length > 0;
      const newStatus: MerchantStatus = allDocsApproved ? 'ACTIVE' : 'PENDING';

      await db('cf_merchant').where({ id: merchantId }).update({
        status: newStatus,
        updated_at: new Date(),
      });

      logger.info('[MerchantService] Merchant verification completed', {
        merchantId,
        newStatus,
        traceId,
      });

      return {
        success: true,
        merchantId,
        status: newStatus,
        message: `Merchant ${newStatus === 'ACTIVE' ? 'verified and activated' : 'pending review'}`,
      };
    } catch (error: any) {
      logger.error('[MerchantService] Merchant verification failed', {
        merchantId,
        traceId,
        error: error.message,
      });
      throw error;
    }
  }

  /**
   * [BE-MV002] 商户店铺管理 - 创建店铺
   * @description 为商户创建店铺
   */
  static async createMerchantShop(
    merchantId: string,
    shopInfo: {
      platform: string;
      platformShopId: string;
      name: string;
    }
  ): Promise<any> {
    const traceId = this.generateTraceId();

    logger.info('[MerchantService] Creating merchant shop', {
      merchantId,
      platform: shopInfo.platform,
      traceId,
    });

    try {
      const merchant = await db('cf_merchant').where({ id: merchantId }).first();
      if (!merchant) {
        throw new Error('Merchant not found');
      }

      if (merchant.status !== 'ACTIVE') {
        throw new Error('Merchant is not active');
      }

      const shopId = this.generateId('shop');

      const [shop] = await db('cf_shop')
        .insert({
          id: shopId,
          tenant_id: merchant.tenant_id,
          platform: shopInfo.platform,
          platform_shop_id: shopInfo.platformShopId,
          name: shopInfo.name,
          status: 'ACTIVE',
          trace_id: traceId,
          created_at: new Date(),
          updated_at: new Date(),
        })
        .returning('*');

      logger.info('[MerchantService] Merchant shop created', {
        merchantId,
        shopId,
        traceId,
      });

      return shop;
    } catch (error: any) {
      logger.error('[MerchantService] Shop creation failed', {
        merchantId,
        traceId,
        error: error.message,
      });
      throw error;
    }
  }

  /**
   * [BE-MV003] 功能模块管理 - 获取模块列表
   */
  static async listModules(): Promise<FeatureModule[]> {
    const modules = await db('cf_feature_module')
      .where({ is_active: true })
      .select('*');

    return modules.map((m) => ({
      id: m.id,
      name: m.name,
      code: m.code,
      description: m.description,
      priceMonthly: parseFloat(m.price_monthly),
      priceYearly: parseFloat(m.price_yearly),
      isActive: m.is_active,
      createdAt: m.created_at,
    }));
  }

  /**
   * [BE-MV003] 功能模块管理 - 获取模块配置
   */
  static async getModuleConfig(moduleId: string): Promise<FeatureModule | null> {
    const module = await db('cf_feature_module')
      .where({ id: moduleId, is_active: true })
      .first();

    if (!module) {
      return null;
    }

    return {
      id: module.id,
      name: module.name,
      code: module.code,
      description: module.description,
      priceMonthly: parseFloat(module.price_monthly),
      priceYearly: parseFloat(module.price_yearly),
      isActive: module.is_active,
      createdAt: module.created_at,
    };
  }

  /**
   * [BE-MV004] 功能开通
   * @description 为商户开通功能模块
   */
  static async activateFeature(
    merchantId: string,
    moduleId: string,
    period: 'MONTHLY' | 'YEARLY' = 'MONTHLY'
  ): Promise<MerchantFeature> {
    const traceId = this.generateTraceId();

    logger.info('[MerchantService] Activating feature for merchant', {
      merchantId,
      moduleId,
      period,
      traceId,
    });

    try {
      const merchant = await db('cf_merchant').where({ id: merchantId }).first();
      if (!merchant || merchant.status !== 'ACTIVE') {
        throw new Error('Merchant not found or not active');
      }

      const module = await db('cf_feature_module')
        .where({ id: moduleId, is_active: true })
        .first();
      if (!module) {
        throw new Error('Feature module not found');
      }

      const existingFeature = await db('cf_merchant_feature')
        .where({ merchant_id: merchantId, feature_id: moduleId })
        .where('status', 'ACTIVE')
        .first();

      if (existingFeature) {
        throw new Error('Feature already activated');
      }

      const expireAt = new Date();
      if (period === 'MONTHLY') {
        expireAt.setMonth(expireAt.getMonth() + 1);
      } else {
        expireAt.setFullYear(expireAt.getFullYear() + 1);
      }

      const [feature] = await db('cf_merchant_feature')
        .insert({
          id: this.generateId('mf'),
          merchant_id: merchantId,
          feature_id: moduleId,
          status: 'ACTIVE',
          expire_at: expireAt,
          trace_id: traceId,
          created_at: new Date(),
          updated_at: new Date(),
        })
        .returning('*');

      logger.info('[MerchantService] Feature activated', {
        merchantId,
        moduleId,
        expireAt,
        traceId,
      });

      return {
        id: feature.id,
        merchantId: feature.merchant_id,
        featureId: feature.feature_id,
        status: feature.status,
        expireAt: feature.expire_at,
        traceId: feature.trace_id,
        createdAt: feature.created_at,
        updatedAt: feature.updated_at,
      };
    } catch (error: any) {
      logger.error('[MerchantService] Feature activation failed', {
        merchantId,
        moduleId,
        traceId,
        error: error.message,
      });
      throw error;
    }
  }

  /**
   * [BE-MV005] 费用计算
   * @description 计算商户费用明细
   */
  static async calculateFee(
    merchantId: string,
    periodStart: Date,
    periodEnd: Date
  ): Promise<FeeDetail> {
    const traceId = this.generateTraceId();

    logger.info('[MerchantService] Calculating fee for merchant', {
      merchantId,
      periodStart,
      periodEnd,
      traceId,
    });

    try {
      const merchant = await db('cf_merchant').where({ id: merchantId }).first();
      if (!merchant) {
        throw new Error('Merchant not found');
      }

      const activeFeatures = await db('cf_merchant_feature as mf')
        .join('cf_feature_module as fm', 'mf.feature_id', 'fm.id')
        .where('mf.merchant_id', merchantId)
        .where('mf.status', 'ACTIVE')
        .select('fm.name', 'fm.price_monthly');

      let baseFee = 0;
      switch (merchant.tier) {
        case 'BASIC':
          baseFee = 29.99;
          break;
        case 'PRO':
          baseFee = 99.99;
          break;
        case 'ENTERPRISE':
          baseFee = 299.99;
          break;
      }

      const featureFees = activeFeatures.map((f) => ({
        featureName: f.name,
        amount: parseFloat(f.price_monthly),
      }));

      const usageFee = 0;
      const totalAmount =
        baseFee + usageFee + featureFees.reduce((sum, f) => sum + f.amount, 0);

      return {
        merchantId,
        periodStart,
        periodEnd,
        baseFee,
        usageFee,
        featureFees,
        totalAmount: Math.round(totalAmount * 100) / 100,
      };
    } catch (error: any) {
      logger.error('[MerchantService] Fee calculation failed', {
        merchantId,
        traceId,
        error: error.message,
      });
      throw error;
    }
  }

  /**
   * [BE-MV006] 结算引擎
   * @description 生成商户结算单
   */
  static async generateSettlement(
    merchantId: string,
    periodStart: Date,
    periodEnd: Date
  ): Promise<Settlement> {
    const traceId = this.generateTraceId();

    logger.info('[MerchantService] Generating settlement', {
      merchantId,
      periodStart,
      periodEnd,
      traceId,
    });

    try {
      const feeDetail = await this.calculateFee(merchantId, periodStart, periodEnd);

      const [settlement] = await db('cf_settlement')
        .insert({
          id: this.generateId('settle'),
          merchant_id: merchantId,
          period_start: periodStart,
          period_end: periodEnd,
          total_amount: feeDetail.totalAmount,
          status: 'PENDING',
          trace_id: traceId,
          created_at: new Date(),
          updated_at: new Date(),
        })
        .returning('*');

      logger.info('[MerchantService] Settlement generated', {
        merchantId,
        settlementId: settlement.id,
        totalAmount: feeDetail.totalAmount,
        traceId,
      });

      return {
        id: settlement.id,
        merchantId: settlement.merchant_id,
        periodStart: settlement.period_start,
        periodEnd: settlement.period_end,
        totalAmount: parseFloat(settlement.total_amount),
        status: settlement.status,
        traceId: settlement.trace_id,
        createdAt: settlement.created_at,
        updatedAt: settlement.updated_at,
      };
    } catch (error: any) {
      logger.error('[MerchantService] Settlement generation failed', {
        merchantId,
        traceId,
        error: error.message,
      });
      throw error;
    }
  }

  /**
   * [BE-MV007] 多商户订单拆分
   * @description 根据商户拆分订单
   */
  static async splitOrderByMerchant(
    orderId: string,
    merchantList: Array<{ merchantId: string; itemIds: string[] }>
  ): Promise<Array<{ merchantId: string; subOrderId: string; items: any[] }>> {
    const traceId = this.generateTraceId();

    logger.info('[MerchantService] Splitting order by merchant', {
      orderId,
      merchantCount: merchantList.length,
      traceId,
    });

    try {
      const order = await db('cf_consumer_orders').where({ id: orderId }).first();
      if (!order) {
        throw new Error('Order not found');
      }

      const results: Array<{ merchantId: string; subOrderId: string; items: any[] }> =
        [];

      for (const merchantInfo of merchantList) {
        const subOrderId = this.generateId('suborder');

        const items = await db('cf_order_item')
          .whereIn('id', merchantInfo.itemIds)
          .andWhere('order_id', orderId);

        if (items.length === 0) continue;

        const subOrderTotal = items.reduce(
          (sum, item) => sum + parseFloat(item.unit_price) * item.quantity,
          0
        );

        await db('cf_consumer_orders').insert({
          id: subOrderId,
          tenant_id: order.tenant_id,
          shop_id: order.shop_id,
          platform: order.platform,
          platform_order_id: `${order.platform_order_id}_${merchantInfo.merchantId}`,
          total_amount: subOrderTotal,
          currency: order.currency,
          status: 'PENDING_REVIEW',
          trace_id: traceId,
          task_id: order.task_id,
          business_type: order.business_type,
          created_at: new Date(),
          updated_at: new Date(),
        });

        for (const item of items) {
          await db('cf_order_item').insert({
            id: this.generateId('item'),
            order_id: subOrderId,
            sku_id: item.sku_id,
            unit_price: item.unit_price,
            quantity: item.quantity,
            created_at: new Date(),
          });
        }

        results.push({
          merchantId: merchantInfo.merchantId,
          subOrderId,
          items,
        });

        logger.info('[MerchantService] Sub-order created', {
          orderId,
          subOrderId,
          merchantId: merchantInfo.merchantId,
          itemCount: items.length,
          traceId,
        });
      }

      return results;
    } catch (error: any) {
      logger.error('[MerchantService] Order split failed', {
        orderId,
        traceId,
        error: error.message,
      });
      throw error;
    }
  }

  /**
   * [BE-MV008] 多商户库存同步
   * @description 同步商户库存数据
   */
  static async syncMerchantInventory(
    merchantId: string,
    inventoryData: Array<{
      skuId: string;
      quantity: number;
      warehouseId?: string;
    }>
  ): Promise<{ success: boolean; syncedCount: number }> {
    const traceId = this.generateTraceId();

    logger.info('[MerchantService] Syncing merchant inventory', {
      merchantId,
      itemCount: inventoryData.length,
      traceId,
    });

    try {
      const merchant = await db('cf_merchant').where({ id: merchantId }).first();
      if (!merchant || merchant.status !== 'ACTIVE') {
        throw new Error('Merchant not found or not active');
      }

      let syncedCount = 0;

      for (const item of inventoryData) {
        const existingInventory = await db('cf_inventory')
          .where({
            tenant_id: merchant.tenant_id,
            sku_id: item.skuId,
          })
          .first();

        if (existingInventory) {
          await db('cf_inventory')
            .where({ id: existingInventory.id })
            .update({
              total_qty: item.quantity,
              available_qty: item.quantity - existingInventory.reserved_qty,
              updated_at: new Date(),
            });
        } else {
          await db('cf_inventory').insert({
            id: this.generateId('inv'),
            tenant_id: merchant.tenant_id,
            sku_id: item.skuId,
            warehouse_id: item.warehouseId || 'default',
            total_qty: item.quantity,
            available_qty: item.quantity,
            reserved_qty: 0,
            trace_id: traceId,
            business_type: 'TOC',
            created_at: new Date(),
            updated_at: new Date(),
          });
        }

        syncedCount++;
      }

      logger.info('[MerchantService] Inventory sync completed', {
        merchantId,
        syncedCount,
        traceId,
      });

      return { success: true, syncedCount };
    } catch (error: any) {
      logger.error('[MerchantService] Inventory sync failed', {
        merchantId,
        traceId,
        error: error.message,
      });
      throw error;
    }
  }

  /**
   * 初始化商户相关数据库表
   */
  static async initTables(): Promise<void> {
    const merchantTableExists = await db.schema.hasTable('cf_merchant');
    if (!merchantTableExists) {
      logger.info('📦 Creating cf_merchant table...');
      await db.schema.createTable('cf_merchant', (table) => {
        table.string('id', 64).primary();
        table.string('tenant_id', 64).notNullable();
        table.string('company_name', 255).notNullable();
        table.string('business_license', 100);
        table.string('contact_email', 255).notNullable();
        table.string('contact_phone', 50);
        table.enum('status', ['PENDING', 'ACTIVE', 'SUSPENDED', 'TERMINATED']).defaultTo('PENDING');
        table.enum('tier', ['BASIC', 'PRO', 'ENTERPRISE']).defaultTo('BASIC');
        table.string('trace_id', 64);
        table.timestamps(true, true);

        table.index(['tenant_id']);
        table.index(['status']);
        table.index(['contact_email']);
      });
      logger.info('✅ Table cf_merchant created');
    }

    const merchantDocTableExists = await db.schema.hasTable('cf_merchant_document');
    if (!merchantDocTableExists) {
      logger.info('📦 Creating cf_merchant_document table...');
      await db.schema.createTable('cf_merchant_document', (table) => {
        table.string('id', 64).primary();
        table.string('merchant_id', 64).notNullable();
        table.enum('doc_type', ['BUSINESS_LICENSE', 'TAX_CERTIFICATE', 'IDENTITY_PROOF', 'BANK_STATEMENT']).notNullable();
        table.string('doc_url', 512).notNullable();
        table.enum('status', ['PENDING', 'APPROVED', 'REJECTED']).defaultTo('PENDING');
        table.timestamp('reviewed_at');
        table.string('reviewed_by', 64);
        table.string('trace_id', 64);
        table.timestamp('created_at').defaultTo(db.fn.now());

        table.foreign('merchant_id').references('id').inTable('cf_merchant').onDelete('CASCADE');
        table.index(['merchant_id']);
        table.index(['status']);
      });
      logger.info('✅ Table cf_merchant_document created');
    }

    const featureModuleTableExists = await db.schema.hasTable('cf_feature_module');
    if (!featureModuleTableExists) {
      logger.info('📦 Creating cf_feature_module table...');
      await db.schema.createTable('cf_feature_module', (table) => {
        table.string('id', 64).primary();
        table.string('name', 100).notNullable();
        table.string('code', 50).notNullable().unique();
        table.text('description');
        table.decimal('price_monthly', 10, 2).defaultTo(0);
        table.decimal('price_yearly', 10, 2).defaultTo(0);
        table.boolean('is_active').defaultTo(true);
        table.timestamp('created_at').defaultTo(db.fn.now());

        table.index(['code']);
        table.index(['is_active']);
      });
      logger.info('✅ Table cf_feature_module created');

      await db('cf_feature_module').insert([
        {
          id: 'fm_basic',
          name: '基础功能',
          code: 'BASIC_FEATURES',
          description: '基础商品管理和订单处理',
          price_monthly: 0,
          price_yearly: 0,
          is_active: true,
        },
        {
          id: 'fm_advanced',
          name: '高级分析',
          code: 'ADVANCED_ANALYTICS',
          description: '高级数据分析和报表功能',
          price_monthly: 29.99,
          price_yearly: 299.99,
          is_active: true,
        },
        {
          id: 'fm_ai',
          name: 'AI助手',
          code: 'AI_ASSISTANT',
          description: 'AI智能定价和推荐功能',
          price_monthly: 49.99,
          price_yearly: 499.99,
          is_active: true,
        },
      ]);
      logger.info('✅ Default feature modules created');
    }

    const merchantFeatureTableExists = await db.schema.hasTable('cf_merchant_feature');
    if (!merchantFeatureTableExists) {
      logger.info('📦 Creating cf_merchant_feature table...');
      await db.schema.createTable('cf_merchant_feature', (table) => {
        table.string('id', 64).primary();
        table.string('merchant_id', 64).notNullable();
        table.string('feature_id', 64).notNullable();
        table.enum('status', ['ACTIVE', 'EXPIRED', 'SUSPENDED']).defaultTo('ACTIVE');
        table.timestamp('expire_at');
        table.string('trace_id', 64);
        table.timestamps(true, true);

        table.foreign('merchant_id').references('id').inTable('cf_merchant').onDelete('CASCADE');
        table.foreign('feature_id').references('id').inTable('cf_feature_module').onDelete('CASCADE');
        table.index(['merchant_id']);
        table.index(['feature_id']);
        table.index(['status']);
      });
      logger.info('✅ Table cf_merchant_feature created');
    }

    const settlementTableExists = await db.schema.hasTable('cf_settlement');
    if (!settlementTableExists) {
      logger.info('📦 Creating cf_settlement table...');
      await db.schema.createTable('cf_settlement', (table) => {
        table.string('id', 64).primary();
        table.string('merchant_id', 64).notNullable();
        table.date('period_start').notNullable();
        table.date('period_end').notNullable();
        table.decimal('total_amount', 12, 2).notNullable();
        table.enum('status', ['PENDING', 'PROCESSING', 'COMPLETED']).defaultTo('PENDING');
        table.string('trace_id', 64);
        table.timestamps(true, true);

        table.foreign('merchant_id').references('id').inTable('cf_merchant').onDelete('CASCADE');
        table.index(['merchant_id']);
        table.index(['status']);
        table.index(['period_start', 'period_end']);
      });
      logger.info('✅ Table cf_settlement created');
    }
  }

  private static mapToMerchant(row: any): Merchant {
    return {
      id: row.id,
      tenantId: row.tenant_id,
      companyName: row.company_name,
      businessLicense: row.business_license,
      contactEmail: row.contact_email,
      contactPhone: row.contact_phone,
      status: row.status as MerchantStatus,
      tier: row.tier as MerchantTier,
      traceId: row.trace_id,
      createdAt: row.created_at,
      updatedAt: row.updated_at,
    };
  }
}
