package agent

import (
	"context"
	"time"
	"bdqr-server/app/main/model"
	"bdqr-server/common/ctxdata"
	"bdqr-server/common/globalkey"
	"bdqr-server/common/xerr"

	"github.com/Masterminds/squirrel"
	"github.com/pkg/errors"

	"bdqr-server/app/main/api/internal/svc"
	"bdqr-server/app/main/api/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetConversionRateLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetConversionRateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetConversionRateLogic {
	return &GetConversionRateLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetConversionRateLogic) GetConversionRate() (resp *types.ConversionRateResp, err error) {
	userID, err := ctxdata.GetUidFromCtx(l.ctx)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户信息失败, %v", err)
	}

	// 1. 获取代理信息
	agent, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
	if err != nil {
		if errors.Is(err, model.ErrNotFound) {
			return nil, errors.Wrapf(xerr.NewErrMsg("您不是代理"), "")
		}
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败, %v", err)
	}

	// 2. 统计我的转化率
	myConversionRate := l.calculateConversionRate(agent.Id, nil)

	// 3. 统计下级转化率（按时间段动态查询历史下级关系）
	subordinateConversionRate := l.calculateSubordinateConversionRate(agent.Id)

	return &types.ConversionRateResp{
		MyConversionRate:          myConversionRate,
		SubordinateConversionRate: subordinateConversionRate,
	}, nil
}

// calculateSubordinateConversionRate 计算下级转化率（考虑历史关系）
func (l *GetConversionRateLogic) calculateSubordinateConversionRate(parentAgentId string) types.ConversionRateData {
	// 使用Asia/Shanghai时区，与数据库保持一致
	loc, _ := time.LoadLocation("Asia/Shanghai")
	now := time.Now().In(loc)

	// 日统计：今日、昨日、前日
	todayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc)
	todayEnd := todayStart.AddDate(0, 0, 1)
	yesterdayStart := todayStart.AddDate(0, 0, -1)
	yesterdayEnd := todayStart
	dayBeforeStart := todayStart.AddDate(0, 0, -2)
	dayBeforeEnd := yesterdayStart

	daily := []types.PeriodConversionData{
		l.calculateSubordinatePeriodConversion(parentAgentId, "今日", todayStart, todayEnd),
		l.calculateSubordinatePeriodConversion(parentAgentId, "昨日", yesterdayStart, yesterdayEnd),
		l.calculateSubordinatePeriodConversion(parentAgentId, "前日", dayBeforeStart, dayBeforeEnd),
	}

	// 周统计：本周、上周、上上周
	weekdayOffset := int(now.Weekday())
	if weekdayOffset == 0 {
		weekdayOffset = 7 // 周日算作第7天
	}
	thisWeekStart := now.AddDate(0, 0, -(weekdayOffset - 1))
	thisWeekStart = time.Date(thisWeekStart.Year(), thisWeekStart.Month(), thisWeekStart.Day(), 0, 0, 0, 0, loc)
	thisWeekEnd := now
	lastWeekStart := thisWeekStart.AddDate(0, 0, -7)
	lastWeekEnd := thisWeekStart
	lastTwoWeekStart := thisWeekStart.AddDate(0, 0, -14)
	lastTwoWeekEnd := lastWeekStart

	weekly := []types.PeriodConversionData{
		l.calculateSubordinatePeriodConversion(parentAgentId, "本周", thisWeekStart, thisWeekEnd),
		l.calculateSubordinatePeriodConversion(parentAgentId, "上周", lastWeekStart, lastWeekEnd),
		l.calculateSubordinatePeriodConversion(parentAgentId, "上上周", lastTwoWeekStart, lastTwoWeekEnd),
	}

	// 月统计：本月、上月、前两月
	thisMonthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, loc)
	thisMonthEnd := now
	lastMonthStart := thisMonthStart.AddDate(0, -1, 0)
	lastMonthEnd := thisMonthStart
	lastTwoMonthStart := thisMonthStart.AddDate(0, -2, 0)
	lastTwoMonthEnd := lastMonthStart

	monthly := []types.PeriodConversionData{
		l.calculateSubordinatePeriodConversion(parentAgentId, "本月", thisMonthStart, thisMonthEnd),
		l.calculateSubordinatePeriodConversion(parentAgentId, "上月", lastMonthStart, lastMonthEnd),
		l.calculateSubordinatePeriodConversion(parentAgentId, "前两月", lastTwoMonthStart, lastTwoMonthEnd),
	}

	return types.ConversionRateData{
		Daily:   daily,
		Weekly:  weekly,
		Monthly: monthly,
	}
}

