/**
 * Exchange management routes - Refactored
 */
import { Hono } from 'hono';
import { getLogger } from '@stock-bot/logger';
import type { IServiceContainer } from '@stock-bot/types';
import { createExchangeService } from '../services/exchange.service';
import { createSuccessResponse, handleError } from '../utils/error-handler';
import {
  validateCreateExchange,
  validateCreateProviderMapping,
  validateUpdateExchange,
  validateUpdateProviderMapping,
} from '../utils/validation';

const logger = getLogger('exchange-routes');

export function createExchangeRoutes(container: IServiceContainer) {
  const exchangeRoutes = new Hono();
  const exchangeService = createExchangeService(container);

  // Get all exchanges with provider mapping counts and mappings
  exchangeRoutes.get('/', async c => {
    logger.debug('Getting all exchanges');
    try {
      const exchanges = await exchangeService.getAllExchanges();
      logger.info('Successfully retrieved exchanges', { count: exchanges.length });
      return c.json(createSuccessResponse(exchanges, undefined, exchanges.length));
    } catch (error) {
      logger.error('Failed to get exchanges', { error });
      return handleError(c, error, 'to get exchanges');
    }
  });

  // Get exchange by ID with detailed provider mappings
  exchangeRoutes.get('/:id', async c => {
    const exchangeId = c.req.param('id');
    logger.debug('Getting exchange by ID', { exchangeId });

    try {
      const result = await exchangeService.getExchangeById(exchangeId);

      if (!result) {
        logger.warn('Exchange not found', { exchangeId });
        return c.json(createSuccessResponse(null, 'Exchange not found'), 404);
      }

      logger.info('Successfully retrieved exchange details', {
        exchangeId,
        exchangeCode: result.exchange.code,
        mappingCount: result.provider_mappings.length,
      });
      return c.json(createSuccessResponse(result));
    } catch (error) {
      logger.error('Failed to get exchange details', { error, exchangeId });
      return handleError(c, error, 'to get exchange details');
    }
  });

  // Create new exchange
  exchangeRoutes.post('/', async c => {
    logger.debug('Creating new exchange');

    try {
      const body = await c.req.json();
      logger.debug('Received exchange creation request', { requestBody: body });

      const validatedData = validateCreateExchange(body);
      logger.debug('Exchange data validated successfully', { validatedData });

      const exchange = await exchangeService.createExchange(validatedData);
      logger.info('Exchange created successfully', {
        exchangeId: exchange.id,
        code: exchange.code,
        name: exchange.name,
      });

      return c.json(createSuccessResponse(exchange, 'Exchange created successfully'), 201);
    } catch (error) {
      logger.error('Failed to create exchange', { error });
      return handleError(c, error, 'to create exchange');
    }
  });

  // Update exchange (activate/deactivate, rename, etc.)
  exchangeRoutes.patch('/:id', async c => {
    const exchangeId = c.req.param('id');
    logger.debug('Updating exchange', { exchangeId });

    try {
      const body = await c.req.json();
      logger.debug('Received exchange update request', { exchangeId, updates: body });

      const validatedUpdates = validateUpdateExchange(body);
      logger.debug('Exchange update data validated', { exchangeId, validatedUpdates });

      const exchange = await exchangeService.updateExchange(exchangeId, validatedUpdates);

      if (!exchange) {
        logger.warn('Exchange not found for update', { exchangeId });
        return c.json(createSuccessResponse(null, 'Exchange not found'), 404);
      }

      logger.info('Exchange updated successfully', {
        exchangeId,
        code: exchange.code,
        updates: validatedUpdates,
      });

      // Log special actions
      if (validatedUpdates.visible === false) {
        logger.warn('Exchange marked as hidden - provider mappings will be deleted', {
          exchangeId,
          code: exchange.code,
        });
      }

      return c.json(createSuccessResponse(exchange, 'Exchange updated successfully'));
    } catch (error) {
      logger.error('Failed to update exchange', { error, exchangeId });
      return handleError(c, error, 'to update exchange');
    }
  });

  // Get all provider mappings
  exchangeRoutes.get('/provider-mappings/all', async c => {
    logger.debug('Getting all provider mappings');

    try {
      const mappings = await exchangeService.getAllProviderMappings();
      logger.info('Successfully retrieved all provider mappings', { count: mappings.length });
      return c.json(createSuccessResponse(mappings, undefined, mappings.length));
    } catch (error) {
      logger.error('Failed to get provider mappings', { error });
      return handleError(c, error, 'to get provider mappings');
    }
  });

  // Get provider mappings by provider
  exchangeRoutes.get('/provider-mappings/:provider', async c => {
    const provider = c.req.param('provider');
    logger.debug('Getting provider mappings by provider', { provider });

    try {
      const mappings = await exchangeService.getProviderMappingsByProvider(provider);
      logger.info('Successfully retrieved provider mappings', { provider, count: mappings.length });

      return c.json(createSuccessResponse(mappings, undefined, mappings.length));
    } catch (error) {
      logger.error('Failed to get provider mappings', { error, provider });
      return handleError(c, error, 'to get provider mappings');
    }
  });

  // Update provider mapping (activate/deactivate, verify, change confidence)
  exchangeRoutes.patch('/provider-mappings/:id', async c => {
    const mappingId = c.req.param('id');
    logger.debug('Updating provider mapping', { mappingId });

    try {
      const body = await c.req.json();
      logger.debug('Received provider mapping update request', { mappingId, updates: body });

      const validatedUpdates = validateUpdateProviderMapping(body);
      logger.debug('Provider mapping update data validated', { mappingId, validatedUpdates });

      const mapping = await exchangeService.updateProviderMapping(mappingId, validatedUpdates);

      if (!mapping) {
        logger.warn('Provider mapping not found for update', { mappingId });
        return c.json(createSuccessResponse(null, 'Provider mapping not found'), 404);
      }

      logger.info('Provider mapping updated successfully', {
        mappingId,
        provider: mapping.provider,
        providerExchangeCode: mapping.provider_exchange_code,
        updates: validatedUpdates,
      });

      return c.json(createSuccessResponse(mapping, 'Provider mapping updated successfully'));
    } catch (error) {
      logger.error('Failed to update provider mapping', { error, mappingId });
      return handleError(c, error, 'to update provider mapping');
    }
  });

  // Create new provider mapping
  exchangeRoutes.post('/provider-mappings', async c => {
    logger.debug('Creating new provider mapping');

    try {
      const body = await c.req.json();
      logger.debug('Received provider mapping creation request', { requestBody: body });

      const validatedData = validateCreateProviderMapping(body);
      logger.debug('Provider mapping data validated successfully', { validatedData });

      const mapping = await exchangeService.createProviderMapping(validatedData);
      logger.info('Provider mapping created successfully', {
        mappingId: mapping.id,
        provider: mapping.provider,
        providerExchangeCode: mapping.provider_exchange_code,
        masterExchangeId: mapping.master_exchange_id,
      });

      return c.json(createSuccessResponse(mapping, 'Provider mapping created successfully'), 201);
    } catch (error) {
      logger.error('Failed to create provider mapping', { error });
      return handleError(c, error, 'to create provider mapping');
    }
  });

  // Get all available providers
  exchangeRoutes.get('/providers/list', async c => {
    logger.debug('Getting providers list');

    try {
      const providers = await exchangeService.getProviders();
      logger.info('Successfully retrieved providers list', { count: providers.length, providers });
      return c.json(createSuccessResponse(providers));
    } catch (error) {
      logger.error('Failed to get providers list', { error });
      return handleError(c, error, 'to get providers list');
    }
  });

  // Get unmapped provider exchanges by provider
  exchangeRoutes.get('/provider-exchanges/unmapped/:provider', async c => {
    const provider = c.req.param('provider');
    logger.debug('Getting unmapped provider exchanges', { provider });

    try {
      const exchanges = await exchangeService.getUnmappedProviderExchanges(provider);
      logger.info('Successfully retrieved unmapped provider exchanges', {
        provider,
        count: exchanges.length,
      });

      return c.json(createSuccessResponse(exchanges, undefined, exchanges.length));
    } catch (error) {
      logger.error('Failed to get unmapped provider exchanges', { error, provider });
      return handleError(c, error, 'to get unmapped provider exchanges');
    }
  });

  // Get exchange statistics
  exchangeRoutes.get('/stats/summary', async c => {
    logger.debug('Getting exchange statistics');

    try {
      const stats = await exchangeService.getExchangeStats();
      logger.info('Successfully retrieved exchange statistics', { stats });
      return c.json(createSuccessResponse(stats));
    } catch (error) {
      logger.error('Failed to get exchange statistics', { error });
      return handleError(c, error, 'to get exchange statistics');
    }
  });

  return exchangeRoutes;
}
