import { logger } from '../utils/logger';
import BlacklistDatabaseService, { BlacklistRecord } from './BlacklistDatabaseService';
import BlacklistService from './BlacklistService';

export interface ShareRule {
  id: string;
  tenant_id: string;
  shop_ids: string[];
  share_level: 'TENANT' | 'GROUP' | 'GLOBAL';
  platform_filter: string[];
  type_filter: string[];
  min_risk_score: number;
  expiration_days: number;
  auto_accept: boolean;
  created_by: string;
  created_at: Date;
  updated_at: Date;
}

export interface ShareRequest {
  id: string;
  source_tenant_id: string;
  source_shop_id: string;
  target_tenant_id: string;
  target_shop_id: string;
  blacklist_ids: string[];
  share_reason: string;
  status: 'PENDING' | 'ACCEPTED' | 'REJECTED';
  shared_at: Date;
  processed_at?: Date;
  processed_by?: string;
  processed_reason?: string;
}

export interface BlacklistShare {
  id: string;
  source_tenant_id: string;
  source_shop_id: string;
  target_tenant_id: string;
  target_shop_id: string;
  blacklist_id: string;
  shared_at: Date;
  status: 'ACTIVE' | 'INACTIVE';
  share_reason: string;
  risk_score: number;
  blacklist_type: string;
}

export interface ShareStats {
  total_shared: number;
  accepted: number;
  rejected: number;
  pending: number;
  by_platform: Record<string, number>;
  by_type: Record<string, number>;
  recent_shares: number;
}

export interface ShareResponse {
  success: boolean;
  message?: string;
  data?: any;
  error?: string;
}

export interface ShareRequestResponse {
  success: boolean;
  request_id?: string;
  message?: string;
  error?: string;
}

export default class BlacklistShareService {
  private static instance: BlacklistShareService;
  private blacklistService: BlacklistService;

  static getInstance(): BlacklistShareService {
    if (!BlacklistShareService.instance) {
      BlacklistShareService.instance = new BlacklistShareService();
    }
    return BlacklistShareService.instance;
  }

  constructor() {
    this.blacklistService = BlacklistService.getInstance();
  }

  async initTables(): Promise<void> {
    // 初始化共享规则表
    const hasShareRulesTable = await db.schema.hasTable('cf_blacklist_share_rule');
    if (!hasShareRulesTable) {
      logger.info('[BlacklistShareService] Creating cf_blacklist_share_rule table...');
      await db.schema.createTable('cf_blacklist_share_rule', (table) => {
        table.string('id', 36).primary();
        table.string('tenant_id', 64).notNullable().index();
        table.json('shop_ids').notNullable();
        table.enum('share_level', ['TENANT', 'GROUP', 'GLOBAL']).notNullable();
        table.json('platform_filter').notNullable();
        table.json('type_filter').notNullable();
        table.decimal('min_risk_score', 5, 2).notNullable();
        table.integer('expiration_days').notNullable();
        table.boolean('auto_accept').notNullable().defaultTo(false);
        table.string('created_by', 64).notNullable();
        table.datetime('created_at').notNullable().defaultTo(db.fn.now());
        table.datetime('updated_at').notNullable().defaultTo(db.fn.now());
      });
    }

    // 初始化共享请求表
    const hasShareRequestsTable = await db.schema.hasTable('cf_blacklist_share_request');
    if (!hasShareRequestsTable) {
      logger.info('[BlacklistShareService] Creating cf_blacklist_share_request table...');
      await db.schema.createTable('cf_blacklist_share_request', (table) => {
        table.string('id', 36).primary();
        table.string('source_tenant_id', 64).notNullable().index();
        table.string('source_shop_id', 64).notNullable();
        table.string('target_tenant_id', 64).notNullable().index();
        table.string('target_shop_id', 64).notNullable();
        table.json('blacklist_ids').notNullable();
        table.text('share_reason').notNullable();
        table.enum('status', ['PENDING', 'ACCEPTED', 'REJECTED']).notNullable().defaultTo('PENDING');
        table.datetime('shared_at').notNullable().defaultTo(db.fn.now());
        table.datetime('processed_at');
        table.string('processed_by', 64);
        table.text('processed_reason');
      });
    }

    // 初始化共享记录表
    const hasShareTable = await db.schema.hasTable('cf_blacklist_share');
    if (!hasShareTable) {
      logger.info('[BlacklistShareService] Creating cf_blacklist_share table...');
      await db.schema.createTable('cf_blacklist_share', (table) => {
        table.string('id', 36).primary();
        table.string('source_tenant_id', 64).notNullable().index();
        table.string('source_shop_id', 64).notNullable();
        table.string('target_tenant_id', 64).notNullable().index();
        table.string('target_shop_id', 64).notNullable();
        table.string('blacklist_id', 36).notNullable().index();
        table.datetime('shared_at').notNullable().defaultTo(db.fn.now());
        table.enum('status', ['ACTIVE', 'INACTIVE']).notNullable().defaultTo('ACTIVE');
        table.text('share_reason').notNullable();
        table.decimal('risk_score', 5, 2).notNullable();
        table.string('blacklist_type', 32).notNullable();
      });
    }
  }