// calculateConversionRate 计算转化率
// agentId > 0 时统计该代理的转化率，否则统计 subordinateIds 列表的转化率
func (l *GetConversionRateLogic) calculateConversionRate(agentId string, subordinateIds []string) types.ConversionRateData {
	// 使用Asia/Shanghai时区，与数据库保持一致
	loc, _ := time.LoadLocation("Asia/Shanghai")
	now := time.Now().In(loc)

	// 日统计：今日、昨日、前日
	todayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc)
	todayEnd := todayStart.AddDate(0, 0, 1)
	yesterdayStart := todayStart.AddDate(0, 0, -1)
	yesterdayEnd := todayStart
	dayBeforeStart := todayStart.AddDate(0, 0, -2)
	dayBeforeEnd := yesterdayStart

	daily := []types.PeriodConversionData{
		l.calculatePeriodConversion(agentId, subordinateIds, "今日", todayStart, todayEnd),
		l.calculatePeriodConversion(agentId, subordinateIds, "昨日", yesterdayStart, yesterdayEnd),
		l.calculatePeriodConversion(agentId, subordinateIds, "前日", dayBeforeStart, dayBeforeEnd),
	}

	// 周统计：本周、上周、上上周
	// 本周：本周一00:00:00 到现在
	weekdayOffset := int(now.Weekday())
	if weekdayOffset == 0 {
		weekdayOffset = 7 // 周日算作第7天
	}
	// 计算本周一：当前日期减去(weekdayOffset-1)天
	thisWeekStart := now.AddDate(0, 0, -(weekdayOffset - 1))
	thisWeekStart = time.Date(thisWeekStart.Year(), thisWeekStart.Month(), thisWeekStart.Day(), 0, 0, 0, 0, loc)
	thisWeekEnd := now
	lastWeekStart := thisWeekStart.AddDate(0, 0, -7)
	lastWeekEnd := thisWeekStart
	lastTwoWeekStart := thisWeekStart.AddDate(0, 0, -14)
	lastTwoWeekEnd := lastWeekStart

	weekly := []types.PeriodConversionData{
		l.calculatePeriodConversion(agentId, subordinateIds, "本周", thisWeekStart, thisWeekEnd),
		l.calculatePeriodConversion(agentId, subordinateIds, "上周", lastWeekStart, lastWeekEnd),
		l.calculatePeriodConversion(agentId, subordinateIds, "上上周", lastTwoWeekStart, lastTwoWeekEnd),
	}

	// 月统计：本月、上月、前两月
	thisMonthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, loc)
	thisMonthEnd := now
	lastMonthStart := thisMonthStart.AddDate(0, -1, 0)
	lastMonthEnd := thisMonthStart
	lastTwoMonthStart := thisMonthStart.AddDate(0, -2, 0)
	lastTwoMonthEnd := lastMonthStart

	monthly := []types.PeriodConversionData{
		l.calculatePeriodConversion(agentId, subordinateIds, "本月", thisMonthStart, thisMonthEnd),
		l.calculatePeriodConversion(agentId, subordinateIds, "上月", lastMonthStart, lastMonthEnd),
		l.calculatePeriodConversion(agentId, subordinateIds, "前两月", lastTwoMonthStart, lastTwoMonthEnd),
	}

	return types.ConversionRateData{
		Daily:   daily,
		Weekly:  weekly,
		Monthly: monthly,
	}
}

