const CoffeeRepository = require('../../repositories/subscriptions/CoffeeRepository');
const UnitOfWork = require('../../database/UnitOfWork');
const { logger } = require('../../middleware/logger');

function validate(data) {
  const errors = [];
  if (!data.title || String(data.title).trim() === '') errors.push('title');
  if (!data.description || String(data.description).trim() === '') errors.push('description');
  const price = Number(data.price);
  if (!Number.isFinite(price) || price < 0) errors.push('price');
  if (typeof data.state !== 'boolean') errors.push('state');
  if (data.currency && String(data.currency).length > 3) errors.push('currency');
  if (typeof data.is_featured !== 'boolean') errors.push('is_featured');
  // Enforce fixed billing defaults (month/1) if provided differently
  if (data.billing_interval && data.billing_interval !== 'month') errors.push('billing_interval');
  if (data.interval_count && Number(data.interval_count) !== 1) errors.push('interval_count');
  return errors;
}

class CoffeeService {
  async list() {
    return CoffeeRepository.listAll();
  }

  async get(id) {
    return CoffeeRepository.getById(id);
  }

  async create(data) {
    // Force billing defaults
    data.billing_interval = 'month';
    data.interval_count = 1;
    const errors = validate(data);
    if (errors.length) {
      logger.warn('[CoffeeService.create] validation_failed', { errors });
      throw Object.assign(new Error('Validation failed'), { code: 'VALIDATION_ERROR', errors });
    }
    const uow = new UnitOfWork();
    try {
      await uow.start();
      const result = await CoffeeRepository.create(data, uow.connection);
      await uow.commit();
      return result;
    } catch (e) {
      try { await uow.rollback(e); } catch(_) {}
      throw e;
    }
  }

  async update(id, data) {
    // Keep billing values fixed regardless of incoming payload
    data.billing_interval = 'month';
    data.interval_count = 1;
    const errors = validate(data);
    if (errors.length) {
      logger.warn('[CoffeeService.update] validation_failed', { id, errors });
      throw Object.assign(new Error('Validation failed'), { code: 'VALIDATION_ERROR', errors });
    }
    const uow = new UnitOfWork();
    try {
      await uow.start();
      await CoffeeRepository.update(id, data, uow.connection);
      const updated = await CoffeeRepository.getById(id, uow.connection);
      await uow.commit();
      return updated;
    } catch (e) {
      try { await uow.rollback(e); } catch(_) {}
      throw e;
    }
  }

  async setState(id, state) {
    const uow = new UnitOfWork();
    try {
      await uow.start();
      await CoffeeRepository.setState(id, !!state, uow.connection);
      const updated = await CoffeeRepository.getById(id, uow.connection);
      await uow.commit();
      return updated;
    } catch (e) {
      try { await uow.rollback(e); } catch(_) {}
      throw e;
    }
  }

  async delete(id) {
    const uow = new UnitOfWork();
    try {
      await uow.start();
      const ok = await CoffeeRepository.delete(id, uow.connection);
      await uow.commit();
      return ok;
    } catch (e) {
      try { await uow.rollback(e); } catch(_) {}
      throw e;
    }
  }

  async listActive() {
    return CoffeeRepository.listActive();
  }

  async editPictures(id, payload = {}) {
    const numericId = Number(id);
    if (!Number.isFinite(numericId) || numericId <= 0) {
      throw new Error('Invalid coffee id');
    }

    const uow = new UnitOfWork();
    try {
      await uow.start();
      const existing = await CoffeeRepository.getById(numericId, uow.connection);
      if (!existing) {
        await uow.rollback();
        return null;
      }

      const result = await CoffeeRepository.editPictures(numericId, payload, uow.connection);
      await uow.commit();
      return result;
    } catch (e) {
      try { await uow.rollback(e); } catch(_) {}
      throw e;
    }
  }
}

module.exports = new CoffeeService();