  async createShareRule(rule: Omit<ShareRule, 'id' | 'created_at' | 'updated_at'>): Promise<ShareResponse> {
    try {
      const id = uuidv4();
      const now = new Date();
      
      const newRule: ShareRule = {
        ...rule,
        id,
        created_at: now,
        updated_at: now
      };

      await db('cf_blacklist_share_rule').insert(newRule);
      logger.info(`[BlacklistShareService] Share rule created: id=${id}, tenantId=${rule.tenant_id}`);
      return {
        success: true,
        message: 'Share rule created successfully',
        data: newRule
      };
    } catch (error: any) {
      logger.error(`[BlacklistShareService] Failed to create share rule: ${error.message}`);
      return {
        success: false,
        error: error.message
      };
    }
  }

  async shareBlacklist(sourceTenantId: string, sourceShopId: string, targetTenantId: string, targetShopId: string, blacklistIds: string[], shareReason: string, traceId: string): Promise<ShareRequestResponse> {
    try {
      logger.info(`[BlacklistShareService] Sharing blacklist: source=${sourceTenantId}, target=${targetTenantId}, count=${blacklistIds.length}, traceId=${traceId}`);

      // 验证黑名单记录存在
      const blacklistRecords: BlacklistRecord[] = [];
      for (const id of blacklistIds) {
        const record = await BlacklistDatabaseService.getBlacklistRecordById(id);
        if (!record) {
          return {
            success: false,
            error: `Blacklist record not found: ${id}`
          };
        }
        if (record.tenant_id !== sourceTenantId) {
          return {
            success: false,
            error: `You don't have permission to share this blacklist record: ${id}`
          };
        }
        blacklistRecords.push(record);
      }

      // 检查目标租户的自动接受规则
      const autoAcceptRules = await db('cf_blacklist_share_rule')
        .where({ tenant_id: targetTenantId, auto_accept: true })
        .first();

      const id = uuidv4();
      const now = new Date();
      const shareRequest: ShareRequest = {
        id,
        source_tenant_id: sourceTenantId,
        source_shop_id: sourceShopId,
        target_tenant_id: targetTenantId,
        target_shop_id: targetShopId,
        blacklist_ids: blacklistIds,
        share_reason: shareReason,
        status: autoAcceptRules ? 'ACCEPTED' : 'PENDING',
        shared_at: now,
        processed_at: autoAcceptRules ? now : undefined,
        processed_by: autoAcceptRules ? 'System' : undefined,
        processed_reason: autoAcceptRules ? 'Auto accepted by rule' : undefined
      };

      await db('cf_blacklist_share_request').insert(shareRequest);

      if (autoAcceptRules) {
        // 自动接受共享
        await this.processShareRequest(id, 'ACCEPTED', 'System', 'Auto accepted by rule', traceId);
      }

      logger.info(`[BlacklistShareService] Share request created: id=${id}, status=${shareRequest.status}, traceId=${traceId}`);
      return {
        success: true,
        request_id: id,
        message: `Share request ${autoAcceptRules ? 'auto-accepted' : 'created'}`
      };
    } catch (error: any) {
      logger.error(`[BlacklistShareService] Failed to share blacklist: ${error.message}, traceId=${traceId}`);
      return {
        success: false,
        error: error.message
      };
    }
  }