// calculatePeriodConversion 计算指定时间段的转化率数据
func (l *GetConversionRateLogic) calculatePeriodConversion(agentId string, subordinateIds []string, periodLabel string, startTime, endTime time.Time) types.PeriodConversionData {
	// 构建 agent_order 查询条件
	agentOrderBuilder := l.svcCtx.AgentOrderModel.SelectBuilder().
		Where("del_state = ?", globalkey.DelStateNo).
		Where("create_time >= ? AND create_time < ?", startTime, endTime)

	if agentId != "" {
		// 统计我的转化率
		agentOrderBuilder = agentOrderBuilder.Where("agent_id = ?", agentId)
	} else if len(subordinateIds) > 0 {
		// 统计下级转化率
		agentOrderBuilder = agentOrderBuilder.Where(squirrel.Eq{"agent_id": subordinateIds})
	} else {
		// 没有数据
		l.Infof("calculatePeriodConversion: 没有代理ID或下级ID，periodLabel=%s", periodLabel)
		return types.PeriodConversionData{
			PeriodLabel:    periodLabel,
			QueryUsers:     0,
			PaidUsers:      0,
			TotalAmount:    0,
			QueryUserCount: 0,
			PaidUserCount:  0,
		}
	}

	// 添加调试日志
	if agentId == "" && len(subordinateIds) > 0 {
		l.Infof("calculatePeriodConversion: 统计下级转化率，periodLabel=%s, startTime=%v, endTime=%v, subordinateIds数量=%d",
			periodLabel, startTime, endTime, len(subordinateIds))
	}

	// 查询所有代理订单
	agentOrders, err := l.svcCtx.AgentOrderModel.FindAll(l.ctx, agentOrderBuilder, "")
	if err != nil && !errors.Is(err, model.ErrNotFound) {
		l.Errorf("查询代理订单失败: periodLabel=%s, err=%v", periodLabel, err)
		return types.PeriodConversionData{
			PeriodLabel:    periodLabel,
			QueryUsers:     0,
			PaidUsers:      0,
			TotalAmount:    0,
			QueryUserCount: 0,
			PaidUserCount:  0,
		}
	}

	if len(agentOrders) == 0 {
		if agentId == "" && len(subordinateIds) > 0 {
			l.Infof("calculatePeriodConversion: 未找到代理订单，periodLabel=%s, startTime=%v, endTime=%v",
				periodLabel, startTime, endTime)
		}
		return types.PeriodConversionData{
			PeriodLabel:    periodLabel,
			QueryUsers:     0,
			PaidUsers:      0,
			TotalAmount:    0,
			QueryUserCount: 0,
			PaidUserCount:  0,
		}
	}

	l.Infof("calculatePeriodConversion: 找到代理订单数量=%d, periodLabel=%s", len(agentOrders), periodLabel)

	// 收集订单ID
	orderIds := make([]string, 0, len(agentOrders))
	for _, ao := range agentOrders {
		orderIds = append(orderIds, ao.OrderId)
	}

	// 查询订单信息
	orderBuilder := l.svcCtx.OrderModel.SelectBuilder().
		Where(squirrel.Eq{"id": orderIds}).
		Where("del_state = ?", globalkey.DelStateNo)

	orders, err := l.svcCtx.OrderModel.FindAll(l.ctx, orderBuilder, "")
	if err != nil && !errors.Is(err, model.ErrNotFound) {
		l.Errorf("查询订单失败: %v", err)
		return types.PeriodConversionData{
			PeriodLabel:    periodLabel,
			QueryUsers:     0,
			PaidUsers:      0,
			TotalAmount:    0,
			QueryUserCount: 0,
			PaidUserCount:  0,
		}
	}

	// 统计查询订单数、付费订单数、用户数和总金额
	var totalAmount float64
	paidOrderCount := 0
	queryUserSet := make(map[string]bool)
	paidUserSet := make(map[string]bool)

	for _, order := range orders {
		// 查询用户数（所有订单的用户，去重）
		queryUserSet[order.UserId] = true

		// 付费订单数和总金额（只统计已支付的订单）
		if order.Status == "paid" {
			paidOrderCount++
			paidUserSet[order.UserId] = true
			totalAmount += order.Amount
		}
	}

	// 查询订单数 = 所有订单数量
	queryOrderCount := len(orders)

	return types.PeriodConversionData{
		PeriodLabel:    periodLabel,
		QueryUsers:     int64(queryOrderCount), // 订单数量（保持向后兼容）
		PaidUsers:      int64(paidOrderCount),  // 订单数量（保持向后兼容）
		TotalAmount:    totalAmount,
		QueryUserCount: int64(len(queryUserSet)), // 用户数量（新增）
		PaidUserCount:  int64(len(paidUserSet)),  // 用户数量（新增）
	}
}

