package bbxt

import (
	"ai_scheduler/internal/config"
	pkginner "ai_scheduler/internal/pkg"
	"ai_scheduler/internal/pkg/lsxd"
	"ai_scheduler/internal/pkg/utils_oss"
	"ai_scheduler/pkg"
	"context"
	"fmt"
	"math/rand"
	"slices"
	"sort"

	"time"

	"github.com/shopspring/decimal"
)

const (
	RedStyle   = "${color: FF0000;horizontal:center;vertical:center;borderColor:#000000}"
	GreenStyle = "${color: 008000;horizontal:center;vertical:center;borderColor:#000000}"
)

const (
	IndexLossSumDetail = "lossSumDetail"
)

type LossSumInitFunc func(ctx context.Context, day time.Time, totalDetail []*ResellerLoss, selfObj *BbxtTools) error

var (
	DownWardValue int32 = 1000
	SumFilter     int32 = -150
)

var ResellerBlackListProduct = []string{
	"悦跑",
	"电商-独立",
	"蓝星严选连续包月",
	"通钱-2025年12月",
	"彦浩同行",
	"运营部测试专用",
	"彦浩直客商户",
}

type BbxtTools struct {
	cacheDir     string
	excelTempDir string
	ossClient    *utils_oss.Client
	config       *config.Config
	login        *lsxd.Login
}

func NewBbxtTools(config *config.Config, login *lsxd.Login) (*BbxtTools, error) {
	cache, err := pkg.GetCacheDir()
	if err != nil {
		return nil, err
	}
	tempDir, err := pkg.GetTmplDir()
	if err != nil {
		return nil, err
	}

	return &BbxtTools{
		cacheDir:     cache,
		excelTempDir: fmt.Sprintf("%s/excel_temp", tempDir),
		config:       config,
		login:        login,
	}, nil
}

func (b *BbxtTools) DailyReport(
	ctx context.Context,
	now time.Time,
	downWardValue int32,
	productName []string,
	sumFilter int32,
	ossClient *utils_oss.Client,
	initFunc LossSumInitFunc,
) (reports []*ReportRes, err error) {
	reports = make([]*ReportRes, 0, 4)
	productLossReport, err := b.StatisOursProductLossSum(ctx, now, initFunc)
	if err != nil {
		return
	}
	profitRankingSum, err := b.GetProfitRankingSum(now)
	if err != nil {
		return
	}
	statisOfficialProductSum, err := b.GetStatisOfficialProductSum(now, productName)
	if err != nil {
		return
	}
	statisOfficialProductSumDecline, err := b.GetStatisOfficialProductSumDecline(now, downWardValue, productName, sumFilter)
	if err != nil {
		return
	}
	reports = append(reports, profitRankingSum, statisOfficialProductSum, statisOfficialProductSumDecline, productLossReport)
	if ossClient != nil {
		uploader := NewUploader(ossClient, b.config)
		for _, report := range reports {
			_ = uploader.Run(report)
		}
	}

	return
}
func (b *BbxtTools) ResellerLossSort(ctx context.Context, now time.Time) ([]*ResellerLoss, error) {
	ct := []string{
		time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).Format("2006-01-02 15:04:05"),
		adjustedTime(now), //adjustedTime(time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location())),
	}

	data, err := StatisOursProductLossSumApi(&StatisOursProductLossSumReq{
		Ct: ct,
	})
	if err != nil {
		return nil, err
	}
	var (
		resellerMap = make(map[int32]*ResellerLoss)
	)

	for _, info := range data.List {
		// 检查经销商是否已存在
		if _, ok := resellerMap[info.ResellerId]; !ok {
			// 创建新的经销商记录
			resellerMap[info.ResellerId] = &ResellerLoss{
				ResellerId:   info.ResellerId,
				ResellerName: info.ResellerName,
				Total:        0,                            // 初始化为0，后续累加
				ProductLoss:  make(map[int32]*ProductLoss), // 初始化map
			}
		}

		// 获取当前经销商
		reseller := resellerMap[info.ResellerId]

		// 累加经销商总亏损
		num1 := decimal.NewFromFloat(reseller.Total)
		num2 := decimal.NewFromFloat(info.Loss)
		reseller.Total, _ = num1.Add(num2).Round(2).Float64()

		// 检查产品是否已存在
		if _, ok := reseller.ProductLoss[info.OursProductId]; !ok {
			// 创建新的产品亏损记录
			reseller.ProductLoss[info.OursProductId] = &ProductLoss{
				ProductId:   info.OursProductId,
				ProductName: info.OursProductName,
				Loss:        info.Loss, // 初始化为当前产品的亏损
			}
		} else {
			// 已存在产品记录，累加亏损
			productLoss := reseller.ProductLoss[info.OursProductId]
			productLoss.Loss += info.Loss
			reseller.ProductLoss[info.OursProductId] = productLoss
		}
	}

	// 按经销商总亏损排序
	resellers := make([]*ResellerLoss, 0, len(resellerMap))
	for _, v := range resellerMap {
		resellers = append(resellers, v)
	}
	sort.Slice(resellers, func(i, j int) bool {
		return resellers[i].Total < resellers[j].Total
	})
	return resellers, nil
}