  async processShareRequest(requestId: string, status: 'ACCEPTED' | 'REJECTED', processedBy: string, processedReason: string, traceId: string): Promise<ShareResponse> {
    try {
      logger.info(`[BlacklistShareService] Processing share request: id=${requestId}, status=${status}, traceId=${traceId}`);

      const request = await db('cf_blacklist_share_request').where({ id: requestId }).first();
      if (!request) {
        return {
          success: false,
          error: 'Share request not found'
        };
      }

      if (request.status !== 'PENDING') {
        return {
          success: false,
          error: 'Share request already processed'
        };
      }

      await db('cf_blacklist_share_request')
        .where({ id: requestId })
        .update({
          status,
          processed_at: new Date(),
          processed_by,
          processed_reason
        });

      if (status === 'ACCEPTED') {
        // 处理接受共享的逻辑
        for (const blacklistId of request.blacklist_ids) {
          const record = await BlacklistDatabaseService.getBlacklistRecordById(blacklistId);
          if (record) {
            // 创建共享记录
            const shareId = uuidv4();
            await db('cf_blacklist_share').insert({
              id: shareId,
              source_tenant_id: request.source_tenant_id,
              source_shop_id: request.source_shop_id,
              target_tenant_id: request.target_tenant_id,
              target_shop_id: request.target_shop_id,
              blacklist_id: blacklistId,
              shared_at: new Date(),
              status: 'ACTIVE',
              share_reason: request.share_reason,
              risk_score: record.risk_score,
              blacklist_type: record.blacklist_type
            });

            // 在目标租户中创建本地黑名单记录
            await BlacklistDatabaseService.createBlacklistRecord({
              tenant_id: request.target_tenant_id,
              shop_id: request.target_shop_id,
              trace_id: traceId,
              business_type: record.business_type,
              buyer_id: record.buyer_id,
              buyer_name: record.buyer_name,
              buyer_email: record.buyer_email,
              buyer_phone: record.buyer_phone,
              platform: record.platform,
              platform_buyer_id: record.platform_buyer_id,
              blacklist_reason: `${record.blacklist_reason} (Shared from ${request.source_tenant_id})`,
              blacklist_type: record.blacklist_type,
              risk_score: record.risk_score,
              blacklist_date: record.blacklist_date,
              expiry_date: record.expiry_date,
              status: 'ACTIVE',
              evidence: record.evidence,
              created_by: processedBy
            });
          }
        }
      }

      logger.info(`[BlacklistShareService] Share request processed: id=${requestId}, status=${status}, traceId=${traceId}`);
      return {
        success: true,
        message: `Share request ${status.toLowerCase()} successfully`
      };
    } catch (error: any) {
      logger.error(`[BlacklistShareService] Failed to process share request: ${error.message}, traceId=${traceId}`);
      return {
        success: false,
        error: error.message
      };
    }
  }

  async getShareRequests(tenantId: string, status?: string, limit: number = 100, offset: number = 0): Promise<{
    requests: ShareRequest[];
    total: number;
  }> {
    try {
      let query = db('cf_blacklist_share_request')
        .where('target_tenant_id', '=', tenantId);

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

      const total = await query.count('id as count').first();
      const requests = await query
        .orderBy('shared_at', 'desc')
        .limit(limit)
        .offset(offset);

      return {
        requests: requests as ShareRequest[],
        total: total ? parseInt(total.count as string) : 0
      };
    } catch (error: any) {
      logger.error(`[BlacklistShareService] Failed to get share requests: ${error.message}`);
      return {
        requests: [],
        total: 0
      };
    }
  }

  async getSharedBlacklists(tenantId: string, shopId?: string): Promise<BlacklistShare[]> {
    try {
      let query = db('cf_blacklist_share')
        .where('target_tenant_id', '=', tenantId);

      if (shopId) {
        query = query.where('target_shop_id', '=', shopId);
      }

      const shares = await query.orderBy('shared_at', 'desc');
      return shares as BlacklistShare[];
    } catch (error: any) {
      logger.error(`[BlacklistShareService] Failed to get shared blacklists: ${error.message}`);
      return [];
    }
  }

