/**
 * [BE-PRICING002] 竞品价格服务
 * 实现竞品价格监控、历史追踪、市场分析和价格预警
 * AI注意: 所有竞品价格数据通过此服务获取和管理
 */

import db from '../config/database';
import { logger } from '../utils/logger';
import RedisService from './RedisService';
import { EventBusService } from './EventBusService';

export interface CompetitorPriceData {
  id: string;
  tenant_id: string;
  shop_id: string;
  product_id: string;
  
  competitor_name: string;
  competitor_shop_id: string;
  competitor_product_id: string;
  platform: string;
  
  price: number;
  shipping_cost: number;
  total_price: number;
  currency: string;
  
  stock_status: 'IN_STOCK' | 'LOW_STOCK' | 'OUT_OF_STOCK';
  stock_quantity?: number;
  
  rating: number;
  review_count: number;
  sales_count?: number;
  
  listing_url: string;
  image_url?: string;
  
  last_checked: Date;
  next_check?: Date;
  
  created_at: Date;
  updated_at: Date;
}

export interface PriceHistoryRecord {
  id: string;
  competitor_price_id: string;
  old_price: number;
  new_price: number;
  price_change: number;
  change_percent: number;
  change_type: 'INCREASE' | 'DECREASE' | 'STABLE';
  checked_at: Date;
}

export interface MarketPriceAnalysis {
  product_id: string;
  analysis_date: Date;
  
  price_range: {
    min: number;
    max: number;
    avg: number;
    median: number;
  };
  
  price_distribution: {
    range: string;
    count: number;
    percentage: number;
  }[];
  
  competitor_ranking: {
    rank: number;
    competitor_name: string;
    price: number;
    market_share?: number;
  }[];
  
  our_position: {
    rank: number;
    percentile: number;
    price_gap_to_lowest: number;
    price_gap_to_avg: number;
  };
  
  recommendations: {
    optimal_price: number;
    expected_position: number;
    reasoning: string;
  };
}

export interface PriceAlert {
  id: string;
  tenant_id: string;
  shop_id: string;
  product_id: string;
  
  alert_type: 'PRICE_DROP' | 'PRICE_INCREASE' | 'OUT_OF_STOCK' | 'BACK_IN_STOCK' | 'NEW_COMPETITOR';
  severity: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
  
  competitor_name: string;
  old_value?: number;
  new_value?: number;
  change_description: string;
  
  is_read: boolean;
  read_at?: Date;
  read_by?: string;
  
  action_taken?: string;
  action_at?: Date;
  
  created_at: Date;
}

export interface CompetitorMonitorConfig {
  id: string;
  tenant_id: string;
  shop_id: string;
  product_id: string;
  
  monitor_enabled: boolean;
  check_frequency: 'HOURLY' | 'EVERY_6_HOURS' | 'DAILY' | 'WEEKLY';
  
  price_alert_threshold: number;
  stock_alert_enabled: boolean;
  
  competitors_to_track: string[];
  platforms_to_track: string[];
  
  auto_adjust_enabled: boolean;
  auto_adjust_rules: {
    follow_lowest: boolean;
    max_price_gap: number;
    min_profit_margin: number;
  };
  
  created_at: Date;
  updated_at: Date;
}

export class CompetitorPriceService {
  private static readonly PRICE_TABLE = 'cf_competitor_prices';
  private static readonly HISTORY_TABLE = 'cf_competitor_price_history';
  private static readonly ALERT_TABLE = 'cf_price_alerts';
  private static readonly CONFIG_TABLE = 'cf_competitor_monitor_configs';
  private static readonly CACHE_PREFIX = 'competitor_price:';
  private static readonly CACHE_TTL = 3600;

