// controllers/serviceStats.ts
import { Request, Response } from "express";
import { getRepository, In } from "typeorm";
import dayjs from "dayjs";
import DeceasedRetail from "@/entity/DeceasedRetail";
import SeletedServiceList from "@/entity/SeletedServiceList";
import ServiceItem from "@/entity/ServiceItem";
import ServiceCategory from "@/entity/ServiceCategory";
import { handleError } from "@/util/globalMethods";

// 类型定义
interface ServiceStatsItem {
  serviceName: string;
  price: number;
  unit: string;
  quantity: number;
  subtotal: number;
}

interface CategoryStats {
  categoryName: string;
  services: ServiceStatsItem[];
  totalQuantity: number;
  totalAmount: number;
}

interface StatsResponse {
  categories: CategoryStats[];
  otherCategory: CategoryStats;
  grandTotalQuantity: number;
  grandTotalAmount: number;
}

interface QueryParams {
  startDate?: string;
  endDate?: string;
  serviceName?: string;
  categoryName?: string;
}

export const getServiceStats = async (req: Request, res: Response) => {
  try {
    // 1. 参数解析和验证
    const params = parseQueryParams(
      req.method === "GET" ? req.query : req.body
    );
    // 2. 查询符合条件的零售单（按结账时间）
    const retailRecords = await getRepository(DeceasedRetail)
      .createQueryBuilder("dr")
      .where("dr.checkoutDate BETWEEN :start AND :end", {
        start:
          params.startDate ||
          dayjs().startOf("day").format("YYYY-MM-DD HH:mm:ss"),
        end: params.endDate || dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss"),
      })
      .andWhere("dr.retailState = 1 AND  dr.cancelState = 0") // 只统计已结账的
      .getMany();

    // 3. 收集所有服务项目ID（从serviceItems字段）
    const allServiceItemIds = retailRecords
      .map((record) => {
        try {
          return record.serviceItems.split(",").map(Number);
        } catch (e) {
          return [];
        }
      })
      .flat()
      .filter((id) => id > 0); // 过滤无效ID

    if (allServiceItemIds.length === 0) {
      return res.json(emptyResponse());
    }

    // 4. 查询这些服务项目在SeletedServiceList中的记录
    const selectedServices = await getRepository(SeletedServiceList)
      .createQueryBuilder("ssl")
      .where("ssl.id IN (:...ids)", { ids: allServiceItemIds })
      .getMany();

    // 5. 收集所有不重复的服务名称
    const serviceNames = Array.from(
      new Set(selectedServices.map((s) => s.name))
    );
    if (serviceNames.length === 0) {
      return res.json(emptyResponse());
    }

    // 6. 分步查询分类信息
    // 第一步：查询ServiceItem获取parentIds
    const serviceItems = await getRepository(ServiceItem)
      .createQueryBuilder("si")
      .select(["si.name", "si.parentId"])
      .where("si.name IN (:...names)", { names: serviceNames })
      .getMany();

    // 第二步：收集所有parentIds
    const parentIds = Array.from(
      new Set(serviceItems.map((item) => item.parentId))
    );

    // 第三步：批量查询分类名称
    const categories = await getRepository(ServiceCategory)
      .createQueryBuilder("sc")
      .select(["sc.id", "sc.name"])
      .where({ id: In(parentIds) })
      .getMany();

    // 第四步：构建分类ID到名称的映射
    const categoryIdToName = new Map<number, string>();
    categories.forEach((cat) => categoryIdToName.set(cat.id, cat.name));

    // 第五步：构建服务名称到分类的映射
    const nameToCategoryMap = new Map<string, string>();
    serviceItems.forEach((item) => {
      const categoryName = categoryIdToName.get(item.parentId) || "其他服务";
      nameToCategoryMap.set(item.name, categoryName);
    });

    // 7. 初始化统计结构
    const categoryStats = new Map<string, ServiceStatsItem[]>();
    const otherServices: ServiceStatsItem[] = [];

    // 8. 处理每个服务项的统计
    const serviceNameToStats = new Map<string, ServiceStatsItem>();

    selectedServices.forEach((service) => {
      // 应用服务名称过滤条件
      if (params.serviceName && !service.name.includes(params.serviceName)) {
        return;
      }

      const existingItem = serviceNameToStats.get(service.name);
      if (existingItem) {
        // 如果已存在同名服务，则合并数量和金额
        existingItem.quantity += service.quantity;
        existingItem.subtotal += Number(service.price) * service.quantity;
      } else {
        // 否则创建新条目
        serviceNameToStats.set(service.name, {
          serviceName: service.name,
          price: Number(service.price),
          unit: service.unit,
          quantity: service.quantity,
          subtotal: Number(service.price) * service.quantity,
        });
      }
    });

    // // 9. 将合并后的服务项按分类分组
    // const categoryStats = new Map<string, ServiceStatsItem[]>();
    // const otherServices: ServiceStatsItem[] = [];

    serviceNameToStats.forEach((statsItem, serviceName) => {
      // 获取分类名称，默认为"其他服务"
      const categoryName = nameToCategoryMap.get(serviceName) || "其他服务";

      // 分类到对应分组
      if (categoryName === "其他服务") {
        otherServices.push(statsItem);
      } else {
        if (!categoryStats.has(categoryName)) {
          categoryStats.set(categoryName, []);
        }
        categoryStats.get(categoryName)?.push(statsItem);
      }
    });

    // 9. 应用分类过滤条件
    if (params.categoryName) {
      if (params.categoryName !== "其他服务") {
        categoryStats.forEach((_, key) => {
          if (key !== params.categoryName) {
            categoryStats.delete(key);
          }
        });
      } else {
        categoryStats.clear(); // 只保留其他服务
      }
    }

    // 10. 构建最终响应
    const response = buildFinalResponse(categoryStats, otherServices);
    res.json({ code: 200, data: response });
  } catch (error) {
    handleError(res, error);
  }
};