func (b *BbxtTools) GetMapResellerLossSumProductRelation(ctx context.Context, now time.Time, initFunc LossSumInitFunc) (map[int32]*ResellerLossSumProductRelation, error) {
	resellers, err := b.ResellerLossSort(ctx, now)
	if err != nil {
		return nil, err
	}
	var totalDetail []*ResellerLoss
	for _, v := range resellers {
		if v.Total <= -100 && !slices.Contains(ResellerBlackListProduct, v.ResellerName) {

			totalDetail = append(totalDetail, v)
		}

	}
	if len(totalDetail) > 0 {
		err = initFunc(ctx, now, totalDetail, b)
		if err != nil {
			return nil, err
		}
	}
	value := b.ResellerLossToMapResellerLossSumProductRelation(totalDetail)
	return value, nil
}

func (b *BbxtTools) ResellerLossToMapResellerLossSumProductRelation(totalDetail []*ResellerLoss) map[int32]*ResellerLossSumProductRelation {
	relations := make(map[int32]*ResellerLossSumProductRelation)
	for _, detail := range totalDetail {
		if _, ok := relations[detail.ResellerId]; !ok {
			relations[detail.ResellerId] = &ResellerLossSumProductRelation{
				ResellerName:  detail.ResellerName,
				AfterSaleName: detail.Manager,
				Products:      make(map[int32]*LossReason),
			}
		}
		for _, product := range detail.ProductLoss {
			relations[detail.ResellerId].Products[product.ProductId] = &LossReason{
				ProductName: product.ProductName,
				LossReason:  product.LossReason,
			}
		}

	}
	return relations
}

// StatisOursProductLossSum 负利润分析
func (b *BbxtTools) StatisOursProductLossSum(ctx context.Context, now time.Time, initFunc LossSumInitFunc) (report *ReportRes, err error) {
	resellers, err := b.ResellerLossSort(ctx, now)
	var (
		total [][]string
		//gt          []*ResellerLoss
		totalDetail []*ResellerLoss
		totalSum    = decimal.NewFromFloat(0)
		//totalSum500 float64
	)
	// 构建分组
	for _, v := range resellers {
		if slices.Contains(ResellerBlackListProduct, v.ResellerName) {
			continue
		}
		if v.Total <= -100 {
			total = append(total, []string{
				fmt.Sprintf("%s", v.ResellerName),
				fmt.Sprintf("%.2f", v.Total),
			})

			totalDetail = append(totalDetail, v)
		}
		num := decimal.NewFromFloat(v.Total)
		totalSum = totalSum.Add(num).Round(2)
		//if v.Total <= -500 && !slices.Contains(ResellerBlackListProduct, v.ResellerName) {
		//	gt = append(gt, v)
		//	totalSum500 += v.Total
		//}
	}
	//report = make([]*ReportRes, 3)
	timeCh := now.Format("1月2日15点")
	//总量生成excel
	//if len(total) > 0 {
	//	filePath := b.cacheDir + "/kshj_total" + fmt.Sprintf("%d%d", time.Now().Unix(), rand.Intn(1000)) + ".xlsx"
	//	err = b.SimpleFillExcelWithTitle(b.excelTempDir+"/"+"kshj_total.xlsx", filePath, total, "")
	//	if err != nil {
	//		return
	//	}
	//	report[0] = &ReportRes{
	//		ReportName: "分销商负利润统计",
	//		Title:      "截至" + timeCh + "利润累计亏损" + fmt.Sprintf("%.2f", totalSum),
	//		Path:       filePath,
	//		Data:       total,
	//	}
	//}
	//
	//if len(gt) > 0 {
	//	filePath := b.cacheDir + "/kshj_gt" + fmt.Sprintf("%d%d", time.Now().Unix(), rand.Intn(1000)) + ".xlsx"
	//	title := "截至" + timeCh + "亏损500以上的分销商和产品"
	//	err = b.resellerDetailFillExcelV2(b.excelTempDir+"/"+"kshj_gt.xlsx", filePath, gt, title)
	//	if err != nil {
	//		return
	//	}
	//	report[1] = &ReportRes{
	//		ReportName: "负利润分析(亏损500以上)",
	//		Title:      "截至" + timeCh + "亏损500以上利润累计亏损" + fmt.Sprintf("%.2f", totalSum500),
	//		Path:       filePath,
	//		Data:       total,
	//	}
	//}

	if len(totalDetail) > 0 {
		err = initFunc(ctx, now, totalDetail, b)
		if err != nil {
			return
		}
		filePath := b.cacheDir + "/kshj_total_ana" + fmt.Sprintf("%d%d", time.Now().Unix(), rand.Intn(1000)) + ".xlsx"
		totalSumFloat64, _ := totalSum.Float64()
		title := "截至" + timeCh + "利润累计亏损" + fmt.Sprintf("%.2f", totalSumFloat64) + ",亏损100以上利润原因如下"
		err = b.resellerDetailFillExcelAna(b.excelTempDir+"/"+"kshj_total_ana.xlsx", filePath, totalDetail, title)
		if err != nil {
			return
		}
		report = &ReportRes{
			ReportName: "负利润分析(亏损100以上)",
			Title:      title,
			Path:       filePath,
			Data:       total,
		}
	}
	return report, nil
}

