import { logger } from '../utils/logger';
import ReturnRateDatabaseService, { ReturnRecord, SKUReturnMetrics, ReturnRateThreshold } from './ReturnRateDatabaseService';

export interface CreateReturnRecordRequest {
  tenant_id: string;
  shop_id: string;
  task_id?: string;
  trace_id: string;
  order_id: string;
  order_item_id: string;
  product_id: string;
  sku_id: string;
  platform: string;
  platform_product_id: string;
  platform_sku_id: string;
  buyer_id: string;
  return_id: string;
  return_reason: string;
  return_reason_category: string;
  return_quantity: number;
  refund_amount: number;
  return_type: 'FULL' | 'PARTIAL';
}

export interface MonitorResult {
  success: boolean;
  message?: string;
  metrics?: SKUReturnMetrics;
  threshold?: ReturnRateThreshold;
  error?: string;
}

export interface BatchMonitorResult {
  success: boolean;
  processed: number;
  high_risk_count: number;
  results: MonitorResult[];
}

export default class ReturnRateMonitorService {
  private static instance: ReturnRateMonitorService;

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

  async recordReturn(request: CreateReturnRecordRequest): Promise<{ success: boolean; record?: ReturnRecord; error?: string }> {
    try {
      logger.info(`[ReturnRateMonitorService] Recording return: orderId=${request.order_id}, returnId=${request.return_id}, traceId=${request.trace_id}`);

      const record = await ReturnRateDatabaseService.createReturnRecord({
        ...request,
        return_status: 'PENDING',
        is_accepted: false
      });

      logger.info(`[ReturnRateMonitorService] Return recorded: id=${record.id}, traceId=${request.trace_id}`);
      return { success: true, record };
    } catch (error: any) {
      logger.error(`[ReturnRateMonitorService] Failed to record return: ${error.message}, traceId=${request.trace_id}`);
      return { success: false, error: error.message };
    }
  }

  async updateReturnStatus(returnId: string, status: 'PENDING' | 'APPROVED' | 'REJECTED' | 'COMPLETED', traceId: string, inspectionResult?: string): Promise<{ success: boolean; error?: string }> {
    try {
      logger.info(`[ReturnRateMonitorService] Updating return status: returnId=${returnId}, status=${status}, traceId=${traceId}`);

      await db('cf_return_record')
        .where({ id: returnId })
        .update({
          return_status: status,
          inspection_result: inspectionResult,
          updated_at: new Date()
        });

      if (status === 'COMPLETED') {
        await this.triggerMetricsUpdate(returnId, traceId);
      }

      return { success: true };
    } catch (error: any) {
      logger.error(`[ReturnRateMonitorService] Failed to update return status: ${error.message}, traceId=${traceId}`);
      return { success: false, error: error.message };
    }
  }

  private async triggerMetricsUpdate(returnId: string, traceId: string): Promise<void> {
    try {
      const returnRecord = await db('cf_return_record').where({ id: returnId }).first();
      if (returnRecord) {
        await ReturnRateDatabaseService.updateSKUReturnMetrics(
          returnRecord.tenant_id,
          returnRecord.shop_id,
          returnRecord.product_id,
          returnRecord.sku_id,
          returnRecord.platform,
          30
        );
        logger.info(`[ReturnRateMonitorService] SKU metrics updated for product: ${returnRecord.product_id}, traceId=${traceId}`);
      }
    } catch (error) {
      logger.error(`[ReturnRateMonitorService] Failed to trigger metrics update: ${error}`);
    }
  }

  async calculateSKUReturnMetrics(tenantId: string, shopId: string, productId: string, skuId: string, platform: string, periodDays: number = 30): Promise<MonitorResult> {
    try {
      logger.info(`[ReturnRateMonitorService] Calculating SKU return metrics: tenantId=${tenantId}, productId=${productId}, platform=${platform}, traceId=${traceId}`);

      const metrics = await ReturnRateDatabaseService.updateSKUReturnMetrics(tenantId, shopId, productId, skuId, platform, periodDays);
      
      if (!metrics) {
        return { success: false, error: 'Failed to calculate metrics' };
      }

      const threshold = await ReturnRateDatabaseService.getThreshold(tenantId, platform, shopId);

      logger.info(`[ReturnRateMonitorService] SKU return metrics calculated: returnRate=${metrics.return_rate}%, isHighRisk=${metrics.is_high_risk}, traceId=${traceId}`);
      return {
        success: true,
        metrics,
        threshold: threshold || undefined
      };
    } catch (error: any) {
      logger.error(`[ReturnRateMonitorService] Failed to calculate SKU return metrics: ${error.message}`);
      return { success: false, error: error.message };
    }
  }

