package service

import (
	"boss/internal/common"
	"boss/internal/config"
	"boss/internal/datas"
	"boss/internal/models/order"
	"boss/internal/models/payfor"
	"boss/internal/models/road"
	"boss/internal/models/user"
	"boss/internal/utils/mfa"
	"context"
	"fmt"
	"math"
	"time"

	"github.com/duke-git/lancet/v2/slice"

	"github.com/beego/beego/v2/client/httplib"
	"github.com/beego/beego/v2/core/logs"
)

type QueryService struct {
}

func OrderQuery(ctx context.Context, bankOrderId string) string {
	orderInfo := order.GetOrderByBankOrderId(ctx, bankOrderId)
	if orderInfo.BankOrderId == "" || len(orderInfo.BankOrderId) == 0 {
		logs.Error("不存在这样的订单，订单查询结束")
		return "不存在这样的订单"
	}

	if orderInfo.Status != "" && orderInfo.Status != "wait" {
		logs.Error(fmt.Sprintf("该订单=%s，已经处理完毕，", bankOrderId))
		return "该订单已经处理完毕"
	}

	// 向gateway发送请求，请求上游的支付结果
	gUrl := "http://kami_gateway:12309/" + "gateway/supplier/order/query" + "?" + "bankOrderId=" + bankOrderId
	res, err := httplib.Get(gUrl).String()
	if err != nil {
		logs.Error("获取gateway上游订单查询结果失败：" + err.Error())
	}

	logs.Info("请求远程地址", gUrl, "远程返回结果：", res)
	return res
}

func (c *QueryService) SupplierOrderQuery(ctx context.Context, bankOrderId string) *datas.KeyDataJSON {
	keyDataJSON := new(datas.KeyDataJSON)
	keyDataJSON.Code = 200
	exist := order.BankOrderIdIsExist(ctx, bankOrderId)
	if !exist {
		keyDataJSON.Msg = "该订单不存在"
		keyDataJSON.Code = -1
	}

	msg := OrderQuery(ctx, bankOrderId)

	keyDataJSON.Msg = msg
	return keyDataJSON
}

func (c *QueryService) SupplierPayForQuery(ctx context.Context, bankOrderId string) *datas.KeyDataJSON {
	keyDataJSON := new(datas.KeyDataJSON)
	keyDataJSON.Code = 200

	if bankOrderId == "" {
		keyDataJSON.Code = -1
		keyDataJSON.Msg = "不存在这样的代付订单"
	} else {
		payFor := payfor.GetPayForByBankOrderId(ctx, bankOrderId)
		if payFor.RoadUid == "" {
			keyDataJSON.Msg = "该代付订单没有对应的通道uid"
		} else {
			result := querySupplierPayForResult(ctx, bankOrderId)
			if result {
				keyDataJSON.Msg = "处理成功！"
			} else {
				keyDataJSON.Msg = "处理失败！"
			}
		}
	}
	return keyDataJSON
}

func querySupplierPayForResult(ctx context.Context, bankOrderId string) bool {
	u := config.GetGatewayHost() + "gateway/supplier/payfor/query" + "?bankOrderId=" + bankOrderId
	s, err := httplib.Get(u).String()
	if err != nil {
		logs.Error("处理代付查询请求gateway失败：", err)
		return false
	}
	if s == "fail" {
		return false
	} else {
		return true
	}
}

func QueryTotalSummary(ctx context.Context, params map[string]string) order.Summary {
	summaryInfos, err := order.GetOrderRawSummary(ctx, params)
	if err != nil {
		logs.Error("获取订单汇总信息失败：", err)
	}
	profit, err := order.GetOrderProfitRawSummary(ctx, params)
	if err != nil {
		logs.Error("获取订单利润信息失败：", err)
	}
	output := order.Summary{}
	slice.ForEach(summaryInfos, func(index int, item order.OrderSummaryOutput) {
		output.TotalAmount += item.TotalOrderAmount
		output.TotalNum += item.TotalOrderCount
		output.PaidNum += item.SuccessFactCount
		output.PaidAmount += item.SuccessFactAmount
	})
	if output.TotalNum == 0 {
		output.SucceedRate = 0
	} else {
		output.SucceedRate = math.Round(float64(output.PaidNum)/float64(output.TotalNum)*100*100) / 100
	}
	output.PlatformIncome = profit
	return output
}

func QuerySummaryByOrderInfo(ctx context.Context, infoInfoList []order.OrderInfo) order.Summary {
	orderProfitInfoList := make([]order.OrderProfitInfo, 0)

	for _, info := range infoInfoList {
		orderProfitInfoList = append(orderProfitInfoList, order.GetOrderProfitByBankOrderId(ctx, info.BankOrderId))
	}

	totalNum := 0
	todayAllAmount := 0.0
	todaySupplierAll := 0.0
	todayPlatformAll := 0.0
	todayAgentAll := 0.0
	TodaySuccessNum := 0

	for _, info := range orderProfitInfoList {
		totalNum += 1
		todayAllAmount += info.FactAmount

		if info.Status != common.OrderStatusSuccess {
			continue
		}

		todaySupplierAll += info.SupplierProfit
		todayPlatformAll += info.PlatformProfit
		todayAgentAll += info.AgentProfit
		TodaySuccessNum += 1
	}

	succeedRate := 0.0

	if totalNum != 0 {
		succeedRate = math.Round(float64(TodaySuccessNum)/float64(totalNum)*100*100) / 100
	} else {
		succeedRate = 0
	}

	return order.Summary{
		TotalNum:       int64(totalNum),
		TotalAmount:    math.Round(todayAllAmount*100) / 100,
		PaidNum:        int64(TodaySuccessNum),
		PlatformIncome: math.Round(todayPlatformAll*100) / 100,
		AgencyIncome:   todayAgentAll,
		SucceedRate:    succeedRate,
	}
}