func (b *BbxtTools) GetResellerLossMannagerAndLossReasonFromApi(ctx context.Context, resellerLoss []*ResellerLoss) (map[int32]*ResellerLossSumProductRelation, error) {
	var (
		resellerMap     = make(map[int32]map[string][]int32)
		resellerLossMap = make(map[int32]*ResellerLoss, len(resellerLoss))
		relationMap     = make(map[int32]*ResellerLossSumProductRelation)
	)

	for _, v := range resellerLoss {
		var productSlice = make([]int32, 0, len(v.ProductLoss))
		for _, vv := range v.ProductLoss {
			productSlice = append(productSlice, vv.ProductId)
		}
		if _, ex := resellerMap[v.ResellerId]; !ex {
			resellerMap[v.ResellerId] = make(map[string][]int32, 1)
		}
		resellerMap[v.ResellerId]["values"] = productSlice
		resellerLossMap[v.ResellerId] = v
		relationMap[v.ResellerId] = &ResellerLossSumProductRelation{
			ResellerName: v.ResellerName,
			Products:     make(map[int32]*LossReason, len(v.ProductLoss)),
		}
		for _, product := range v.ProductLoss {
			relationMap[v.ResellerId].Products[product.ProductId] = &LossReason{
				ProductName: product.ProductName,
				LossReason:  "", // 初始化为未填写
			}
		}
	}
	res, err := GetManagerAndDefaultLossReasonApi(&GetManagerAndDefaultLossReasonRequest{
		Param: resellerMap,
	}, b.login.GetToken(ctx), b.config.Tools.ZltxResellerAuthProductToManagerAndDefaultLossReason.BaseURL)
	if err != nil {
		return nil, err
	}
	for _, v := range res {
		if v == nil {
			continue
		}
		if _, ok := resellerLossMap[v.ResellerInfo.ResellerId]; !ok {
			continue
		}
		relationMap[v.ResellerInfo.ResellerId].AfterSaleName = v.ResellerInfo.AfterSaleName

		for _, vv := range v.ProductList {
			if _, ex := relationMap[v.ResellerInfo.ResellerId].Products[vv.ProductId]; !ex {
				continue
			}
			if len(vv.LossReason) == 0 {
				continue
			}
			relationMap[v.ResellerInfo.ResellerId].Products[vv.ProductId].LossReason = vv.LossReason
		}
	}
	return relationMap, nil
}

