package api

import (
	"box-cost/db/model"
	"box-cost/db/repo"
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis/v8"
	"github.com/xuri/excelize/v2"
	"go.mongodb.org/mongo-driver/bson/primitive"
)

// 统计报表 按时间范围，供应商  包装-计划（多选） 维度进行过滤，形成报表。可以下载
func Report(r *GinRouter) {
	// 加工列表
	r.GET("/report/produce/list", ReportProduceList)
	// 采购列表
	r.GET("/report/purchase/list", ReportPurchaseList)
	r.GET("/report/product/list", ReportProductList)
	r.GETJWT("/report/list", ReportList)
	r.GETJWT("/report/download", ReportListDownload)
}

// 加工单
func ReportListDownload(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	_, _, query := UtilQueryPageSize(c)
	// start, stop := CreatePageRange(page, size)
	supplierId := primitive.NilObjectID
	if _supplierId, ok := query["supplierId"]; ok {
		supplierId, _ = primitive.ObjectIDFromHex(_supplierId.(string))
	}

	timeRange := []interface{}{}
	if _timeRange, ok := query["timeRange"]; ok {
		timeRange, _ = _timeRange.([]interface{})
	}
	filtter := handleReportQuery(query)

	purchases := []*model.PurchaseBill{}
	produces := []*model.ProduceBill{}
	products := []*model.ProductBill{}

	repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
		CollectName: repo.CollectionBillPurchase,
		Query:       filtter,
		Project:     []string{"_id", "completeTime"},
	}, &purchases)
	repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
		CollectName: repo.CollectionBillProduce,
		Query:       filtter,
		Project:     []string{"_id", "completeTime"},
	}, &produces)
	repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
		CollectName: repo.CollectionBillProduct,
		Query:       filtter,
		Project:     []string{"_id", "completeTime"},
	}, &products)

	// 加入redis有序集合中
	redisCli := apictx.Svc.Redis

	reportBillKey := "report-bill-list:" + apictx.User.Parent

	isExist := redisCli.Exists(apictx.CreateRepoCtx().Ctx, reportBillKey).Val()
	// 不存在这个key时
	if isExist < 1 {
		if len(purchases) > 0 {
			for _, purchase := range purchases {
				member := "purchase_" + purchase.Id.Hex()
				score := purchase.CompleteTime.Unix()
				redisCli.ZAdd(apictx.CreateRepoCtx().Ctx, reportBillKey, &redis.Z{Score: float64(score), Member: member})
			}
		}
		if len(produces) > 0 {
			for _, produce := range produces {
				member := "produce_" + produce.Id.Hex()
				score := produce.CompleteTime.Unix()
				redisCli.ZAdd(apictx.CreateRepoCtx().Ctx, reportBillKey, &redis.Z{Score: float64(score), Member: member})
			}
		}
		if len(products) > 0 {
			for _, product := range products {
				member := "product_" + product.Id.Hex()
				score := product.CompleteTime.Unix()
				redisCli.ZAdd(apictx.CreateRepoCtx().Ctx, reportBillKey, &redis.Z{Score: float64(score), Member: member})
			}
		}
		// 设置过期时间
		redisCli.Expire(apictx.CreateRepoCtx().Ctx, reportBillKey, 1*time.Second)

	}

	total, err := redisCli.ZCard(apictx.CreateRepoCtx().Ctx, reportBillKey).Uint64()
	fmt.Println(total)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	reports, err := redisCli.ZRevRange(apictx.CreateRepoCtx().Ctx, reportBillKey, 0, -1).Result()
	if err != nil {
		return nil, err
	}

	if len(reports) < 1 {
		return nil, errors.New("没有单据信息")
	}
	lists := []map[string]interface{}{}
	for _, report := range reports {
		billArray := strings.Split(report, "_")
		billType := billArray[0]
		_billId := billArray[1]
		billId, _ := primitive.ObjectIDFromHex(_billId)
		billData := map[string]interface{}{}

		found := false
		if billType == "purchase" {
			found, billData = repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
				CollectName: repo.CollectionBillPurchase,
				Query:       repo.Map{"_id": billId},
			})

		}
		if billType == "produce" {
			found, billData = repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
				CollectName: repo.CollectionBillProduce,
				Query:       repo.Map{"_id": billId},
			})

		}
		if billType == "product" {
			found, billData = repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
				CollectName: repo.CollectionBillProduct,
				Query:       repo.Map{"_id": billId},
			})

		}
		if found {
			billData["billType"] = billType
			lists = append(lists, billData)
		}
	}
	f := excelize.NewFile()
	defer f.Close()
	index := f.NewSheet("Sheet1")
	f.SetActiveSheet(index)
	f.SetDefaultFont("宋体")
	report := NewReportExcel(f)
	supplier := model.Supplier{}
	supplierName := "【所有供应商】"
	if !supplierId.IsZero() {
		repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
			CollectName: repo.CollectionSupplier,
			Query:       repo.Map{"_id": supplierId},
			Project:     []string{"name"},
		}, &supplier)
		supplierName = supplier.Name

	}
	report.SupplierName = supplierName
	if len(timeRange) == 2 {
		report.TimeRange = append(report.TimeRange, timeRange[0].(string), timeRange[1].(string))
	}
	report.Content = lists
	report.Draws()

	c.Header("Content-Type", "application/octet-stream")
	c.Header("Content-Disposition", "attachment; filename="+"report.xlsx")
	c.Header("Content-Transfer-Encoding", "binary")
	err = f.Write(c.Writer)
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// 加工单
func ReportList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	page, size, query := UtilQueryPageSize(c)
	start, stop := CreatePageRange(page, size)
	filtter := handleReportQuery(query)

	purchases := []*model.PurchaseBill{}
	produces := []*model.ProduceBill{}
	products := []*model.ProductBill{}

	repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
		CollectName: repo.CollectionBillPurchase,
		Query:       filtter,
		Project:     []string{"_id", "completeTime"},
	}, &purchases)
	repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
		CollectName: repo.CollectionBillProduce,
		Query:       filtter,
		Project:     []string{"_id", "completeTime"},
	}, &produces)
	repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
		CollectName: repo.CollectionBillProduct,
		Query:       filtter,
		Project:     []string{"_id", "completeTime"},
	}, &products)

	// 加入redis有序集合中
	redisCli := apictx.Svc.Redis

	reportBillKey := "report-bill-list:" + apictx.User.Parent

	isExist := redisCli.Exists(apictx.CreateRepoCtx().Ctx, reportBillKey).Val()
	// 不存在这个key时
	if isExist < 1 {
		if len(purchases) > 0 {
			for _, purchase := range purchases {
				member := "purchase_" + purchase.Id.Hex()
				score := purchase.CompleteTime.Unix()
				redisCli.ZAdd(apictx.CreateRepoCtx().Ctx, reportBillKey, &redis.Z{Score: float64(score), Member: member})
			}
		}
		if len(produces) > 0 {
			for _, produce := range produces {
				member := "produce_" + produce.Id.Hex()
				score := produce.CompleteTime.Unix()
				redisCli.ZAdd(apictx.CreateRepoCtx().Ctx, reportBillKey, &redis.Z{Score: float64(score), Member: member})
			}
		}
		if len(products) > 0 {
			for _, product := range products {
				member := "product_" + product.Id.Hex()
				score := product.CompleteTime.Unix()
				redisCli.ZAdd(apictx.CreateRepoCtx().Ctx, reportBillKey, &redis.Z{Score: float64(score), Member: member})
			}
		}
		// 设置过期时间
		redisCli.Expire(apictx.CreateRepoCtx().Ctx, reportBillKey, 1*time.Second)

	}

	total, err := redisCli.ZCard(apictx.CreateRepoCtx().Ctx, reportBillKey).Uint64()
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	reports, err := redisCli.ZRevRange(apictx.CreateRepoCtx().Ctx, reportBillKey, start, stop).Result()
	if err != nil {
		return nil, err
	}

	if len(reports) < 1 {
		return repo.PageResult{
			List:  []map[string]interface{}{},
			Page:  page,
			Size:  size,
			Total: 0,
		}, nil
	}
	lists := []map[string]interface{}{}
	for _, report := range reports {
		billArray := strings.Split(report, "_")
		billType := billArray[0]
		_billId := billArray[1]
		billId, _ := primitive.ObjectIDFromHex(_billId)
		billData := map[string]interface{}{}

		found := false
		if billType == "purchase" {
			found, billData = repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
				CollectName: repo.CollectionBillPurchase,
				Query:       repo.Map{"_id": billId},
			})

		}
		if billType == "produce" {
			found, billData = repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
				CollectName: repo.CollectionBillProduce,
				Query:       repo.Map{"_id": billId},
			})

		}
		if billType == "product" {
			found, billData = repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
				CollectName: repo.CollectionBillProduct,
				Query:       repo.Map{"_id": billId},
			})

		}
		if found {
			billData["billType"] = billType
			lists = append(lists, billData)
		}
	}
	return repo.PageResult{
		List:  lists,
		Total: int64(total),
		Page:  page,
		Size:  size,
	}, nil
}

func CreatePageRange(page, size int64) (int64, int64) {
	if page < 1 {
		page = 1
	}
	if size < 1 {
		size = 10
	}

	start := (page - 1) * size
	stop := page*size - 1

	return start, stop
}

func ReportProduceList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	page, size, query := UtilQueryPageSize(c)
	// 条件处理
	// 获取采购单符合条件的信息
	return repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
		CollectName: repo.CollectionBillProduce,
		Query:       handleReportQuery(query),
		Page:        page,
		Size:        size,
	})

}

// 采购单
func ReportPurchaseList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	page, size, query := UtilQueryPageSize(c)
	return repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
		CollectName: repo.CollectionBillPurchase,
		Query:       handleReportQuery(query),
		Page:        page,
		Size:        size,
	})

}

func ReportProductList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	page, size, query := UtilQueryPageSize(c)
	return repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
		CollectName: repo.CollectionBillProduct,
		Query:       handleReportQuery(query),
		Page:        page,
		Size:        size,
	})

}
