import { getLogger } from '@stock-bot/logger';
import type { IServiceContainer } from '@stock-bot/types';
import type { JobPayload } from '../../../types/job-payloads';

const logger = getLogger('sync-qm-exchanges');

export async function syncQMExchanges(
  payload: JobPayload,
  container: IServiceContainer
): Promise<{ processed: number; created: number; updated: number }> {
  logger.info('Starting QM exchanges sync...');

  try {
    const mongoClient = container.mongodb;
    const postgresClient = container.postgres;

    // 1. Get all QM exchanges from MongoDB
    const qmExchanges = await mongoClient.find('qmExchanges', {});
    logger.info(`Found ${qmExchanges.length} QM exchanges to process`);

    let created = 0;
    let updated = 0;

    for (const exchange of qmExchanges) {
      try {
        // 2. Check if exchange exists
        const existingExchange = await findExchange(exchange.exchangeCode, postgresClient);

        if (existingExchange) {
          // Update existing
          await updateExchange(existingExchange.id, exchange, postgresClient);
          updated++;
        } else {
          // Create new
          await createExchange(exchange, postgresClient);
          created++;
        }
      } catch (error) {
        logger.error('Failed to process exchange', { error, exchange: exchange.exchangeCode });
      }
    }

    // 3. Update sync status
    await updateSyncStatus('qm', 'exchanges', qmExchanges.length, postgresClient);

    const result = { processed: qmExchanges.length, created, updated };
    logger.info('QM exchanges sync completed', result);
    return result;
  } catch (error) {
    logger.error('QM exchanges sync failed', { error });
    throw error;
  }
}

// Helper functions
interface Exchange {
  id: string;
  code: string;
  name: string;
  country: string;
  currency: string;
  visible: boolean;
}

async function findExchange(
  exchangeCode: string,
  postgresClient: IServiceContainer['postgres']
): Promise<Exchange | null> {
  const query = 'SELECT * FROM exchanges WHERE code = $1';
  const result = await postgresClient.query(query, [exchangeCode]);
  return result.rows[0] || null;
}

interface QMExchange {
  exchangeCode?: string;
  exchange?: string;
  exchangeShortName?: string;
  name?: string;
  countryCode?: string;
}

async function createExchange(
  qmExchange: QMExchange,
  postgresClient: IServiceContainer['postgres']
): Promise<void> {
  const query = `
    INSERT INTO exchanges (code, name, country, currency, visible)
    VALUES ($1, $2, $3, $4, $5)
    ON CONFLICT (code) DO NOTHING
  `;

  await postgresClient.query(query, [
    qmExchange.exchangeCode || qmExchange.exchange,
    qmExchange.exchangeShortName || qmExchange.name,
    qmExchange.countryCode || 'US',
    'USD', // Default currency, can be improved
    true, // New exchanges are visible by default
  ]);
}

async function updateExchange(
  exchangeId: string,
  qmExchange: QMExchange,
  postgresClient: IServiceContainer['postgres']
): Promise<void> {
  const query = `
    UPDATE exchanges 
    SET name = COALESCE($2, name),
        country = COALESCE($3, country),
        updated_at = NOW()
    WHERE id = $1
  `;

  await postgresClient.query(query, [
    exchangeId,
    qmExchange.exchangeShortName || qmExchange.name,
    qmExchange.countryCode,
  ]);
}

async function updateSyncStatus(
  provider: string,
  dataType: string,
  count: number,
  postgresClient: IServiceContainer['postgres']
): Promise<void> {
  const query = `
    UPDATE sync_status 
    SET last_sync_at = NOW(),
        last_sync_count = $3,
        sync_errors = NULL,
        updated_at = NOW()
    WHERE provider = $1 AND data_type = $2
  `;

  await postgresClient.query(query, [provider, dataType, count]);
}