// GetProfitRankingSum 利润同比分销商排行榜
func (b *BbxtTools) GetProfitRankingSum(now time.Time) (report *ReportRes, err error) {

	ct := []string{
		time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).Format("2006-01-02 15:04:05"),
		adjustedTime(now),
	}

	data, err := GetProfitRankingSumApi(&GetProfitRankingSumRequest{
		Ct: ct,
	})
	timeCh := now.Format("1月2日15点")
	title := "截至" + timeCh + "利润同比分销商排行榜"
	if err != nil {
		return
	}

	//排序
	sort.Slice(data.List, func(i, j int) bool {
		return data.List[i].HistoryOneDiff > data.List[j].HistoryOneDiff
	})
	//取前20和后20
	var (
		total  [][]string
		top    = data.List[:20]
		bottom = data.List[len(data.List)-20:]
	)
	//合并前20和后20
	top = append(top, bottom...)

	// 构建分组
	for _, v := range top {
		var diff string
		if v.HistoryOneDiff > 0 {
			diff = fmt.Sprintf("%s↑%.4f", RedStyle, v.HistoryOneDiff)
		} else {
			diff = fmt.Sprintf("%s↓%.4f", GreenStyle, v.HistoryOneDiff)
		}
		total = append(total, []string{
			fmt.Sprintf("%s", v.ResellerName),
			fmt.Sprintf("%.4f", v.CurrentProfit),
			fmt.Sprintf("%.4f", v.HistoryOneProfit),
			diff,
		})
	}
	//总量生成excel
	if len(total) == 0 {
		return
	}
	filePath := b.cacheDir + "/lrtb_rank" + fmt.Sprintf("%d", time.Now().Unix()) + ".xlsx"
	err = b.SimpleFillExcelWithTitle(b.excelTempDir+"/"+"lrtb_rank.xlsx", filePath, total, title)
	return &ReportRes{
		ReportName: "利润同比分销商排行榜",
		Title:      title,
		Path:       filePath,
		Data:       total,
	}, err
}

// GetStatisOfficialProductSum 销量同比分析
func (b *BbxtTools) GetStatisOfficialProductSum(now time.Time, productName []string) (report *ReportRes, err error) {
	ct := []string{
		time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).Format("2006-01-02 15:04:05"),
		adjustedTime(now),
	}
	var ids []int32
	if len(productName) > 0 {
		ids, err = b.getProductIdFromProductName(productName)
		if err != nil {
			return
		}
	}
	reqParam := &GetStatisOfficialProductSumRequest{
		Ct: ct,
	}
	if len(ids) > 0 {
		reqParam.OfficialProductId = ids
	}
	data, err := GetStatisOfficialProductSumApi(reqParam)
	if err != nil {
		return
	}

	// 创建临时map存储产品数据
	productDataMap := make(map[string][]string)
	var productNamesInResult []string

	for _, v := range data.OfficialProductSum {
		var (
			yeterDatyDiff string
			lastWeekDiff  string
		)
		if v.HistoryOneDiff > 0 {
			yeterDatyDiff = fmt.Sprintf("%s↑%d", RedStyle, v.HistoryOneDiff)
		} else {
			yeterDatyDiff = fmt.Sprintf("%s↓%d", GreenStyle, v.HistoryOneDiff)
		}
		if v.HistoryTwoDiff > 0 {
			lastWeekDiff = fmt.Sprintf("%s↑%d", RedStyle, v.HistoryTwoDiff)
		} else {
			lastWeekDiff = fmt.Sprintf("%s↓%d", GreenStyle, v.HistoryTwoDiff)
		}

		rowData := []string{
			fmt.Sprintf("%s", v.OfficialProductName),
			fmt.Sprintf("%d", v.CurrentNum),
			fmt.Sprintf("%d", v.HistoryOneNum),
			yeterDatyDiff,
			fmt.Sprintf("%d", v.HistoryTwoNum),
			lastWeekDiff,
		}

		// 存储到map中，key为产品名
		productDataMap[v.OfficialProductName] = rowData
		productNamesInResult = append(productNamesInResult, v.OfficialProductName)
	}

	// 按照productName的顺序构建total
	var total [][]string

	for _, name := range productName {
		if rowData, exists := productDataMap[name]; exists {
			total = append(total, rowData)
		}
	}

	timeCh := now.Format("1月2日15点")
	title := "截至" + timeCh + "销售同比分析"
	//总量生成excel
	if len(total) == 0 {
		return
	}
	filePath := b.cacheDir + "/xstb_ana" + fmt.Sprintf("%d", time.Now().Unix()) + ".xlsx"
	err = b.SimpleFillExcelWithTitle(b.excelTempDir+"/"+"xstb_ana.xlsx", filePath, total, title)
	return &ReportRes{
		ReportName: "销售同比分析",
		Title:      title,
		Path:       filePath,
		Data:       total,
	}, err
}