// calculateSubordinatePeriodConversion 计算指定时间段内下级转化率
// 结合使用agent_rebate表和agent_order表：
// 1. 查询量：通过agent_order表统计所有查询（包括未付费的）
// 2. 付费量和金额：通过agent_rebate表统计（只有付费的订单才会产生返佣）
func (l *GetConversionRateLogic) calculateSubordinatePeriodConversion(parentAgentId string, periodLabel string, startTime, endTime time.Time) types.PeriodConversionData {
	// 1. 查询agent_rebate表：获取所有曾经给当前用户产生返佣的source_agent_id（这些代理在某个时间点是下级）
	// 不限制时间，获取所有历史返佣记录，用于确定哪些代理曾经是下级
	rebateBuilder := l.svcCtx.AgentRebateModel.SelectBuilder().
		Where("agent_id = ? AND del_state = ?", parentAgentId, globalkey.DelStateNo).
		Where("source_agent_id != ?", parentAgentId)

	allRebates, err := l.svcCtx.AgentRebateModel.FindAll(l.ctx, rebateBuilder, "")
	if err != nil && !errors.Is(err, model.ErrNotFound) {
		l.Errorf("查询返佣记录失败: periodLabel=%s, err=%v", periodLabel, err)
		return types.PeriodConversionData{
			PeriodLabel:    periodLabel,
			QueryUsers:     0,
			PaidUsers:      0,
			TotalAmount:    0,
			QueryUserCount: 0,
			PaidUserCount:  0,
		}
	}

	// 收集所有曾经产生返佣的source_agent_id（这些代理在某个时间点是下级）
	sourceAgentIdSet := make(map[string]bool)
	paidOrderIdSet := make(map[string]bool)         // 已付费的订单ID（有返佣的订单）
	paidOrderIdToAmount := make(map[string]float64) // 已付费订单的金额

	for _, rebate := range allRebates {
		sourceAgentIdSet[rebate.SourceAgentId] = true
		// 如果返佣记录的创建时间在时间段内，说明该订单在时间段内已付费
		if rebate.CreateTime.After(startTime) || rebate.CreateTime.Equal(startTime) {
			if rebate.CreateTime.Before(endTime) {
				paidOrderIdSet[rebate.OrderId] = true
			}
		}
	}

	if len(sourceAgentIdSet) == 0 {
		l.Infof("calculateSubordinatePeriodConversion: 未找到返佣记录，periodLabel=%s, startTime=%v, endTime=%v",
			periodLabel, startTime, endTime)
		return types.PeriodConversionData{
			PeriodLabel:    periodLabel,
			QueryUsers:     0,
			PaidUsers:      0,
			TotalAmount:    0,
			QueryUserCount: 0,
			PaidUserCount:  0,
		}
	}

	sourceAgentIds := make([]string, 0, len(sourceAgentIdSet))
	for agentId := range sourceAgentIdSet {
		sourceAgentIds = append(sourceAgentIds, agentId)
	}

	l.Infof("calculateSubordinatePeriodConversion: periodLabel=%s, 曾经产生返佣的代理数量=%d", periodLabel, len(sourceAgentIds))

	// 2. 查询agent_order表：统计这些代理在时间段内的所有订单（包括未付费的）
	agentOrderBuilder := l.svcCtx.AgentOrderModel.SelectBuilder().
		Where("del_state = ?", globalkey.DelStateNo).
		Where("create_time >= ? AND create_time < ?", startTime, endTime).
		Where(squirrel.Eq{"agent_id": sourceAgentIds})

	agentOrders, err := l.svcCtx.AgentOrderModel.FindAll(l.ctx, agentOrderBuilder, "")
	if err != nil && !errors.Is(err, model.ErrNotFound) {
		l.Errorf("查询代理订单失败: periodLabel=%s, err=%v", periodLabel, err)
		return types.PeriodConversionData{
			PeriodLabel:    periodLabel,
			QueryUsers:     0,
			PaidUsers:      0,
			TotalAmount:    0,
			QueryUserCount: 0,
			PaidUserCount:  0,
		}
	}

	l.Infof("calculateSubordinatePeriodConversion: periodLabel=%s, 查询到代理订单数量=%d", periodLabel, len(agentOrders))

	if len(agentOrders) == 0 {
		return types.PeriodConversionData{
			PeriodLabel:    periodLabel,
			QueryUsers:     0,
			PaidUsers:      0,
			TotalAmount:    0,
			QueryUserCount: 0,
			PaidUserCount:  0,
		}
	}

	// 3. 通过order_id去重，获取所有订单ID（用于查询订单详情）
	orderIdSet := make(map[string]bool)
	orderIdToAgentOrder := make(map[string]*model.AgentOrder)

	for _, ao := range agentOrders {
		orderIdSet[ao.OrderId] = true
		// 如果同一个订单有多个agent_order记录，保留金额更大的
		if existing, exists := orderIdToAgentOrder[ao.OrderId]; exists {
			if ao.OrderAmount > existing.OrderAmount {
				orderIdToAgentOrder[ao.OrderId] = ao
			}
		} else {
			orderIdToAgentOrder[ao.OrderId] = ao
		}
	}

	orderIds := make([]string, 0, len(orderIdSet))
	for orderId := range orderIdSet {
		orderIds = append(orderIds, orderId)
	}

	// 4. 查询订单信息
	orderBuilder := l.svcCtx.OrderModel.SelectBuilder().
		Where(squirrel.Eq{"id": orderIds}).
		Where("del_state = ?", globalkey.DelStateNo)

	orders, err := l.svcCtx.OrderModel.FindAll(l.ctx, orderBuilder, "")
	if err != nil && !errors.Is(err, model.ErrNotFound) {
		l.Errorf("查询订单失败: %v", err)
		return types.PeriodConversionData{
			PeriodLabel:    periodLabel,
			QueryUsers:     0,
			PaidUsers:      0,
			TotalAmount:    0,
			QueryUserCount: 0,
			PaidUserCount:  0,
		}
	}

	// 5. 查询时间段内的返佣记录，获取已付费订单的金额
	rebateBuilder = l.svcCtx.AgentRebateModel.SelectBuilder().
		Where("agent_id = ? AND del_state = ?", parentAgentId, globalkey.DelStateNo).
		Where("source_agent_id != ?", parentAgentId).
		Where("create_time >= ? AND create_time < ?", startTime, endTime).
		Where(squirrel.Eq{"order_id": orderIds})

	rebates, err := l.svcCtx.AgentRebateModel.FindAll(l.ctx, rebateBuilder, "")
	if err != nil && !errors.Is(err, model.ErrNotFound) {
		l.Errorf("查询返佣记录失败: %v", err)
		return types.PeriodConversionData{
			PeriodLabel:    periodLabel,
			QueryUsers:     0,
			PaidUsers:      0,
			TotalAmount:    0,
			QueryUserCount: 0,
			PaidUserCount:  0,
		}
	}

	// 记录已付费订单的金额（使用agent_order的order_amount）
	for _, rebate := range rebates {
		if ao, exists := orderIdToAgentOrder[rebate.OrderId]; exists {
			paidOrderIdToAmount[rebate.OrderId] = ao.OrderAmount
		}
	}

	// 6. 统计查询订单数、付费订单数、用户数和总金额
	var totalAmount float64
	paidOrderCount := 0
	queryUserSet := make(map[string]bool)
	paidUserSet := make(map[string]bool)

	for _, order := range orders {
		// 查询用户数（所有订单的用户，去重）
		queryUserSet[order.UserId] = true

		// 付费订单数和总金额（只统计已付费的订单，即order_id在paidOrderIdToAmount中）
		if _, isPaid := paidOrderIdToAmount[order.Id]; isPaid {
			paidOrderCount++
			paidUserSet[order.UserId] = true
			// 使用agent_order的order_amount（用户实际支付金额）
			totalAmount += paidOrderIdToAmount[order.Id]
		}
	}

	// 查询订单数 = 所有订单数量
	queryOrderCount := len(orders)

	l.Infof("calculateSubordinatePeriodConversion: periodLabel=%s, 查询订单数=%d, 付费订单数=%d, 查询用户数=%d, 付费用户数=%d, 总金额=%.2f",
		periodLabel, queryOrderCount, paidOrderCount, len(queryUserSet), len(paidUserSet), totalAmount)

	return types.PeriodConversionData{
		PeriodLabel:    periodLabel,
		QueryUsers:     int64(queryOrderCount), // 订单数量（保持向后兼容）
		PaidUsers:      int64(paidOrderCount),  // 订单数量（保持向后兼容）
		TotalAmount:    totalAmount,
		QueryUserCount: int64(len(queryUserSet)), // 用户数量（新增）
		PaidUserCount:  int64(len(paidUserSet)),  // 用户数量（新增）
	}
}