  async getShareStatistics(tenantId: string): Promise<ShareStats> {
    try {
      const totalShared = await db('cf_blacklist_share')
        .where('source_tenant_id', '=', tenantId)
        .count('id as count')
        .first();

      const accepted = await db('cf_blacklist_share_request')
        .where('source_tenant_id', '=', tenantId)
        .where('status', '=', 'ACCEPTED')
        .count('id as count')
        .first();

      const rejected = await db('cf_blacklist_share_request')
        .where('source_tenant_id', '=', tenantId)
        .where('status', '=', 'REJECTED')
        .count('id as count')
        .first();

      const pending = await db('cf_blacklist_share_request')
        .where('source_tenant_id', '=', tenantId)
        .where('status', '=', 'PENDING')
        .count('id as count')
        .first();

      const byPlatform = await db('cf_blacklist_share')
        .join('cf_blacklist', 'cf_blacklist_share.blacklist_id', '=', 'cf_blacklist.id')
        .where('cf_blacklist_share.source_tenant_id', '=', tenantId)
        .select('cf_blacklist.platform', db.raw('count(*) as count'))
        .groupBy('cf_blacklist.platform');

      const byType = await db('cf_blacklist_share')
        .where('source_tenant_id', '=', tenantId)
        .select('blacklist_type', db.raw('count(*) as count'))
        .groupBy('blacklist_type');

      const thirtyDaysAgo = new Date();
      thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
      const recentShares = await db('cf_blacklist_share')
        .where('source_tenant_id', '=', tenantId)
        .where('shared_at', '>=', thirtyDaysAgo)
        .count('id as count')
        .first();

      return {
        total_shared: totalShared ? parseInt(totalShared.count as string) : 0,
        accepted: accepted ? parseInt(accepted.count as string) : 0,
        rejected: rejected ? parseInt(rejected.count as string) : 0,
        pending: pending ? parseInt(pending.count as string) : 0,
        by_platform: byPlatform.reduce((acc, item) => {
          acc[item.platform] = parseInt(item.count as string);
          return acc;
        }, {} as Record<string, number>),
        by_type: byType.reduce((acc, item) => {
          acc[item.blacklist_type] = parseInt(item.count as string);
          return acc;
        }, {} as Record<string, number>),
        recent_shares: recentShares ? parseInt(recentShares.count as string) : 0
      };
    } catch (error: any) {
      logger.error(`[BlacklistShareService] Failed to get share statistics: ${error.message}`);
      return {
        total_shared: 0,
        accepted: 0,
        rejected: 0,
        pending: 0,
        by_platform: {},
        by_type: {},
        recent_shares: 0
      };
    }
  }

  async revokeSharedBlacklist(shareId: string, traceId: string): Promise<ShareResponse> {
    try {
      logger.info(`[BlacklistShareService] Revoking shared blacklist: id=${shareId}, traceId=${traceId}`);

      const share = await db('cf_blacklist_share').where({ id: shareId }).first();
      if (!share) {
        return {
          success: false,
          error: 'Shared blacklist not found'
        };
      }

      await db('cf_blacklist_share')
        .where({ id: shareId })
        .update({ status: 'INACTIVE' });

      // 同时在目标租户中停用对应的黑名单记录
      const blacklistRecord = await BlacklistDatabaseService.getBlacklistRecordById(share.blacklist_id);
      if (blacklistRecord) {
        await BlacklistDatabaseService.updateBlacklistRecord(share.blacklist_id, {
          status: 'INACTIVE',
          trace_id: traceId
        });
      }

      logger.info(`[BlacklistShareService] Shared blacklist revoked: id=${shareId}, traceId=${traceId}`);
      return {
        success: true,
        message: 'Shared blacklist revoked successfully'
      };
    } catch (error: any) {
      logger.error(`[BlacklistShareService] Failed to revoke shared blacklist: ${error.message}, traceId=${traceId}`);
      return {
        success: false,
        error: error.message
      };
    }
  }

  async syncSharedBlacklists(tenantId: string, traceId: string): Promise<{
    synced: number;
    failed: number;
  }> {
    try {
      logger.info(`[BlacklistShareService] Syncing shared blacklists for tenant: ${tenantId}, traceId=${traceId}`);

      // 获取该租户的所有活跃共享
      const activeShares = await db('cf_blacklist_share')
        .where('target_tenant_id', '=', tenantId)
        .where('status', '=', 'ACTIVE');

      let synced = 0;
      let failed = 0;

      for (const share of activeShares) {
        try {
          const sourceRecord = await BlacklistDatabaseService.getBlacklistRecordById(share.blacklist_id);
          if (sourceRecord) {
            // 更新本地记录
            await BlacklistDatabaseService.updateBlacklistRecord(share.blacklist_id, {
              risk_score: sourceRecord.risk_score,
              status: sourceRecord.status,
              expiry_date: sourceRecord.expiry_date,
              trace_id: traceId
            });
            synced++;
          }
        } catch (error) {
          failed++;
        }
      }

      logger.info(`[BlacklistShareService] Synced ${synced} shared blacklists, failed ${failed}, traceId=${traceId}`);
      return { synced, failed };
    } catch (error: any) {
      logger.error(`[BlacklistShareService] Failed to sync shared blacklists: ${error.message}, traceId=${traceId}`);
      return { synced: 0, failed: 0 };
    }
  }
}

// 导入必要的依赖
import db from '../config/database';
import { v4 as uuidv4 } from 'uuid';