func QueryTodaySummary(ctx context.Context, params map[string]string) order.Summary {
	now := time.Now()
	todayAtMidnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
	tomorrowAtMidNight := todayAtMidnight.Add(time.Hour * 24)

	st := todayAtMidnight.Format("2006-01-02 15:04:05")
	end := tomorrowAtMidNight.Format("2006-01-02 15:04:05")

	paramsProfit := params
	if startTimeStr, exists := paramsProfit["create_time__gte"]; exists {
		startTime, err := time.Parse("2006-01-02 15:04:05", startTimeStr)
		if err != nil {
			paramsProfit["create_time__gte"] = st
		} else {
			if tomorrowAtMidNight.Before(startTime) || todayAtMidnight.After(startTime) {
				paramsProfit["create_time__gte"] = st
			}
		}
	} else {
		paramsProfit["create_time__gte"] = st
	}

	if endTimeStr, exists := paramsProfit["create_time__lte"]; exists {
		endTime, err := time.Parse("2006-01-02 15:04:05", endTimeStr)
		if err != nil {
			paramsProfit["create_time__gte"] = st
		} else {
			if tomorrowAtMidNight.Before(endTime) || todayAtMidnight.After(endTime) {
				paramsProfit["create_time__gte"] = st
			}
		}
	} else {
		paramsProfit["create_time__lte"] = end
	}

	summaryInfos, err := order.GetOrderRawSummary(ctx, paramsProfit)
	if err != nil {
		logs.Error("获取订单汇总信息失败：", err)
	}
	profit, err := order.GetOrderProfitRawSummary(ctx, params)
	if err != nil {
		logs.Error("获取订单利润信息失败：", err)
	}
	output := order.Summary{}
	slice.ForEach(summaryInfos, func(index int, item order.OrderSummaryOutput) {
		output.TotalAmount += item.TotalOrderAmount
		output.TotalNum += item.TotalOrderCount
		output.PaidNum += item.SuccessFactCount
		output.PaidAmount += item.SuccessFactAmount
	})
	if output.TotalNum == 0 {
		output.SucceedRate = 0
	} else {
		output.SucceedRate = math.Round(float64(output.PaidNum)/float64(output.TotalNum)*100*100) / 100
	}
	output.PlatformIncome = profit
	return output

	//
	//todaySuccessNum := 0
	//todayAllAmount := 0.0
	//todaySupplierAll := 0.0
	//todayPlatformAll := 0.0
	//todayAgentAll := 0.0
	//todayPaidAmount := 0.0
	//
	//totalNum := order.GetOrderCountByMap(ctx, paramsProfit)
	//for i := int64(0); i < totalNum; i += 1000 {
	//	orderInfoList := order.GetOrderByMap(ctx, paramsProfit, 1000, i)
	//	bankIdList := slice.Map(orderInfoList, func(index int, item order.OrderInfo) string {
	//		return item.BankOrderId
	//	})
	//	dataInfo := order.GetOrderProfitListByBankOrderIdList(ctx, bankIdList)
	//	for _, info := range dataInfo {
	//		todayAllAmount += info.FactAmount
	//		if info.Status != common.OrderStatusSuccess {
	//			continue
	//		}
	//		todaySupplierAll += info.SupplierProfit
	//		todayPlatformAll += info.PlatformProfit
	//		todayAgentAll += info.AgentProfit
	//		todayPaidAmount += info.FactAmount
	//		todaySuccessNum += 1
	//	}
	//}
	//
	//succeedRate := 0.0
	//if totalNum != 0 {
	//	succeedRate = math.Round(float64(todaySuccessNum)/float64(totalNum)*100*100) / 100
	//}
	//return order.Summary{
	//	TotalNum:       int64(totalNum),
	//	TotalAmount:    math.Round(todayAllAmount*100) / 100,
	//	PaidNum:        int64(todaySuccessNum),
	//	PaidAmount:     todayPaidAmount,
	//	PlatformIncome: math.Round(todayPlatformAll*100) / 100,
	//	AgencyIncome:   todayAgentAll,
	//	SucceedRate:    succeedRate,
	//}
}

func ValidTotp(ctx context.Context, accountUid, totpCode string) bool {
	userInfo := user.GetUserInfoByUserID(ctx, accountUid)
	if userInfo.Id == 0 {
		return false
	}
	if userInfo.OtpSecret == "" {
		return true
	}
	return mfa.ValidCode(totpCode, userInfo.OtpSecret)
}

func QueryRoad(ctx context.Context) []road.RoadInfo {
	roadInfoList := road.GetAllRoad(ctx, map[string]string{})
	return roadInfoList
}
