import Product from '../models/Product.js';
import { allVariantRows } from '../utils/variantUtils.js';

const SORT_MAP = {
  'createdAt_desc': { createdAt: -1 },
  'createdAt_asc': { createdAt: 1 },
  'name_asc': { name: 1 },
  'name_desc': { name: -1 },
  'sellingPrice_desc': { sellingPrice: -1 },
  'sellingPrice_asc': { sellingPrice: 1 },
  'currentStock_desc': { currentStock: -1 },
  'currentStock_asc': { currentStock: 1 },
};

export const findAll = async ({ search, category, stockStatus, status, sort, page = 1, limit = 20 }) => {
  const query = {};
  if (search) {
    const escaped = String(search).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    query.$or = [
      { name: { $regex: escaped, $options: 'i' } },
      { category: { $regex: escaped, $options: 'i' } },
      { 'variants.label': { $regex: escaped, $options: 'i' } },
      { 'variants.sku': { $regex: escaped, $options: 'i' } },
      { 'variants.barcode': { $regex: escaped, $options: 'i' } },
    ];
  }
  if (category && category !== 'All') query.category = category;

  const filter = stockStatus || status;
  const sortObj = SORT_MAP[sort] || { createdAt: -1 };
  const skip = (Number(page) - 1) * Number(limit);
  const perPage = Number(limit) || 20;

  if (filter) {
    const all = await Product.find(query).sort(sortObj);
    const filtered = all.filter((p) => p.stockStatus === filter);
    return {
      products: filtered.slice(skip, skip + perPage),
      total: filtered.length,
      page: Number(page),
      pages: Math.max(1, Math.ceil(filtered.length / perPage)),
    };
  }

  const [products, total] = await Promise.all([
    Product.find(query).sort(sortObj).skip(skip).limit(perPage),
    Product.countDocuments(query),
  ]);

  return {
    products,
    total,
    page: Number(page),
    pages: Math.ceil(total / perPage),
  };
};

export const findAllVariantRows = async ({ search, category, status, page = 1, limit = 20 }) => {
  const query = {};
  if (category && category !== 'All') query.category = category;

  const skip = (Number(page) - 1) * Number(limit);
  const perPage = Number(limit) || 20;

  const products = await Product.find(query).sort({ createdAt: -1 });
  let rows = allVariantRows(products);

  if (search) {
    const s = String(search).toLowerCase();
    rows = rows.filter(
      (r) =>
        (r.productName || '').toLowerCase().includes(s) ||
        (r.category || '').toLowerCase().includes(s) ||
        (r.variantLabel || '').toLowerCase().includes(s) ||
        (r.sellingUnit || '').toLowerCase().includes(s) ||
        (r.measurementUnit || '').toLowerCase().includes(s) ||
        (r.sku || '').toLowerCase().includes(s) ||
        (r.barcode || '').toLowerCase().includes(s) ||
        String(r.measurementValue ?? '').includes(s)
    );
  }

  if (status && status !== 'ALL') {
    rows = rows.filter((r) => r.status === status);
  }

  return {
    items: rows.slice(skip, skip + perPage),
    total: rows.length,
    page: Number(page),
    pages: Math.max(1, Math.ceil(rows.length / perPage)),
  };
};

export const findById = async (id) => Product.findById(id);

export const findAllRaw = async (query = {}) => Product.find(query);

export const create = async (data) => {
  const product = new Product(data);
  await product.save();
  return product;
};

export const update = async (id, data) =>
  Product.findByIdAndUpdate(id, data, { new: true, runValidators: true });

export const deleteOne = async (id) => Product.findByIdAndDelete(id);

export const findMultiple = async (ids) => Product.find({ _id: { $in: ids } });

export const findLowStock = async () => {
  const products = await Product.find();
  return products.filter((p) => p.stockStatus === 'LOW_STOCK');
};

export const findOutOfStock = async () => {
  const products = await Product.find();
  return products.filter((p) => p.stockStatus === 'OUT_OF_STOCK');
};

export const findDistinctCategories = async () => Product.distinct('category');

export const aggregateByCategory = async () =>
  Product.aggregate([
    { $group: { _id: '$category', count: { $sum: 1 } } },
    { $sort: { count: -1 } },
  ]);

export const countDocuments = async () => Product.countDocuments();