import { Logger } from '../utils/Logger';
import { PlatformAdapter, TikTokAdapter, TemuAdapter, ShopeeAdapter } from '../platforms';

interface RefundStatus {
  refundId: string;
  returnId: string;
  orderId: string;
  platform: string;
  shopId: string;
  status: 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'CANCELLED';
  amount: number;
  currency: string;
  method: string;
  processedAt?: string;
  failureReason?: string;
  traceId: string;
}

interface QueryResult {
  refundId: string;
  platform: string;
  status: RefundStatus;
  error?: string;
}

export class RefundQuery {
  private logger = new Logger('RefundQuery');
  private platformAdapters: Map<string, PlatformAdapter> = new Map();
  
  constructor() {
    this.platformAdapters.set('tiktok', new TikTokAdapter());
    this.platformAdapters.set('temu', new TemuAdapter());
    this.platformAdapters.set('shopee', new ShopeeAdapter());
  }
  
  async queryRefundStatus(
    platform: string,
    refundId: string,
    traceId?: string
  ): Promise<RefundStatus> {
    const actualTraceId = traceId || this.generateTraceId();
    
    this.logger.info('Querying refund status', {
      platform,
      refundId,
      traceId: actualTraceId,
    });
    
    const adapter = this.platformAdapters.get(platform.toLowerCase());
    if (!adapter) {
      throw new Error(`Unsupported platform: ${platform}`);
    }
    
    try {
      const status = await adapter.getRefundStatus(refundId, actualTraceId);
      
      this.logger.info('Refund status retrieved', {
        platform,
        refundId,
        status: status.status,
        traceId: actualTraceId,
      });
      
      return status;
    } catch (error: any) {
      this.logger.error('Refund status query failed', {
        platform,
        refundId,
        error: error.message,
        traceId: actualTraceId,
      });
      throw error;
    }
  }
  
  async queryAllRefunds(): Promise<QueryResult[]> {
    this.logger.info('Starting refund status query for all pending refunds');
    
    const pendingRefunds = await this.getPendingRefunds();
    const results: QueryResult[] = [];
    
    for (const refund of pendingRefunds) {
      const traceId = this.generateTraceId();
      
      try {
        const status = await this.queryRefundStatus(
          refund.platform,
          refund.refundId,
          traceId
        );
        
        await this.updateRefundStatus(status, refund.tenantId, traceId);
        
        results.push({
          refundId: refund.refundId,
          platform: refund.platform,
          status,
        });
      } catch (error: any) {
        results.push({
          refundId: refund.refundId,
          platform: refund.platform,
          status: {
            refundId: refund.refundId,
            returnId: refund.returnId,
            orderId: refund.orderId,
            platform: refund.platform,
            shopId: refund.shopId,
            status: 'FAILED',
            amount: refund.amount,
            currency: refund.currency,
            method: 'UNKNOWN',
            failureReason: error.message,
            traceId,
          },
          error: error.message,
        });
      }
    }
    
    this.logger.info('Refund status query completed', {
      totalRefunds: pendingRefunds.length,
      successCount: results.filter(r => !r.error).length,
    });
    
    return results;
  }
  
  async batchQueryRefunds(
    refunds: Array<{
      platform: string;
      refundId: string;
    }>,
    traceId?: string
  ): Promise<QueryResult[]> {
    const actualTraceId = traceId || this.generateTraceId();
    
    this.logger.info('Batch querying refund status', {
      count: refunds.length,
      traceId: actualTraceId,
    });
    
    const results: QueryResult[] = [];
    
    for (const refund of refunds) {
      try {
        const status = await this.queryRefundStatus(
          refund.platform,
          refund.refundId,
          actualTraceId
        );
        
        results.push({
          refundId: refund.refundId,
          platform: refund.platform,
          status,
        });
      } catch (error: any) {
        results.push({
          refundId: refund.refundId,
          platform: refund.platform,
          status: {
            refundId: refund.refundId,
            returnId: '',
            orderId: '',
            platform: refund.platform,
            shopId: '',
            status: 'FAILED',
            amount: 0,
            currency: 'USD',
            method: 'UNKNOWN',
            failureReason: error.message,
            traceId: actualTraceId,
          },
          error: error.message,
        });
      }
    }
    
    return results;
  }
  
  private async getPendingRefunds(): Promise<Array<{
    refundId: string;
    returnId: string;
    orderId: string;
    platform: string;
    shopId: string;
    tenantId: string;
    amount: number;
    currency: string;
  }>> {
    const data = await chrome.storage.local.get('pendingRefunds');
    return data.pendingRefunds || [];
  }
  
  private async updateRefundStatus(
    status: RefundStatus,
    tenantId: string,
    traceId: string
  ): Promise<void> {
    const config = await chrome.storage.local.get('config');
    const apiEndpoint = config.config?.apiEndpoint || 'http://localhost:3003';
    
    const response = await fetch(`${apiEndpoint}/api/refunds/${status.refundId}/status`, {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/json',
        'X-Tenant-Id': tenantId,
        'X-Trace-Id': traceId,
      },
      body: JSON.stringify({
        status: status.status,
        processedAt: status.processedAt,
        failureReason: status.failureReason,
        traceId,
      }),
    });
    
    if (!response.ok) {
      throw new Error(`Status update failed: ${response.status}`);
    }
    
    if (status.status === 'COMPLETED' || status.status === 'CANCELLED') {
      const data = await chrome.storage.local.get('pendingRefunds');
      const pendingRefunds = data.pendingRefunds || [];
      const updatedRefunds = pendingRefunds.filter(
        (r: any) => r.refundId !== status.refundId
      );
      await chrome.storage.local.set({ pendingRefunds: updatedRefunds });
    }
    
    this.logger.info('Refund status updated', {
      refundId: status.refundId,
      status: status.status,
      tenantId,
      traceId,
    });
  }
  
  private generateTraceId(): string {
    return `TRC-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  }
}
