const { getCollections } = require('../config/db');

function toDateOnly(d) {
  const dt = new Date(d);
  dt.setHours(0, 0, 0, 0);
  return dt;
}

function ymKey(date) {
  const d = new Date(date);
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, '0');
  return `${y}-${m}`;
}

// Sales by date range
const salesByDateRange = async (req, res) => {
  const { start_date, end_date } = req.query;
  if (!start_date || !end_date)
    return res.status(400).json({ message: 'start_date and end_date are required.' });

  try {
    const { sales } = await getCollections();

    const start = toDateOnly(start_date);
    const end = toDateOnly(end_date);
    end.setHours(23, 59, 59, 999);

    const rows = await sales
      .find({ sale_date: { $gte: start, $lte: end } })
      .sort({ sale_date: -1 })
      .toArray();

    const total = rows.reduce((sum, r) => sum + Number(r.total_price), 0);

    res.json({ sales: rows, total_revenue: total, count: rows.length });
  } catch (err) {
    res.status(500).json({ message: 'Server error.' });
  }
};

// Monthly report
const monthlyReport = async (req, res) => {
  const { start_date, end_date } = req.query;
  try {
    const { sales } = await getCollections();

    const start = toDateOnly(start_date || '2000-01-01');
    const end = toDateOnly(end_date || '2099-12-31');
    end.setHours(23, 59, 59, 999);

    const rows = await sales
      .find({ sale_date: { $gte: start, $lte: end } })
      .toArray();

    const byMonth = new Map();
    for (const s of rows) {
      const key = ymKey(s.sale_date);
      const cur = byMonth.get(key) || { month: key, total_sales: 0, total_quantity: 0, total_revenue: 0 };
      cur.total_sales += 1;
      cur.total_quantity += Number(s.quantity);
      cur.total_revenue += Number(s.total_price);
      byMonth.set(key, cur);
    }

    const out = Array.from(byMonth.values()).sort((a, b) => a.month.localeCompare(b.month));
    res.json(out);
  } catch (err) {
    res.status(500).json({ message: 'Server error.' });
  }
};

// Product stock report
const stockReport = async (req, res) => {
  try {
    const { products, sales } = await getCollections();

    const allProducts = await products.find({}).toArray();
    const salesRows = await sales.find({}).toArray();

    const soldByProduct = new Map();
    for (const s of salesRows) {
      const pid = s.product_id;
      const cur = soldByProduct.get(pid) || 0;
      soldByProduct.set(pid, cur + Number(s.quantity));
    }

    const out = allProducts
      .map((p) => ({
        product_id: p.product_id,
        product_name: p.product_name,
        category: p.category,
        price: p.price,
        available_stock: p.stock,
        sold_stock: soldByProduct.get(p.product_id) || 0
      }))
      .sort((a, b) => {
        const c = String(a.category).localeCompare(String(b.category));
        if (c !== 0) return c;
        return String(a.product_name).localeCompare(String(b.product_name));
      });

    res.json(out);
  } catch (err) {
    res.status(500).json({ message: 'Server error.' });
  }
};

// Customer purchase report
const customerPurchaseReport = async (req, res) => {
  const { customer_id } = req.params;
  try {
    const { customers, sales } = await getCollections();

    const customer = await customers.findOne({ customer_id: Number(customer_id) });
    if (!customer) return res.status(404).json({ message: 'Customer not found.' });

    const purchases = await sales
      .find({ customer_id: Number(customer_id) })
      .sort({ sale_date: -1 })
      .toArray();

    const total_spent = purchases.reduce((sum, r) => sum + Number(r.total_price), 0);
    res.json({ customer, purchases, total_spent });
  } catch (err) {
    res.status(500).json({ message: 'Server error.' });
  }
};

// Dashboard stats
const dashboardStats = async (req, res) => {
  try {
    const { products, customers, sales } = await getCollections();

    const total_products = await products.countDocuments({});
    const total_customers = await customers.countDocuments({});
    const total_sales = await sales.countDocuments({});

    const total_revenueAgg = await sales
      .find({})
      .toArray();
    const total_revenue = total_revenueAgg.reduce((sum, s) => sum + Number(s.total_price), 0);

    // Sales last 7 days
    const now = new Date();
    const start = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);

    const recentSales = await sales
      .find({ sale_date: { $gte: start } })
      .toArray();

    const byDate = new Map();
    for (const s of recentSales) {
      const key = new Date(s.sale_date);
      key.setHours(0, 0, 0, 0);
      const k = key.toISOString().slice(0, 10);
      const cur = byDate.get(k) || { date: k, revenue: 0 };
      cur.revenue += Number(s.total_price);
      byDate.set(k, cur);
    }

    const recentSalesOut = Array.from(byDate.values()).sort((a, b) => a.date.localeCompare(b.date));

    // Top products
    const topMap = new Map();
    for (const s of total_revenueAgg) {
      const key = s.product_name;
      const cur = topMap.get(key) || { product_name: key, total_sold: 0, revenue: 0 };
      cur.total_sold += Number(s.quantity);
      cur.revenue += Number(s.total_price);
      topMap.set(key, cur);
    }
    const topProducts = Array.from(topMap.values())
      .sort((a, b) => b.total_sold - a.total_sold)
      .slice(0, 5);

    // Category breakdown
    const productDocs = await products.find({}).toArray();
    const catMap = new Map();
    const productById = new Map(productDocs.map((p) => [p.product_id, p]));

    for (const s of total_revenueAgg) {
      const p = productById.get(s.product_id);
      const cat = p?.category;
      if (!cat) continue;
      const cur = catMap.get(cat) || { category: cat, sales_count: 0, revenue: 0 };
      cur.sales_count += 1;
      cur.revenue += Number(s.total_price);
      catMap.set(cat, cur);
    }

    const categoryStats = Array.from(catMap.values());

    res.json({
      total_products,
      total_customers,
      total_sales,
      total_revenue,
      recentSales: recentSalesOut,
      topProducts,
      categoryStats
    });
  } catch (err) {
    console.error(err);
    res.status(500).json({ message: 'Server error.' });
  }
};

module.exports = { salesByDateRange, monthlyReport, stockReport, customerPurchaseReport, dashboardStats };

