const Sequelize = require("sequelize");
const { Op } = Sequelize;
const baseModel = require("../../middleware/baseModel");
const { build_search_where } = require("../utils/query_helpers");

function build_date_where(start_date, end_date) {
  const where = {};
  if (start_date && end_date) {
    where.call_date = { [Op.between]: [start_date, end_date] };
  } else if (start_date) {
    where.call_date = { [Op.gte]: start_date };
  } else if (end_date) {
    where.call_date = { [Op.lte]: end_date };
  }
  return where;
}

module.exports = {
  "POST /biz_api_stats/by_user": async (ctx) => {
    const body = ctx.getBody();
    const { user_id, start_date, end_date } = body;
    if (!user_id) {
      ctx.fail("缺少 user_id");
      return;
    }
    const where = { user_id, ...build_date_where(start_date, end_date) };
    const rows = await baseModel.biz_api_call_log.findAll({
      attributes: [
        "api_path",
        [baseModel.Sequelize.fn("COUNT", baseModel.Sequelize.col("id")), "call_count"],
        [baseModel.Sequelize.fn("AVG", baseModel.Sequelize.col("response_time")), "avg_response_time"],
      ],
      where,
      group: ["api_path"],
      order: [[baseModel.Sequelize.literal("call_count"), "DESC"]],
      raw: true,
    });
    const total = rows.reduce((s, r) => s + Number(r.call_count), 0);
    ctx.success({ total, rows });
  },

  "POST /biz_api_stats/by_api": async (ctx) => {
    const body = ctx.getBody();
    const { api_path, start_date, end_date } = body;
    if (!api_path) {
      ctx.fail("缺少 api_path");
      return;
    }
    const where = { api_path, ...build_date_where(start_date, end_date) };
    const rows = await baseModel.biz_api_call_log.findAll({
      attributes: [
        "user_id",
        [baseModel.Sequelize.fn("COUNT", baseModel.Sequelize.col("id")), "call_count"],
        [baseModel.Sequelize.fn("AVG", baseModel.Sequelize.col("response_time")), "avg_response_time"],
      ],
      where,
      group: ["user_id"],
      order: [[baseModel.Sequelize.literal("call_count"), "DESC"]],
      raw: true,
    });
    const total = rows.reduce((s, r) => s + Number(r.call_count), 0);
    ctx.success({ total, rows });
  },

  "POST /biz_api_stats/summary": async (ctx) => {
    const body = ctx.getBody();
    const { start_date, end_date, top_limit } = body;
    const dateWhere = build_date_where(start_date, end_date);
    const Seq = baseModel.Sequelize;
    const lim = top_limit || 10;

    const totalResult = await baseModel.biz_api_call_log.count({ where: dateWhere });

    const daily_trend = await baseModel.biz_api_call_log.findAll({
      attributes: ["call_date", [Seq.fn("COUNT", Seq.col("id")), "call_count"]],
      where: dateWhere,
      group: ["call_date"],
      order: [["call_date", "ASC"]],
      raw: true,
    });

    const top_apis = await baseModel.biz_api_call_log.findAll({
      attributes: ["api_path", [Seq.fn("COUNT", Seq.col("id")), "call_count"]],
      where: dateWhere,
      group: ["api_path"],
      order: [[Seq.literal("call_count"), "DESC"]],
      limit: lim,
      raw: true,
    });

    const top_users = await baseModel.biz_api_call_log.findAll({
      attributes: ["user_id", [Seq.fn("COUNT", Seq.col("id")), "call_count"]],
      where: dateWhere,
      group: ["user_id"],
      order: [[Seq.literal("call_count"), "DESC"]],
      limit: lim,
      raw: true,
    });

    ctx.success({
      total_calls: totalResult,
      daily_trend,
      top_apis,
      top_users,
    });
  },

  "POST /biz_api_call_log/page": async (ctx) => {
    const body = ctx.getBody();
    const param = body.param || body;
    const page_option = param.pageOption || {};
    const seach_option = param.seachOption || {};
    const page_num = parseInt(page_option.page, 10) || 1;
    const page_size = parseInt(page_option.pageSize, 10) || 20;
    const offset = (page_num - 1) * page_size;
    const biz_api_call_log = baseModel.biz_api_call_log;
    const where = build_search_where(biz_api_call_log, seach_option);
    const { count, rows } = await biz_api_call_log.findAndCountAll({
      where,
      offset,
      limit: page_size,
      order: [["id", "DESC"]],
    });
    ctx.success({ rows, count });
  },
};
