import db from '../config/database';
import { logger } from '../utils/logger';
import { v4 as uuidv4 } from 'uuid';

export interface BlacklistRecord {
  id: string;
  tenant_id: string;
  shop_id: string;
  task_id?: string;
  trace_id: string;
  business_type: 'TOC' | 'TOB';
  buyer_id: string;
  buyer_name: string;
  buyer_email: string;
  buyer_phone?: string;
  platform: string;
  platform_buyer_id: string;
  blacklist_reason: string;
  blacklist_type: 'FRAUD' | 'CHARGEBACK' | 'ABUSE' | 'OTHER';
  risk_score: number;
  blacklist_date: Date;
  expiry_date?: Date;
  status: 'ACTIVE' | 'INACTIVE' | 'EXPIRED';
  evidence?: string;
  created_by: string;
  created_at: Date;
  updated_at: Date;
}

export interface BlacklistFilter {
  tenant_id?: string;
  shop_id?: string;
  platform?: string;
  blacklist_type?: string;
  status?: string;
  start_date?: Date;
  end_date?: Date;
  risk_score_min?: number;
  risk_score_max?: number;
}

export interface BlacklistStatistics {
  total_count: number;
  active_count: number;
  inactive_count: number;
  expired_count: number;
  by_type: Record<string, number>;
  by_platform: Record<string, number>;
  risk_distribution: {
    low: number;
    medium: number;
    high: number;
  };
  recent_additions: number;
}

export default class BlacklistDatabaseService {
  static readonly TABLE_NAME = 'cf_blacklist';

  static async initTable(): Promise<void> {
    const hasTable = await db.schema.hasTable(this.TABLE_NAME);
    if (!hasTable) {
      logger.info(`[BlacklistDatabaseService] Creating ${this.TABLE_NAME} table...`);
      await db.schema.createTable(this.TABLE_NAME, (table) => {
        table.string('id', 36).primary();
        table.string('tenant_id', 64).notNullable().index();
        table.string('shop_id', 64).notNullable().index();
        table.string('task_id', 36);
        table.string('trace_id', 64).notNullable();
        table.enum('business_type', ['TOC', 'TOB']).notNullable();
        table.string('buyer_id', 64).notNullable();
        table.string('buyer_name', 255).notNullable();
        table.string('buyer_email', 255).notNullable().index();
        table.string('buyer_phone', 32);
        table.string('platform', 64).notNullable().index();
        table.string('platform_buyer_id', 64).notNullable().index();
        table.text('blacklist_reason').notNullable();
        table.enum('blacklist_type', ['FRAUD', 'CHARGEBACK', 'ABUSE', 'OTHER']).notNullable().index();
        table.decimal('risk_score', 5, 2).notNullable().index();
        table.datetime('blacklist_date').notNullable().index();
        table.datetime('expiry_date');
        table.enum('status', ['ACTIVE', 'INACTIVE', 'EXPIRED']).notNullable().defaultTo('ACTIVE').index();
        table.text('evidence');
        table.string('created_by', 64).notNullable();
        table.datetime('created_at').notNullable().defaultTo(db.fn.now());
        table.datetime('updated_at').notNullable().defaultTo(db.fn.now());
        
        // 复合索引
        table.index(['tenant_id', 'shop_id']);
        table.index(['platform', 'platform_buyer_id']);
        table.index(['blacklist_date', 'status']);
      });
      logger.info(`[BlacklistDatabaseService] Table ${this.TABLE_NAME} created`);
    }
  }

  static async createBlacklistRecord(record: Omit<BlacklistRecord, 'id' | 'created_at' | 'updated_at'>): Promise<BlacklistRecord> {
    const id = uuidv4();
    const now = new Date();
    
    const newRecord: BlacklistRecord = {
      ...record,
      id,
      created_at: now,
      updated_at: now
    };

    await db(this.TABLE_NAME).insert(newRecord);
    logger.info(`[BlacklistDatabaseService] Blacklist record created: id=${id}, tenantId=${record.tenant_id}, buyerEmail=${record.buyer_email}, traceId=${record.trace_id}`);
    return newRecord;
  }