  static async initTables() {
    const hasPriceTable = await db.schema.hasTable(this.PRICE_TABLE);
    if (!hasPriceTable) {
      logger.info(`Creating ${this.PRICE_TABLE} table...`);
      await db.schema.createTable(this.PRICE_TABLE, (table) => {
        table.string('id', 50).primary();
        table.string('tenant_id', 50).notNullable().index();
        table.string('shop_id', 50).notNullable().index();
        table.string('product_id', 50).notNullable().index();
        
        table.string('competitor_name', 200).notNullable();
        table.string('competitor_shop_id', 100).notNullable();
        table.string('competitor_product_id', 100).notNullable();
        table.string('platform', 50).notNullable();
        
        table.decimal('price', 10, 2).notNullable();
        table.decimal('shipping_cost', 10, 2).defaultTo(0);
        table.decimal('total_price', 10, 2).notNullable();
        table.string('currency', 10).notNullable().defaultTo('USD');
        
        table.enum('stock_status', ['IN_STOCK', 'LOW_STOCK', 'OUT_OF_STOCK']).notNullable().defaultTo('IN_STOCK');
        table.integer('stock_quantity').nullable();
        
        table.decimal('rating', 3, 2).defaultTo(0);
        table.integer('review_count').defaultTo(0);
        table.integer('sales_count').nullable();
        
        table.string('listing_url', 500).nullable();
        table.string('image_url', 500).nullable();
        
        table.timestamp('last_checked').notNullable();
        table.timestamp('next_check').nullable();
        
        table.timestamp('created_at').notNullable().defaultTo(db.fn.now());
        table.timestamp('updated_at').notNullable().defaultTo(db.fn.now());
        
        table.unique(['product_id', 'competitor_shop_id', 'competitor_product_id']);
        table.index(['tenant_id', 'platform']);
      });
      logger.info(`${this.PRICE_TABLE} table created successfully`);
    }

    const hasHistoryTable = await db.schema.hasTable(this.HISTORY_TABLE);
    if (!hasHistoryTable) {
      logger.info(`Creating ${this.HISTORY_TABLE} table...`);
      await db.schema.createTable(this.HISTORY_TABLE, (table) => {
        table.string('id', 50).primary();
        table.string('competitor_price_id', 50).notNullable().index();
        table.decimal('old_price', 10, 2).notNullable();
        table.decimal('new_price', 10, 2).notNullable();
        table.decimal('price_change', 10, 2).notNullable();
        table.decimal('change_percent', 5, 2).notNullable();
        table.enum('change_type', ['INCREASE', 'DECREASE', 'STABLE']).notNullable();
        table.timestamp('checked_at').notNullable().defaultTo(db.fn.now());
        
        table.index(['competitor_price_id', 'checked_at']);
      });
      logger.info(`${this.HISTORY_TABLE} table created successfully`);
    }

    const hasAlertTable = await db.schema.hasTable(this.ALERT_TABLE);
    if (!hasAlertTable) {
      logger.info(`Creating ${this.ALERT_TABLE} table...`);
      await db.schema.createTable(this.ALERT_TABLE, (table) => {
        table.string('id', 50).primary();
        table.string('tenant_id', 50).notNullable().index();
        table.string('shop_id', 50).notNullable().index();
        table.string('product_id', 50).notNullable().index();
        
        table.enum('alert_type', ['PRICE_DROP', 'PRICE_INCREASE', 'OUT_OF_STOCK', 'BACK_IN_STOCK', 'NEW_COMPETITOR']).notNullable();
        table.enum('severity', ['LOW', 'MEDIUM', 'HIGH', 'CRITICAL']).notNullable();
        
        table.string('competitor_name', 200).notNullable();
        table.decimal('old_value', 10, 2).nullable();
        table.decimal('new_value', 10, 2).nullable();
        table.string('change_description', 500).notNullable();
        
        table.boolean('is_read').notNullable().defaultTo(false);
        table.timestamp('read_at').nullable();
        table.string('read_by', 50).nullable();
        
        table.string('action_taken', 500).nullable();
        table.timestamp('action_at').nullable();
        
        table.timestamp('created_at').notNullable().defaultTo(db.fn.now());
        
        table.index(['tenant_id', 'is_read', 'created_at']);
      });
      logger.info(`${this.ALERT_TABLE} table created successfully`);
    }

    const hasConfigTable = await db.schema.hasTable(this.CONFIG_TABLE);
    if (!hasConfigTable) {
      logger.info(`Creating ${this.CONFIG_TABLE} table...`);
      await db.schema.createTable(this.CONFIG_TABLE, (table) => {
        table.string('id', 50).primary();
        table.string('tenant_id', 50).notNullable().index();
        table.string('shop_id', 50).notNullable().index();
        table.string('product_id', 50).notNullable();
        
        table.boolean('monitor_enabled').notNullable().defaultTo(true);
        table.enum('check_frequency', ['HOURLY', 'EVERY_6_HOURS', 'DAILY', 'WEEKLY']).notNullable().defaultTo('DAILY');
        
        table.decimal('price_alert_threshold', 5, 2).notNullable().defaultTo(5.00);
        table.boolean('stock_alert_enabled').notNullable().defaultTo(true);
        
        table.json('competitors_to_track').nullable();
        table.json('platforms_to_track').nullable();
        
        table.boolean('auto_adjust_enabled').notNullable().defaultTo(false);
        table.json('auto_adjust_rules').nullable();
        
        table.timestamp('created_at').notNullable().defaultTo(db.fn.now());
        table.timestamp('updated_at').notNullable().defaultTo(db.fn.now());
        
        table.unique(['shop_id', 'product_id']);
      });
      logger.info(`${this.CONFIG_TABLE} table created successfully`);
    }
  }

