const db = require('../database/database');
const { logger } = require('../middleware/logger');

class UnitOfWork {
  constructor() {
    this.repositories = {};
    this.connection = null;
    this.inTransaction = false;
  }

  async start() {
    logger.info('UnitOfWork.start:start');
    try {
      this.connection = await db.getConnection();
      await this.connection.query('START TRANSACTION');
      this.inTransaction = true;
      logger.info('UnitOfWork.start:success');
    } catch (error) {
      logger.error('UnitOfWork.start:error', { error: error.message });
      throw error;
    }
  }

  async commit() {
    logger.info('UnitOfWork.commit:start');
    if (this.inTransaction && this.connection) {
      try {
        await this.connection.query('COMMIT');
        this.inTransaction = false;
        await this.connection.release();
        this.connection = null;
        logger.info('UnitOfWork.commit:success');
      } catch (error) {
        logger.error('UnitOfWork.commit:error', { error: error.message });
        throw error;
      }
    }
  }

  async rollback(error) {
    logger.warn('UnitOfWork.rollback:start');
    if (this.inTransaction && this.connection) {
      try {
        await this.connection.query('ROLLBACK');
        if (error) {
          logger.error('UnitOfWork.rollback:error', { error: error.message, stack: error.stack });
          console.error('💥 Transaction rolled back due to error:', error);
          if (error.stack) {
            console.error('💥 Error stack:', error.stack);
          }
        } else {
          logger.error('UnitOfWork.rollback:unknown_error');
          console.error('💥 Transaction rolled back due to unknown error');
        }
      } catch (rollbackError) {
        logger.error('UnitOfWork.rollback:rollback_error', { error: rollbackError.message, stack: rollbackError.stack });
        console.error('💥 Error during rollback:', rollbackError);
        if (rollbackError.stack) {
          console.error('💥 Rollback error stack:', rollbackError.stack);
        }
      }
      this.inTransaction = false;
      await this.connection.release();
      this.connection = null;
      logger.info('UnitOfWork.rollback:complete');
    }
  }

  registerRepository(name, repository) {
    this.repositories[name] = repository;
  }

  getRepository(name) {
    return this.repositories[name];
  }

  getConnection() {
    if (!this.inTransaction || !this.connection) {
      throw new Error('UnitOfWork connection not available. Call start() before using getConnection().');
    }
    return this.connection;
  }
}

module.exports = UnitOfWork;
