package order

import (
	"context"
	"strings"
	"time"

	"github.com/beego/beego/v2/client/orm"
	"github.com/beego/beego/v2/core/logs"
	datastructure "github.com/duke-git/lancet/v2/datastructure/list"
	"github.com/duke-git/lancet/v2/slice"
)

type OrderProfitInfo struct {
	Id              int
	MerchantName    string
	MerchantUid     string
	AgentName       string
	AgentUid        string
	PayProductCode  string
	PayProductName  string
	PayTypeCode     string
	PayTypeName     string
	Status          string
	MerchantOrderId string
	BankOrderId     string
	BankTransId     string
	OrderAmount     float64
	ShowAmount      float64
	FactAmount      float64 //实际支付金额
	UserInAmount    float64
	SupplierRate    float64
	PlatformRate    float64
	AgentRate       float64
	AllProfit       float64
	SupplierProfit  float64
	PlatformProfit  float64
	AgentProfit     float64
	UpdateTime      time.Time
	CreateTime      time.Time
}

const ORDER_PROFIT_INFO = "order_profit_info"

func GetOrderProfitByBankOrderId(ctx context.Context, bankOrderId string) OrderProfitInfo {
	o := orm.NewOrm()
	var orderProfit OrderProfitInfo
	_, err := o.QueryTable(ORDER_PROFIT_INFO).Filter("bank_order_id", bankOrderId).Limit(1).AllWithCtx(ctx, &orderProfit)
	if err != nil {
		logs.Error("GetOrderProfitByBankOrderId fail：", err)
	}
	return orderProfit
}

func GetOrderProfitListByBankOrderIdList(ctx context.Context, bankOrderIdList []string) []OrderProfitInfo {
	o := orm.NewOrm()
	orderProfitList := datastructure.NewCopyOnWriteList([]OrderProfitInfo{})
	orderProfitListUnsafe := make([]OrderProfitInfo, 0)
	if len(bankOrderIdList) == 0 {
		orderProfitList.ForEach(func(info OrderProfitInfo) {
			orderProfitListUnsafe = append(orderProfitListUnsafe, info)
		})
		return orderProfitListUnsafe
	}
	bankOrderIdList = slice.Unique(bankOrderIdList)
	slice.ForEach(slice.Chunk(bankOrderIdList, 100), func(index int, item []string) {
		tmpOrderProfitListTmp := make([]OrderProfitInfo, 0)
		_, err := o.QueryTable(ORDER_PROFIT_INFO).Filter("bank_order_id__in", item).AllWithCtx(ctx, &tmpOrderProfitListTmp)
		if err != nil {
			logs.Error("GetOrderProfitByBankOrderId fail：", err)
			return
		}
		orderProfitList.AddAll(tmpOrderProfitListTmp)
	})
	orderProfitList.ForEach(func(info OrderProfitInfo) {
		orderProfitListUnsafe = append(orderProfitListUnsafe, info)
	})
	return orderProfitListUnsafe
}

func GetAllOrderProfit(ctx context.Context, params map[string]string) []OrderProfitInfo {
	o := orm.NewOrm()
	var orderProfit []OrderProfitInfo
	qs := o.QueryTable(ORDER_PROFIT_INFO)
	for k, v := range params {
		if len(v) > 0 {
			qs = qs.Filter(k, v)
		}
	}
	_, err := qs.RelatedSel().AllWithCtx(ctx, &orderProfit)
	if err != nil {
		logs.Error("GetOrderProfitByBankOrderId fail：", err)
	}
	return orderProfit
}

func GetOrderProfitLenByMap(ctx context.Context, params map[string]interface{}) int {
	o := orm.NewOrm()
	qs := o.QueryTable(ORDER_PROFIT_INFO)
	for k, v := range params {
		switch v.(type) {
		case string:
			if len(v.(string)) > 0 {
				qs = qs.Filter(k, v)
			}
		default:
			qs = qs.Filter(k, v)
		}
	}
	cnt, _ := qs.Limit(-1).CountWithCtx(ctx)
	return int(cnt)
}

func GetOrderProfitByMap(ctx context.Context, params map[string]interface{}, display, offset int) []OrderProfitInfo {
	o := orm.NewOrm()
	var orderProfitInfoList []OrderProfitInfo
	qs := o.QueryTable(ORDER_PROFIT_INFO)
	for k, v := range params {
		switch v.(type) {
		case string:
			if len(v.(string)) > 0 {
				qs = qs.Filter(k, v)
			}
		default:
			qs = qs.Filter(k, v)
		}
	}
	_, err := qs.Limit(display, offset).OrderBy("-update_time").AllWithCtx(ctx, &orderProfitInfoList)
	if err != nil {
		logs.Error("get order by map fail: ", err)
	}
	return orderProfitInfoList
}

func GetPlatformProfitByMap(ctx context.Context, params map[string]string) []PlatformProfit {

	o := orm.NewOrm()

	cond := "select merchant_name, agent_name, pay_product_name as supplier_name, pay_type_name, sum(fact_amount) as order_amount, count(1) as order_count, " +
		"sum(platform_profit) as platform_profit, sum(agent_profit) as agent_profit from " + ORDER_PROFIT_INFO + " where status='success' "
	flag := false
	for k, v := range params {
		if len(v) > 0 {
			if flag {
				cond += " and"
			}
			if strings.Contains(k, "create_time__gte") {
				cond = cond + " create_time>='" + v + "'"
			} else if strings.Contains(k, "create_time__lte") {
				cond = cond + " create_time<='" + v + "'"
			} else {
				cond = cond + " " + k + "='" + v + "'"
			}
			flag = true
		}
	}

	logs.Info(cond)
	var platformProfitList []PlatformProfit
	_, err := o.Raw(cond).QueryRows(&platformProfitList)
	if err != nil {
		logs.Error("get platform profit by map fail:", err)
	}

	return platformProfitList
}