  static async getBlacklistRecordById(id: string): Promise<BlacklistRecord | null> {
    const record = await db(this.TABLE_NAME).where({ id }).first();
    return record || null;
  }

  static async getBlacklistRecordByPlatform(platform: string, platformBuyerId: string, tenantId?: string): Promise<BlacklistRecord | null> {
    let query = db(this.TABLE_NAME).where({ platform, platform_buyer_id: platformBuyerId });
    if (tenantId) {
      query = query.where({ tenant_id: tenantId });
    }
    const record = await query.first();
    return record || null;
  }

  static async getBlacklistRecords(filter: BlacklistFilter, limit: number = 100, offset: number = 0): Promise<{
    records: BlacklistRecord[];
    total: number;
  }> {
    let query = db(this.TABLE_NAME);

    if (filter.tenant_id) {
      query = query.where({ tenant_id: filter.tenant_id });
    }
    if (filter.shop_id) {
      query = query.where({ shop_id: filter.shop_id });
    }
    if (filter.platform) {
      query = query.where({ platform: filter.platform });
    }
    if (filter.blacklist_type) {
      query = query.where({ blacklist_type: filter.blacklist_type });
    }
    if (filter.status) {
      query = query.where({ status: filter.status });
    }
    if (filter.start_date) {
      query = query.where('blacklist_date', '>=', filter.start_date);
    }
    if (filter.end_date) {
      query = query.where('blacklist_date', '<=', filter.end_date);
    }
    if (filter.risk_score_min !== undefined) {
      query = query.where('risk_score', '>=', filter.risk_score_min);
    }
    if (filter.risk_score_max !== undefined) {
      query = query.where('risk_score', '<=', filter.risk_score_max);
    }

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

    return {
      records: records as BlacklistRecord[],
      total: total ? parseInt(total.count as string) : 0
    };
  }

  static async updateBlacklistRecord(id: string, updates: Partial<BlacklistRecord>): Promise<boolean> {
    const result = await db(this.TABLE_NAME)
      .where({ id })
      .update({
        ...updates,
        updated_at: new Date()
      });

    if (result > 0) {
      logger.info(`[BlacklistDatabaseService] Blacklist record updated: id=${id}, traceId=${updates.trace_id}`);
    }
    return result > 0;
  }

  static async deleteBlacklistRecord(id: string, traceId: string): Promise<boolean> {
    const result = await db(this.TABLE_NAME).where({ id }).del();
    if (result > 0) {
      logger.info(`[BlacklistDatabaseService] Blacklist record deleted: id=${id}, traceId=${traceId}`);
    }
    return result > 0;
  }

  static async getBlacklistStatistics(tenantId?: string): Promise<BlacklistStatistics> {
    let query = db(this.TABLE_NAME);
    if (tenantId) {
      query = query.where({ tenant_id: tenantId });
    }

    const totalCount = await query.count('id as count').first();
    const activeCount = await query.where({ status: 'ACTIVE' }).count('id as count').first();
    const inactiveCount = await query.where({ status: 'INACTIVE' }).count('id as count').first();
    const expiredCount = await query.where({ status: 'EXPIRED' }).count('id as count').first();

    const byType = await query
      .select('blacklist_type', db.raw('count(*) as count'))
      .groupBy('blacklist_type');

    const byPlatform = await query
      .select('platform', db.raw('count(*) as count'))
      .groupBy('platform');

    const lowRisk = await query.where('risk_score', '<', 50).count('id as count').first();
    const mediumRisk = await query.whereBetween('risk_score', [50, 80]).count('id as count').first();
    const highRisk = await query.where('risk_score', '>=', 80).count('id as count').first();

    const thirtyDaysAgo = new Date();
    thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
    const recentAdditions = await query
      .where('blacklist_date', '>=', thirtyDaysAgo)
      .count('id as count')
      .first();

    return {
      total_count: totalCount ? parseInt(totalCount.count as string) : 0,
      active_count: activeCount ? parseInt(activeCount.count as string) : 0,
      inactive_count: inactiveCount ? parseInt(inactiveCount.count as string) : 0,
      expired_count: expiredCount ? parseInt(expiredCount.count as string) : 0,
      by_type: byType.reduce((acc, item) => {
        acc[item.blacklist_type] = parseInt(item.count as string);
        return acc;
      }, {} as Record<string, number>),
      by_platform: byPlatform.reduce((acc, item) => {
        acc[item.platform] = parseInt(item.count as string);
        return acc;
      }, {} as Record<string, number>),
      risk_distribution: {
        low: lowRisk ? parseInt(lowRisk.count as string) : 0,
        medium: mediumRisk ? parseInt(mediumRisk.count as string) : 0,
        high: highRisk ? parseInt(highRisk.count as string) : 0
      },
      recent_additions: recentAdditions ? parseInt(recentAdditions.count as string) : 0
    };
  }

