const { buildQueryOptions } = require('../utils/queryBuilder');

// Controlador base genérico para CRUD (SIN paginación)
class BaseController {
  constructor(model, modelName, searchFields = []) {
    this.model = model;
    this.modelName = modelName;
    this.searchFields = searchFields;
  }

  // Obtener todos los registros con filtros, búsqueda y ordenamiento (sin paginación)
  getAll = async (req, res, next) => {
    try {
      const { search, sortBy, sortOrder, ...filters } = req.query;

      const queryOptions = buildQueryOptions({
        search,
        searchFields: this.searchFields,
        sortBy,
        sortOrder,
        ...filters
      });

      // findAndCountAll sigue funcionando perfectamente sin offset/limit
      const { count, rows } = await this.model.findAndCountAll(queryOptions);

      if (count === 0) {
        return res.json({
          success: false,
          message: `${this.modelName} no encontrados`
        });
      }


      res.json({
        success: true,
        message: `${this.modelName} obtenidos exitosamente`,
        data: rows,
        total: count
      });
    } catch (error) {
      next(error);
    }
  };

  // Obtener un registro por ID
  getById = async (req, res, next) => {
    try {
      const { id } = req.params;
      const data = await this.model.findByPk(id);

      if (!data) {
        return res.status(404).json({
          success: false,
          message: `${this.modelName} no encontrado`
        });
      }

      res.json({
        success: true,
        message: `${this.modelName} obtenido exitosamente`,
        data
      });
    } catch (error) {
      next(error);
    }
  };

  // Crear un nuevo registro
  create = async (req, res, next) => {
    try {
      const elcuerpo = req.body;
      const data = await this.model.create(elcuerpo);

      res.status(201).json({
        success: true,
        message: `${this.modelName} creado exitosamente`,
        data
      });
    } catch (error) {
      next(error);
    }
  };

  // Actualizar un registro
  update = async (req, res, next) => {
    try {
      const { id } = req.params;
      const elcuerpo = req.body;
      const record = await this.model.findByPk(id);

      if (!record) {
        return res.status(404).json({
          success: false,
          message: `${this.modelName} no encontrado`
        });
      }

      await record.update(elcuerpo);

      res.json({
        success: true,
        message: `${this.modelName} actualizado exitosamente`,
        data: record
      });
    } catch (error) {
      next(error);
    }
  };

  // Eliminar un registro
  delete = async (req, res, next) => {
    try {
      const { id } = req.params;
      const record = await this.model.findByPk(id);

      if (!record) {
        return res.status(404).json({
          success: false,
          message: `${this.modelName} no encontrado`
        });
      }

      await record.destroy();

      res.json({
        success: true,
        message: `${this.modelName} eliminado exitosamente`
      });
    } catch (error) {
      next(error);
    }
  };

  // Búsqueda avanzada (sin paginación)
  search = async (req, res, next) => {
    try {
      const { q, sortBy, sortOrder, ...filters } = req.query;

      if (!q) {
        return res.status(400).json({
          success: false,
          message: 'Parámetro de búsqueda "q" es requerido'
        });
      }

      const queryOptions = buildQueryOptions({
        search: q,
        searchFields: this.searchFields,
        sortBy,
        sortOrder,
        ...filters
      });

      const { count, rows } = await this.model.findAndCountAll(queryOptions);

      res.json({
        success: true,
        message: `Búsqueda completada`,
        data: rows,
        total: count
      });
    } catch (error) {
      next(error);
    }
  };
}

module.exports = BaseController;