  static async getCompetitorPrices(
    tenantId: string,
    productId: string,
    options?: {
      platform?: string;
      limit?: number;
    }
  ): Promise<CompetitorPriceData[]> {
    const cacheKey = `${this.CACHE_PREFIX}${tenantId}:${productId}:${options?.platform || 'all'}`;
    const cached = await RedisService.get(cacheKey);
    if (cached) {
      return JSON.parse(cached);
    }

    let query = db(this.PRICE_TABLE)
      .where('tenant_id', tenantId)
      .where('product_id', productId)
      .orderBy('total_price', 'asc');

    if (options?.platform) {
      query = query.where('platform', options.platform);
    }

    if (options?.limit) {
      query = query.limit(options.limit);
    }

    const records = await query;
    const result = records.map(this.parsePriceRecord);

    await RedisService.set(cacheKey, JSON.stringify(result), this.CACHE_TTL);
    return result;
  }

  static async updateCompetitorPrice(
    priceData: Partial<CompetitorPriceData> & { id: string }
  ): Promise<CompetitorPriceData> {
    const existing = await db(this.PRICE_TABLE).where('id', priceData.id).first();
    if (!existing) {
      throw new Error('竞品价格记录不存在');
    }

    const oldPrice = parseFloat(existing.total_price);
    const newPrice = priceData.total_price || oldPrice;

    if (Math.abs(newPrice - oldPrice) > 0.01) {
      const priceChange = newPrice - oldPrice;
      const changePercent = (priceChange / oldPrice) * 100;
      const changeType: PriceHistoryRecord['change_type'] = 
        priceChange > 0 ? 'INCREASE' : priceChange < 0 ? 'DECREASE' : 'STABLE';

      await db(this.HISTORY_TABLE).insert({
        id: `PH-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
        competitor_price_id: priceData.id,
        old_price: oldPrice,
        new_price: newPrice,
        price_change: priceChange,
        change_percent: changePercent,
        change_type: changeType,
      });

      if (Math.abs(changePercent) >= parseFloat(existing.price_alert_threshold || '5')) {
        await this.createPriceAlert({
          tenant_id: existing.tenant_id,
          shop_id: existing.shop_id,
          product_id: existing.product_id,
          alert_type: priceChange > 0 ? 'PRICE_INCREASE' : 'PRICE_DROP',
          severity: Math.abs(changePercent) >= 20 ? 'CRITICAL' : Math.abs(changePercent) >= 10 ? 'HIGH' : 'MEDIUM',
          competitor_name: existing.competitor_name,
          old_value: oldPrice,
          new_value: newPrice,
          change_description: `${existing.competitor_name} 价格${priceChange > 0 ? '上涨' : '下降'} ${Math.abs(changePercent).toFixed(2)}%`,
        });
      }
    }

    await db(this.PRICE_TABLE)
      .where('id', priceData.id)
      .update({
        ...priceData,
        last_checked: new Date(),
        updated_at: new Date(),
      });

    const updated = await db(this.PRICE_TABLE).where('id', priceData.id).first();
    
    await RedisService.del(`${this.CACHE_PREFIX}${existing.tenant_id}:${existing.product_id}:all`);
    
    logger.info(`[CompetitorPrice] Updated price for ${priceData.id}: ${oldPrice} -> ${newPrice}`);
    return this.parsePriceRecord(updated);
  }

  static async addCompetitorPrice(
    priceData: Omit<CompetitorPriceData, 'id' | 'created_at' | 'updated_at'>
  ): Promise<CompetitorPriceData> {
    const id = `CP-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
    
    await db(this.PRICE_TABLE).insert({
      id,
      ...priceData,
      last_checked: new Date(),
      created_at: new Date(),
      updated_at: new Date(),
    });

    await this.createPriceAlert({
      tenant_id: priceData.tenant_id,
      shop_id: priceData.shop_id,
      product_id: priceData.product_id,
      alert_type: 'NEW_COMPETITOR',
      severity: 'MEDIUM',
      competitor_name: priceData.competitor_name,
      change_description: `发现新竞品: ${priceData.competitor_name} 在 ${priceData.platform} 上架`,
    });

    const record = await db(this.PRICE_TABLE).where('id', id).first();
    logger.info(`[CompetitorPrice] Added competitor price: ${id}`);
    return this.parsePriceRecord(record);
  }

  static async analyzeMarketPrices(
    tenantId: string,
    productId: string
  ): Promise<MarketPriceAnalysis> {
    const prices = await this.getCompetitorPrices(tenantId, productId);

    if (prices.length === 0) {
      return {
        product_id: productId,
        analysis_date: new Date(),
        price_range: { min: 0, max: 0, avg: 0, median: 0 },
        price_distribution: [],
        competitor_ranking: [],
        our_position: { rank: 0, percentile: 0, price_gap_to_lowest: 0, price_gap_to_avg: 0 },
        recommendations: { optimal_price: 0, expected_position: 0, reasoning: '无竞品数据' },
      };
    }

    const allPrices = prices.map(p => p.total_price).sort((a, b) => a - b);
    const min = allPrices[0];
    const max = allPrices[allPrices.length - 1];
    const avg = allPrices.reduce((a, b) => a + b, 0) / allPrices.length;
    const median = allPrices.length % 2 === 0
      ? (allPrices[allPrices.length / 2 - 1] + allPrices[allPrices.length / 2]) / 2
      : allPrices[Math.floor(allPrices.length / 2)];

    const rangeSize = (max - min) / 5 || 1;
    const priceDistribution = [];
    for (let i = 0; i < 5; i++) {
      const rangeStart = min + i * rangeSize;
      const rangeEnd = min + (i + 1) * rangeSize;
      const count = allPrices.filter(p => p >= rangeStart && p < rangeEnd).length;
      priceDistribution.push({
        range: `${rangeStart.toFixed(2)} - ${rangeEnd.toFixed(2)}`,
        count,
        percentage: (count / allPrices.length) * 100,
      });
    }

    const competitorRanking = prices
      .sort((a, b) => a.total_price - b.total_price)
      .map((p, index) => ({
        rank: index + 1,
        competitor_name: p.competitor_name,
        price: p.total_price,
        market_share: undefined,
      }));

    const ourProduct = await db('cf_products')
      .where('id', productId)
      .first();
    
    const ourPrice = ourProduct ? parseFloat(ourProduct.price) : 0;
    let ourPosition = { rank: 0, percentile: 0, price_gap_to_lowest: 0, price_gap_to_avg: 0 };
    
    if (ourPrice > 0) {
      const sortedPrices = [...allPrices, ourPrice].sort((a, b) => a - b);
      const rank = sortedPrices.indexOf(ourPrice) + 1;
      ourPosition = {
        rank,
        percentile: ((allPrices.length - rank + 1) / allPrices.length) * 100,
        price_gap_to_lowest: ourPrice - min,
        price_gap_to_avg: ourPrice - avg,
      };
    }

    const optimalPrice = avg * 0.95;
    const recommendations = {
      optimal_price: Math.max(optimalPrice, min * 1.05),
      expected_position: Math.ceil(allPrices.length * 0.3),
      reasoning: `建议定价低于市场均价5%，可在保持利润的同时获得价格竞争优势`,
    };

    return {
      product_id: productId,
      analysis_date: new Date(),
      price_range: { min, max, avg, median },
      price_distribution: priceDistribution,
      competitor_ranking: competitorRanking,
      our_position: ourPosition,
      recommendations,
    };
  }

  static async getPriceAlerts(
    tenantId: string,
    options?: {
      shopId?: string;
      isRead?: boolean;
      severity?: string;
      limit?: number;
    }
  ): Promise<PriceAlert[]> {
    let query = db(this.ALERT_TABLE)
      .where('tenant_id', tenantId)
      .orderBy('created_at', 'desc');

    if (options?.shopId) {
      query = query.where('shop_id', options.shopId);
    }

    if (options?.isRead !== undefined) {
      query = query.where('is_read', options.isRead);
    }

    if (options?.severity) {
      query = query.where('severity', options.severity);
    }

    if (options?.limit) {
      query = query.limit(options.limit);
    }

    const records = await query;
    return records.map(this.parseAlertRecord);
  }

  static async markAlertAsRead(
    alertId: string,
    userId: string
  ): Promise<void> {
    await db(this.ALERT_TABLE)
      .where('id', alertId)
      .update({
        is_read: true,
        read_at: new Date(),
        read_by: userId,
      });

    logger.info(`[CompetitorPrice] Alert ${alertId} marked as read by ${userId}`);
  }

  static async getMonitorConfig(
    shopId: string,
    productId: string
  ): Promise<CompetitorMonitorConfig | null> {
    const config = await db(this.CONFIG_TABLE)
      .where('shop_id', shopId)
      .where('product_id', productId)
      .first();

    if (!config) return null;

    return {
      ...config,
      competitors_to_track: config.competitors_to_track ? JSON.parse(config.competitors_to_track as any) : [],
      platforms_to_track: config.platforms_to_track ? JSON.parse(config.platforms_to_track as any) : [],
      auto_adjust_rules: config.auto_adjust_rules ? JSON.parse(config.auto_adjust_rules as any) : null,
    };
  }

  static async updateMonitorConfig(
    shopId: string,
    productId: string,
    config: Partial<CompetitorMonitorConfig>
  ): Promise<CompetitorMonitorConfig> {
    const existing = await this.getMonitorConfig(shopId, productId);

    if (existing) {
      await db(this.CONFIG_TABLE)
        .where('id', existing.id)
        .update({
          ...config,
          competitors_to_track: config.competitors_to_track ? JSON.stringify(config.competitors_to_track) : undefined,
          platforms_to_track: config.platforms_to_track ? JSON.stringify(config.platforms_to_track) : undefined,
          auto_adjust_rules: config.auto_adjust_rules ? JSON.stringify(config.auto_adjust_rules) : undefined,
          updated_at: new Date(),
        });

      const updated = await this.getMonitorConfig(shopId, productId);
      logger.info(`[CompetitorPrice] Updated monitor config for product ${productId}`);
      return updated!;
    } else {
      const id = `MC-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
      const tenantId = config.tenant_id || 'default';

      await db(this.CONFIG_TABLE).insert({
        id,
        tenant_id: tenantId,
        shop_id: shopId,
        product_id: productId,
        monitor_enabled: config.monitor_enabled ?? true,
        check_frequency: config.check_frequency ?? 'DAILY',
        price_alert_threshold: config.price_alert_threshold ?? 5,
        stock_alert_enabled: config.stock_alert_enabled ?? true,
        competitors_to_track: config.competitors_to_track ? JSON.stringify(config.competitors_to_track) : null,
        platforms_to_track: config.platforms_to_track ? JSON.stringify(config.platforms_to_track) : null,
        auto_adjust_enabled: config.auto_adjust_enabled ?? false,
        auto_adjust_rules: config.auto_adjust_rules ? JSON.stringify(config.auto_adjust_rules) : null,
        created_at: new Date(),
        updated_at: new Date(),
      });

      const created = await this.getMonitorConfig(shopId, productId);
      logger.info(`[CompetitorPrice] Created monitor config for product ${productId}`);
      return created!;
    }
  }

  static async getPriceHistory(
    competitorPriceId: string,
    days: number = 30
  ): Promise<PriceHistoryRecord[]> {
    const startDate = new Date(Date.now() - days * 24 * 60 * 60 * 1000);

    const records = await db(this.HISTORY_TABLE)
      .where('competitor_price_id', competitorPriceId)
      .where('checked_at', '>=', startDate)
      .orderBy('checked_at', 'asc');

    return records.map(this.parseHistoryRecord);
  }

  static async getCompetitorPriceStats(tenantId: string): Promise<{
    totalCompetitors: number;
    activeMonitors: number;
    unreadAlerts: number;
    priceChanges24h: number;
    avgPriceGap: number;
    byPlatform: Record<string, number>;
  }> {
    const totalCompetitors = await db(this.PRICE_TABLE)
      .where('tenant_id', tenantId)
      .count('* as count')
      .first();

    const activeMonitors = await db(this.CONFIG_TABLE)
      .where('tenant_id', tenantId)
      .where('monitor_enabled', true)
      .count('* as count')
      .first();

    const unreadAlerts = await db(this.ALERT_TABLE)
      .where('tenant_id', tenantId)
      .where('is_read', false)
      .count('* as count')
      .first();

    const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000);
    const priceChanges24h = await db(this.HISTORY_TABLE)
      .join(this.PRICE_TABLE, `${this.HISTORY_TABLE}.competitor_price_id`, `${this.PRICE_TABLE}.id`)
      .where(`${this.PRICE_TABLE}.tenant_id`, tenantId)
      .where(`${this.HISTORY_TABLE}.checked_at`, '>=', yesterday)
      .where(`${this.HISTORY_TABLE}.change_type`, '!=', 'STABLE')
      .count('* as count')
      .first();

    const platformCounts = await db(this.PRICE_TABLE)
      .where('tenant_id', tenantId)
      .select('platform')
      .count('* as count')
      .groupBy('platform');

    const byPlatform: Record<string, number> = {};
    for (const row of platformCounts) {
      byPlatform[row.platform] = parseInt(row.count as any);
    }

    return {
      totalCompetitors: parseInt(totalCompetitors?.count as any || '0'),
      activeMonitors: parseInt(activeMonitors?.count as any || '0'),
      unreadAlerts: parseInt(unreadAlerts?.count as any || '0'),
      priceChanges24h: parseInt(priceChanges24h?.count as any || '0'),
      avgPriceGap: 0,
      byPlatform,
    };
  }

  private static async createPriceAlert(
    alertData: Omit<PriceAlert, 'id' | 'is_read' | 'created_at'>
  ): Promise<PriceAlert> {
    const id = `PA-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;

    await db(this.ALERT_TABLE).insert({
      id,
      ...alertData,
      is_read: false,
      created_at: new Date(),
    });

    const alert = await db(this.ALERT_TABLE).where('id', id).first();
    
    await EventBusService.publish({
      type: 'price.alert.created',
      data: {
        alertId: id,
        type: alertData.alert_type,
        severity: alertData.severity,
        productId: alertData.product_id,
      },
      metadata: {
        source: 'CompetitorPriceService',
        correlationId: id,
        timestamp: Date.now(),
        version: '1.0'
      }
    });

    logger.info(`[CompetitorPrice] Created alert: ${id} - ${alertData.change_description}`);
    return this.parseAlertRecord(alert);
  }

  private static parsePriceRecord(row: any): CompetitorPriceData {
    return {
      id: row.id,
      tenant_id: row.tenant_id,
      shop_id: row.shop_id,
      product_id: row.product_id,
      competitor_name: row.competitor_name,
      competitor_shop_id: row.competitor_shop_id,
      competitor_product_id: row.competitor_product_id,
      platform: row.platform,
      price: parseFloat(row.price),
      shipping_cost: parseFloat(row.shipping_cost),
      total_price: parseFloat(row.total_price),
      currency: row.currency,
      stock_status: row.stock_status,
      stock_quantity: row.stock_quantity,
      rating: parseFloat(row.rating),
      review_count: row.review_count,
      sales_count: row.sales_count,
      listing_url: row.listing_url,
      image_url: row.image_url,
      last_checked: row.last_checked,
      next_check: row.next_check,
      created_at: row.created_at,
      updated_at: row.updated_at,
    };
  }

  private static parseAlertRecord(row: any): PriceAlert {
    return {
      id: row.id,
      tenant_id: row.tenant_id,
      shop_id: row.shop_id,
      product_id: row.product_id,
      alert_type: row.alert_type,
      severity: row.severity,
      competitor_name: row.competitor_name,
      old_value: row.old_value ? parseFloat(row.old_value) : undefined,
      new_value: row.new_value ? parseFloat(row.new_value) : undefined,
      change_description: row.change_description,
      is_read: row.is_read,
      read_at: row.read_at,
      read_by: row.read_by,
      action_taken: row.action_taken,
      action_at: row.action_at,
      created_at: row.created_at,
    };
  }

  private static parseHistoryRecord(row: any): PriceHistoryRecord {
    return {
      id: row.id,
      competitor_price_id: row.competitor_price_id,
      old_price: parseFloat(row.old_price),
      new_price: parseFloat(row.new_price),
      price_change: parseFloat(row.price_change),
      change_percent: parseFloat(row.change_percent),
      change_type: row.change_type,
      checked_at: row.checked_at,
    };
  }
}