// GetStatisOfficialProductSumDecline 销量下滑明细
func (b *BbxtTools) GetStatisOfficialProductSumDecline(now time.Time, downWardValue int32, productName []string, sumFilter int32) (report *ReportRes, err error) {

	var productMap = make(map[string]int)
	for k, v := range productName {
		productMap[v] = k
	}
	ct := []string{
		time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).Format("2006-01-02 15:04:05"),
		adjustedTime(now),
	}
	var ids []int32
	if len(productName) > 0 {
		ids, err = b.getProductIdFromProductName(productName)
		if err != nil {
			return
		}
	}

	reqParam := &GetStatisOfficialProductSumRequest{
		Ct:                ct,
		DownwardValue:     downWardValue,
		OfficialProductId: ids,
		Page:              1,
		Limit:             1000,
	}

	data, err := GetStatisOfficialProductSumDeclineApi(reqParam)
	if err != nil {
		return
	}
	var (
		productSumMap = make(map[string]ProductSumDecline)
	)
	for _, v := range data.OfficialProductSumDecline {
		if _, ex := productSumMap[v.OfficialProductName]; !ex {
			productSumMap[v.OfficialProductName] = ProductSumDecline{
				OfficialProductName: v.OfficialProductName,
				OfficialProductId:   v.OfficialProductId,
				ProductSumReseller:  make(map[int32]ProductSumReseller),
				Index:               productMap[v.OfficialProductName],
			}

		}
		if v.HistoryOneDiff <= sumFilter || v.HistoryTwoDiff <= sumFilter {
			productSumMap[v.OfficialProductName].ProductSumReseller[v.ResellerId] = ProductSumReseller{
				ResellerName:   v.ResellerName,
				CurrentNum:     v.CurrentNum,
				HistoryOneNum:  v.HistoryOneNum,
				HistoryOneDiff: v.HistoryOneDiff,
				HistoryTwoNum:  v.HistoryTwoNum,
				HistoryTwoDiff: v.HistoryTwoDiff,
			}
		}
	}
	var total = make([]ProductSumDecline, 0, len(productSumMap))
	for k, _ := range productSumMap {
		total = append(total, productSumMap[k])
	}
	sort.Slice(total, func(i, j int) bool {
		return total[i].Index > total[j].Index
	})
	timeCh := now.Format("1月2日15点")
	//title := "截至" + timeCh + "销量下滑大于" + fmt.Sprintf("%d", downWardValue) + "明细，分销商仅展示差额大于" + fmt.Sprintf("%d", -sumFilter)
	title := "截至" + timeCh + "销量下滑较大商品"
	//总量生成excel
	if len(productSumMap) == 0 {
		return
	}
	filePath := b.cacheDir + "/xlxhmx" + fmt.Sprintf("%d%d", time.Now().Unix(), rand.Intn(1000)) + ".xlsx"
	err = b.OfficialProductSumDeclineExcel(b.excelTempDir+"/"+"/xlxhmx.xlsx", filePath, total, title)
	return &ReportRes{
		ReportName: "销售下滑明细",
		Title:      title,
		Path:       filePath,
		Desc:       pkginner.JsonStringIgonErr(productSumMap),
	}, err
}

func (b *BbxtTools) getProductIdFromProductName(productNames []string) ([]int32, error) {
	data, err := GetStatisFilterOfficialProductApi(&GetStatisFilterOfficialProductRequest{})
	if err != nil {
		return nil, err
	}
	var product2IdMap = make(map[string]int32)
	for _, v := range data.List {
		product2IdMap[v.OfficialProductName] = v.OfficialProductId
	}
	var ids []int32
	for _, v := range productNames {
		if id, ok := product2IdMap[v]; ok {
			ids = append(ids, id)
		}
	}
	return ids, nil
}

func adjustedTime(t time.Time) string {
	adjusted := time.Date(
		t.Year(), t.Month(), t.Day(),
		t.Hour(), t.Minute(), 59, 999_000_000,
		t.Location(),
	)
	return adjusted.Format("2006-01-02 15:04:05.999")
}