  static async checkExpiredRecords(): Promise<number> {
    const now = new Date();
    const result = await db(this.TABLE_NAME)
      .where('expiry_date', '<', now)
      .where('status', 'ACTIVE')
      .update({ status: 'EXPIRED', updated_at: now });

    if (result > 0) {
      logger.info(`[BlacklistDatabaseService] Updated ${result} expired blacklist records`);
    }
    return result;
  }

  static async importBlacklistRecords(records: Omit<BlacklistRecord, 'id' | 'created_at' | 'updated_at'>[]): Promise<{
    success: number;
    failed: number;
    errors: string[];
  }> {
    let success = 0;
    let failed = 0;
    const errors: string[] = [];

    for (const record of records) {
      try {
        await this.createBlacklistRecord(record);
        success++;
      } catch (error: any) {
        failed++;
        errors.push(`Failed to import record for ${record.buyer_email}: ${error.message}`);
      }
    }

    logger.info(`[BlacklistDatabaseService] Imported ${success} blacklist records, failed ${failed}`);
    return { success, failed, errors };
  }

  static async exportBlacklistRecords(filter?: BlacklistFilter): Promise<BlacklistRecord[]> {
    let query = db(this.TABLE_NAME);

    if (filter) {
      if (filter.tenant_id) {
        query = query.where({ tenant_id: filter.tenant_id });
      }
      if (filter.status) {
        query = query.where({ status: filter.status });
      }
      if (filter.platform) {
        query = query.where({ platform: filter.platform });
      }
    }

    const records = await query.orderBy('blacklist_date', 'desc');
    return records as BlacklistRecord[];
  }

  static async searchBlacklist(query: string, tenantId?: string): Promise<BlacklistRecord[]> {
    let searchQuery = db(this.TABLE_NAME)
      .where('buyer_name', 'like', `%${query}%`)
      .orWhere('buyer_email', 'like', `%${query}%`)
      .orWhere('buyer_phone', 'like', `%${query}%`)
      .orWhere('platform_buyer_id', 'like', `%${query}%`);

    if (tenantId) {
      searchQuery = searchQuery.where({ tenant_id: tenantId });
    }

    const records = await searchQuery.orderBy('blacklist_date', 'desc').limit(100);
    return records as BlacklistRecord[];
  }

  static async isBlacklisted(platform: string, platformBuyerId: string, tenantId?: string): Promise<boolean> {
    const record = await this.getBlacklistRecordByPlatform(platform, platformBuyerId, tenantId);
    return record !== null && record.status === 'ACTIVE';
  }

  static async getBlacklistReasons(platform: string, platformBuyerId: string, tenantId?: string): Promise<string[]> {
    const record = await this.getBlacklistRecordByPlatform(platform, platformBuyerId, tenantId);
    if (!record) {
      return [];
    }
    return [record.blacklist_reason];
  }
}