  async monitorAllSKUs(tenantId: string, shopId?: string): Promise<BatchMonitorResult> {
    try {
      logger.info(`[ReturnRateMonitorService] Monitoring all SKUs: tenantId=${tenantId}, shopId=${shopId || 'all'}`);

      const products = await db('cf_product')
        .where({ tenant_id: tenantId })
        .where(shopId ? { shop_id: shopId } : {})
        .select('id', 'sku_id', 'platform', 'shop_id');

      let processed = 0;
      let highRiskCount = 0;
      const results: MonitorResult[] = [];

      for (const product of products) {
        const result = await this.calculateSKUReturnMetrics(
          tenantId,
          product.shop_id,
          product.id,
          product.sku_id,
          product.platform,
          30
        );

        if (result.success && result.metrics?.is_high_risk) {
          highRiskCount++;
        }

        results.push(result);
        processed++;
      }

      logger.info(`[ReturnRateMonitorService] SKU monitoring completed: processed=${processed}, highRisk=${highRiskCount}`);
      return { success: true, processed, high_risk_count: highRiskCount, results };
    } catch (error: any) {
      logger.error(`[ReturnRateMonitorService] Failed to monitor all SKUs: ${error.message}`);
      return { success: false, processed: 0, high_risk_count: 0, results: [] };
    }
  }

  async getHighRiskSKUs(tenantId: string, shopId?: string, limit: number = 100): Promise<SKUReturnMetrics[]> {
    try {
      logger.info(`[ReturnRateMonitorService] Getting high risk SKUs: tenantId=${tenantId}`);
      return await ReturnRateDatabaseService.getHighRiskSKUs(tenantId, shopId, limit);
    } catch (error: any) {
      logger.error(`[ReturnRateMonitorService] Failed to get high risk SKUs: ${error.message}`);
      return [];
    }
  }

  async setThreshold(threshold: Omit<ReturnRateThreshold, 'id' | 'created_at' | 'updated_at'>): Promise<{ success: boolean; threshold?: ReturnRateThreshold; error?: string }> {
    try {
      logger.info(`[ReturnRateMonitorService] Setting threshold: tenantId=${threshold.tenant_id}, type=${threshold.threshold_type}, value=${threshold.return_rate_threshold}%`);

      const result = await ReturnRateDatabaseService.setThreshold(threshold);
      return { success: true, threshold: result };
    } catch (error: any) {
      logger.error(`[ReturnRateMonitorService] Failed to set threshold: ${error.message}`);
      return { success: false, error: error.message };
    }
  }

  async getThreshold(tenantId: string, platform?: string, shopId?: string): Promise<ReturnRateThreshold | null> {
    try {
      return await ReturnRateDatabaseService.getThreshold(tenantId, platform, shopId);
    } catch (error: any) {
      logger.error(`[ReturnRateMonitorService] Failed to get threshold: ${error.message}`);
      return null;
    }
  }

  async getAllThresholds(tenantId: string): Promise<ReturnRateThreshold[]> {
    try {
      return await ReturnRateDatabaseService.getAllThresholds(tenantId);
    } catch (error: any) {
      logger.error(`[ReturnRateMonitorService] Failed to get all thresholds: ${error.message}`);
      return [];
    }
  }

  async deleteThreshold(id: string): Promise<{ success: boolean; error?: string }> {
    try {
      const result = await ReturnRateDatabaseService.deleteThreshold(id);
      return { success: result, error: result ? undefined : 'Threshold not found' };
    } catch (error: any) {
      logger.error(`[ReturnRateMonitorService] Failed to delete threshold: ${error.message}`);
      return { success: false, error: error.message };
    }
  }

  async getReturnRateTrend(tenantId: string, productId: string, days: number = 90): Promise<{ date: string; rate: number }[]> {
    try {
      return await ReturnRateDatabaseService.getReturnRateTrend(tenantId, productId, days);
    } catch (error: any) {
      logger.error(`[ReturnRateMonitorService] Failed to get return rate trend: ${error.message}`);
      return [];
    }
  }

  async getReturnRecords(filter: {
    tenant_id?: string;
    shop_id?: string;
    product_id?: string;
    sku_id?: string;
    platform?: string;
    return_status?: string;
    start_date?: Date;
    end_date?: Date;
  }, limit: number = 100, offset: number = 0): Promise<{ records: ReturnRecord[]; total: number }> {
    try {
      return await ReturnRateDatabaseService.getReturnRecords(filter, limit, offset);
    } catch (error: any) {
      logger.error(`[ReturnRateMonitorService] Failed to get return records: ${error.message}`);
      return { records: [], total: 0 };
    }
  }

  async startScheduledMonitoring(tenantId: string, intervalHours: number = 24): Promise<void> {
    logger.info(`[ReturnRateMonitorService] Starting scheduled monitoring: tenantId=${tenantId}, interval=${intervalHours}h`);

    setInterval(async () => {
      try {
        await this.monitorAllSKUs(tenantId);
        logger.info(`[ReturnRateMonitorService] Scheduled monitoring completed for tenant: ${tenantId}`);
      } catch (error) {
        logger.error(`[ReturnRateMonitorService] Scheduled monitoring failed: ${error}`);
      }
    }, intervalHours * 60 * 60 * 1000);
  }
}

import db from '../config/database';
const traceId = '';