// 辅助函数
const emptyResponse = (): StatsResponse => ({
  categories: [],
  otherCategory: {
    categoryName: "其他服务",
    services: [],
    totalQuantity: 0,
    totalAmount: 0,
  },
  grandTotalQuantity: 0,
  grandTotalAmount: 0,
});

const buildFinalResponse = (
  categoryMap: Map<string, ServiceStatsItem[]>,
  otherItems: ServiceStatsItem[]
): StatsResponse => {
  const categories: CategoryStats[] = [];
  let grandTotalQuantity = 0;
  let grandTotalAmount = 0;

  // 处理分类数据
  categoryMap.forEach((items, categoryName) => {
    const totalQuantity = items.reduce((sum, item) => sum + item.quantity, 0);
    const totalAmount = items.reduce((sum, item) => sum + item.subtotal, 0);

    categories.push({
      categoryName,
      services: items,
      totalQuantity,
      totalAmount,
    });

    grandTotalQuantity += totalQuantity;
    grandTotalAmount += totalAmount;
  });

  // 处理其他分类
  const otherTotalQuantity = otherItems.reduce(
    (sum, item) => sum + item.quantity,
    0
  );
  const otherTotalAmount = otherItems.reduce(
    (sum, item) => sum + item.subtotal,
    0
  );

  grandTotalQuantity += otherTotalQuantity;
  grandTotalAmount += otherTotalAmount;

  return {
    categories,
    otherCategory: {
      categoryName: "其他服务",
      services: otherItems,
      totalQuantity: otherTotalQuantity,
      totalAmount: otherTotalAmount,
    },
    grandTotalQuantity,
    grandTotalAmount,
  };
};

const parseQueryParams = (query: any): QueryParams => {
  const { startDate, endDate, serviceName, categoryName } = query;

  // 日期格式验证
  const validateDate = (date: string, field: string) => {
    if (date && !dayjs(date).isValid()) {
      throw new Error(`${field}格式错误，请使用YYYY-MM-DD格式`);
    }
  };

  validateDate(startDate, "开始日期");
  validateDate(endDate, "结束日期");

  return {
    startDate: startDate?.trim(),
    endDate: endDate?.trim(),
    serviceName: serviceName?.trim(),
    categoryName: categoryName?.trim(),
  };
};
