const { Op, fn, col, literal } = require("sequelize");

class ReportService {
  /**
   * Get total sales for a specific month and year
   */
  static async getMonthlySales(model, month, year) {
    const result = await model.findOne({
      attributes: [[fn("SUM", col("amount")), "total_amount"]],
      where: {
        created_at: {
          [Op.and]: [
            literal(`MONTH(created_at) = ${month}`),
            literal(`YEAR(created_at) = ${year}`),
          ],
        },
      },
    });

    return {
      month: parseInt(month),
      year: parseInt(year),
      total_amount: parseFloat(result?.dataValues?.total_amount || 0),
    };
  }

  /**
   * Get total sales for a date range
   */
  static async getSalesByDateRange(model, fromDate, toDate) {
    // Ensure dates are in correct order
    const startDate = new Date(fromDate) < new Date(toDate) ? fromDate : toDate;
    const endDate = new Date(fromDate) < new Date(toDate) ? toDate : fromDate;

    const result = await model.findOne({
      attributes: [[fn("SUM", col("amount")), "total_amount"]],
      where: {
        created_at: {
          [Op.between]: [startDate, endDate],
        },
      },
    });

    return {
      from_date: startDate,
      to_date: endDate,
      total_amount: parseFloat(result?.dataValues?.total_amount || 0),
    };
  }

  /**
   * Get monthly sales for a year (only months with sales > 0)
   */
  static async getMonthlySalesByYear(model, year) {
    const results = await model.findAll({
      attributes: [
        [fn("MONTH", col("created_at")), "month"],
        [fn("SUM", col("amount")), "total_amount"],
      ],
      where: {
        created_at: {
          [Op.and]: [literal(`YEAR(created_at) = ${year}`)],
        },
      },
      group: [fn("MONTH", col("created_at"))],
      having: literal("SUM(amount) > 0"),
      order: [[fn("MONTH", col("created_at")), "ASC"]],
    });

    return results.map((result) => ({
      month: parseInt(result.dataValues.month),
      total_amount: parseFloat(result.dataValues.total_amount),
    }));
  }

  /**
   * Get monthly sales for a year by user_id (only months with sales > 0)
   */
  static async getMonthlySalesByUser(model, year, userId) {
    const results = await model.findAll({
      attributes: [
        [fn("MONTH", col("created_at")), "month"],
        [fn("SUM", col("amount")), "total_amount"],
      ],
      where: {
        created_at: {
          [Op.and]: [literal(`YEAR(created_at) = ${year}`)],
        },
        user_id: userId,
      },
      group: [fn("MONTH", col("created_at"))],
      having: literal("SUM(amount) > 0"),
      order: [[fn("MONTH", col("created_at")), "ASC"]],
    });

    return results.map((result) => ({
      month: parseInt(result.dataValues.month),
      total_amount: parseFloat(result.dataValues.total_amount),
    }));
  }

  /**
   * Get monthly sales for a year by shipping_dock_id (only months with sales > 0)
   */
  static async getMonthlySalesByShippingDock(model, year, shippingDockId) {
    const results = await model.findAll({
      attributes: [
        [fn("MONTH", col("created_at")), "month"],
        [fn("SUM", col("amount")), "total_amount"],
      ],
      where: {
        created_at: {
          [Op.and]: [literal(`YEAR(created_at) = ${year}`)],
        },
        shipping_dock_id: shippingDockId,
      },
      group: [fn("MONTH", col("created_at"))],
      having: literal("SUM(amount) > 0"),
      order: [[fn("MONTH", col("created_at")), "ASC"]],
    });

    return results.map((result) => ({
      month: parseInt(result.dataValues.month),
      total_amount: parseFloat(result.dataValues.total_amount),
    }));
  }

  /**
   * Get order count per month for a user in a year (include months with 0 orders)
   */
  static async getOrderCountByUser(model, year, userId) {
    // First get all months with orders
    const orderMonths = await model.findAll({
      attributes: [
        [fn("MONTH", col("created_at")), "month"],
        [fn("COUNT", col("id")), "order_count"],
      ],
      where: {
        created_at: {
          [Op.and]: [literal(`YEAR(created_at) = ${year}`)],
        },
        user_id: userId,
      },
      group: [fn("MONTH", col("created_at"))],
      order: [[fn("MONTH", col("created_at")), "ASC"]],
    });

    // Create a map of months with orders
    const monthMap = {};
    orderMonths.forEach((result) => {
      monthMap[parseInt(result.dataValues.month)] = parseInt(
        result.dataValues.order_count
      );
    });

    // Create result array with all 12 months
    const result = [];
    for (let month = 1; month <= 12; month++) {
      result.push({
        month,
        order_count: monthMap[month] || 0,
      });
    }

    return result;
  }
}

module.exports = ReportService;
