package logic

import (
	"encoding/json"
	"errors"
	"fmt"
	"micro-bundle/internal/dao"
	"micro-bundle/pkg/app"
	"micro-bundle/pkg/msg"
	"time"

	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils"
	"github.com/jinzhu/copier"
	"gorm.io/datatypes"
	"gorm.io/gorm"

	"micro-bundle/internal/model"
	"micro-bundle/pb/bundle"
)

func CreateBundle(req *bundle.BundleProfile) (res *bundle.CommonResponse, err error) {
	res = new(bundle.CommonResponse)
	bundleProfile := new(model.BundleProfile)
	_ = copier.CopyWithOption(&bundleProfile, req, copier.Option{DeepCopy: true})
	bundleProfile.UUID = utils.GetUUID()
	res, err = dao.CreateBundle(bundleProfile)
	return
}

func UpdateBundle(req *bundle.BundleProfile) (res *bundle.CommonResponse, err error) {
	res = new(bundle.CommonResponse)
	bundleProfile := new(model.BundleProfile)
	_ = copier.CopyWithOption(&bundleProfile, req, copier.Option{DeepCopy: true})
	res, err = dao.UpdateBundle(bundleProfile)
	return
}

func DeleteBundle(req *bundle.DelBundleRequest) (res *bundle.CommonResponse, err error) {
	res = new(bundle.CommonResponse)
	res, err = dao.DeleteBundle(req.Uuid)
	return
}

func BundleList(req *bundle.BundleListRequest) (res *bundle.BundleListResponse, err error) {
	res = new(bundle.BundleListResponse)
	res, err = dao.BundleList(req)
	return
}

func BundleDetail(req *bundle.BundleDetailRequest) (res *bundle.BundleDetailResponse, err error) {
	res = new(bundle.BundleDetailResponse)
	res.Bundle = new(bundle.BundleProfile)
	res.Bundle, err = dao.BundleDetail(req.Uuid)
	if err != nil {
		res.Msg = err.Error()
	}
	return
}

func SaveBundle(req *bundle.BundleProfile) (res *bundle.SaveResponse, err error) {
	res = &bundle.SaveResponse{}
	if req.Language == "" {
		return res, errors.New("语言参数不能为空")
	}
	if req.Sort <= 0 {
		return res, errors.New("排序参数需为正整数")
	}
	bundleProfile := &model.BundleProfile{
		Name:        req.Name,
		Sort:        req.Sort,
		Content:     req.Content,
		Price:       req.Price,
		PriceType:   req.PriceType,
		Contract:    "https://e-cdn.fontree.cn/fonchain-main/prod/file/saas/contract/template-25032801.pdf",
		BgImg1:      req.BgImg1,
		BgImg2:      req.BgImg2,
		ShelfStatus: 2, //默认初始状态为2-下架
	}
	bundleLang := &model.BundleProfileLang{
		Name:      req.Name,
		Content:   req.Content,
		Price:     req.Price,
		PriceType: req.PriceType,
		Language:  req.Language,
	}
	if req.Uuid == "" && req.Language != msg.ZH_CN {
		return res, errors.New("请先创建中文版本套餐")
	}
	var existValueService = make(map[string]string)
	if req.Uuid != "" {
		valueService, existErr := dao.GetValueAddServiceUuidsByBundleUuid(req.Uuid)
		if existErr != nil {
			return res, existErr
		}
		if valueService != nil && len(valueService) > 0 {
			for _, v := range valueService {
				existValueService[v] = v
			}
		}
	}
	var cancelValueAddService = make(map[string]string)
	selectService := make([]*model.BundleToValueAddService, 0)
	var selectValueAddServiceCount = make(map[int]struct{})
	if req.Language == msg.ZH_CN && req.SelectValueAddService != nil && len(req.SelectValueAddService) > 0 {
		for _, v := range req.SelectValueAddService {
			detail, checkErr := dao.ValueAddServiceDetailByUuidAndLanguage(v.ValueAddUuid, req.Language)
			if checkErr != nil {
				if checkErr == gorm.ErrRecordNotFound {
					return res, errors.New(fmt.Sprintf("所选增值服务[%s]%s版不存在,请先创建对应增值套餐", v.ServiceName, req.Language))
				} else {
					return res, checkErr
				}
			}
			if detail.PriceType != req.PriceType {
				if req.Uuid == "" {
					//中文套餐创建时,币种不一致直接返回错误
					return res, errors.New(fmt.Sprintf("所选增值服务[%s]%s币种与套餐币种不一致", detail.ServiceName, req.Language))
				} else {
					//更新时,判断是否已存在,存在则取消关联
					_, ok := existValueService[v.ValueAddUuid]
					if ok {
						cancelValueAddService[v.ValueAddUuid] = detail.ServiceName
						continue
					} else {
						//币种不一致,新加币种时返回错误
						return res, errors.New(fmt.Sprintf("所选增值服务[%s]%s币种与套餐币种不一致", detail.ServiceName, req.Language))

					}
				}
			}
			if _, exists := selectValueAddServiceCount[int(detail.ServiceType)]; exists {
				return res, errors.New(fmt.Sprintf("所选增值服务[%s]类型存在多个", detail.ServiceName))
			}
			selectValueAddServiceCount[int(detail.ServiceType)] = struct{}{}
			selectService = append(selectService, &model.BundleToValueAddService{
				ValueUid:  v.ValueAddUuid,
				IsDisplay: v.IsDisplay,
			})
		}
	}
	tx := app.ModuleClients.BundleDB.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	_, err = dao.BundleDetailByUuidAndLanguage(req.Uuid, req.Language)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			// if req.Uuid != "" {
			// 	return res, errors.New("套餐不存在")
			// }
			if req.Language != msg.ZH_CN {
				_, err = dao.BundleDetailByUuidAndLanguage(req.Uuid, msg.ZH_CN)
				if err != nil {
					if err == gorm.ErrRecordNotFound {
						res.Msg = "请先创建中文版本套餐"
						return res, errors.New("请先创建中文版本套餐")
					} else {
						return res, err
					}
				}
			}
			if req.Language == msg.ZH_CN {
				bundleProfile.UUID = utils.GetUUID()
				if err = dao.TxCreateBundle(tx, bundleProfile); err != nil {
					return res, errors.New("保存中文语言套餐失败: " + err.Error())
				}
				bundleLang.UUID = bundleProfile.UUID
				res.Uuid = bundleProfile.UUID
				// 新建套餐时插入中间表
				for _, s := range selectService {
					s.BundleUuid = bundleProfile.UUID
				}
				if len(selectService) > 0 {
					if err = dao.CreateBundleToValueAddService(tx, selectService); err != nil {
						return res, errors.New("保存套餐与增值服务关联失败: " + err.Error())
					}
				}
			} else {
				bundleLang.UUID = req.Uuid
				res.Uuid = req.Uuid
				valueUuid, err1 := dao.GetValueAddServiceUuidsByBundleUuid(bundleLang.UUID)
				if err1 != nil {
					return res, err1
				}
				count := 0
				if valueUuid != nil && len(valueUuid) > 0 {
					for _, v := range valueUuid {
						//可以改成批量获取
						valueDetail, err2 := dao.ValueAddServiceDetailByUuidAndLanguage(v, req.Language)
						if err2 != nil {
							return res, err2
						}
						if valueDetail.PriceType != req.PriceType {
							if err = tx.Where("bundle_uuid =? AND value_uid =?", bundleLang.UUID, v).Delete(&model.BundleToValueAddService{}).Error; err != nil {
								return res, errors.New("删除套餐与增值服务关联失败: " + err.Error())
							}
							count++
						}
					}
				}
				res.CancelNum = int64(count)
			}
			if err = dao.TxCreateBundleLang(tx, bundleLang); err != nil {
				return res, errors.New("保存语言套餐失败: " + err.Error())
			}
			res.Msg = "保存成功"
			return res, nil
		} else {
			return
		}
	} else { // 已存在,进行更新

		// 更新前保存历史记录
		if saveErr := saveBundleHistory(tx, req.Uuid, "", 0); err != nil {
			return res, saveErr
		}

		if req.Language == msg.ZH_CN {
			if len(cancelValueAddService) > 0 {
				cancel := "以下增值服务:"
				for _, v := range cancelValueAddService {
					cancel += fmt.Sprintf("[%s]%s", v, req.Language)
					if err = tx.Where("bundle_uuid = ? AND value_uid = ?", req.Uuid, v).Delete(&model.BundleToValueAddService{}).Error; err != nil {
						return res, errors.New("删除套餐与增值服务关联失败: " + err.Error())
					}
				}
				cancel += "版币种与套餐币种不一致"
				res.Msg = "保存cn成功 " + cancel
			}
			res.CancelNum = int64(len(cancelValueAddService))
			updateBundle := map[string]interface{}{
				"name":       req.Name,
				"sort":       req.Sort,
				"content":    req.Content,
				"price":      req.Price,
				"price_type": req.PriceType,
				"bg_img1":    req.BgImg1,
				"bg_img2":    req.BgImg2,
			}
			if err = dao.TxUpdateBundle(tx, req.Uuid, updateBundle); err != nil {
				return res, err
			}
			// 更新中间表函数
			if err = diffUpdateBundleToValueAddService(tx, req.Uuid, selectService); err != nil {
				tx.Rollback()
				return res, err
			}
		} else {
			//更新其他语言时 先获取所有关联增值服务,判断币种是否一致,不一致则取消关联
			valueAddService, err := dao.GetBundleToValueAddServiceByBundleUuid(req.Uuid)
			if err != nil {
				return res, err
			}
			cancelValueService := make(map[string]string)
			for _, v := range valueAddService {
				detail, checkErr := dao.ValueAddServiceDetailByUuidAndLanguage(v.ValueUid, req.Language)
				if checkErr != nil {
					if checkErr == gorm.ErrRecordNotFound {
						continue
					} else {
						return res, checkErr
					}
				}
				if detail.PriceType != req.PriceType {
					cancelValueService[v.ValueUid] = detail.ServiceName
					continue
				}
			}
			if int64(len(cancelValueService)) > 0 {
				cancel := "以下增值服务:"
				for k, v := range cancelValueService {
					cancel += fmt.Sprintf("[%s]%s", v, req.Language)
					if err = tx.Where("bundle_uuid = ? AND value_uid = ?", req.Uuid, k).Delete(&model.BundleToValueAddService{}).Error; err != nil {
						return res, errors.New("删除套餐与增值服务关联失败: " + err.Error())
					}
				}
				cancel += "版币种与套餐币种不一致,已取消相关关联"
				res.Msg = "保存成功 " + cancel
				res.CancelNum = int64(len(cancelValueService))
			}
		}
		updateBundleLang := map[string]interface{}{
			"name":       req.Name,
			"content":    req.Content,
			"price":      req.Price,
			"price_type": req.PriceType,
		}
		if err = dao.TxUpdateBundleLang(tx, req.Uuid, req.Language, updateBundleLang); err != nil {
			return res, err
		}

		res.Uuid = req.Uuid
		if res.Msg == "" {
			res.Msg = "保存成功"
		}
	}
	return res, nil
}

func BundleListV2(req *bundle.BundleListRequest) (res *bundle.BundleListResponse, err error) {
	res = new(bundle.BundleListResponse)
	res, err = dao.BundleListV2(req)
	return
}
func BundleDetailV2(req *bundle.BundleDetailRequest) (res *bundle.BundleDetailResponseV2, err error) {
	res = new(bundle.BundleDetailResponseV2)
	bundleProfile := &bundle.BundleProfile{}
	bundleProfileLangs := make([]*bundle.BundleProfileLang, 0)
	selectValueAddServices := make([]*bundle.SelectValueAddService, 0) //已选增值服务
	if req.Uuid == "" {
		return res, errors.New("uuid不能为空")
	}
	// if req.Language == "" {
	// 	return res, errors.New("language不能为空")
	// }
	detail, err := dao.BundleDetailV2(req)
	if err != nil {
		res.Msg = err.Error()
	}
	if detail != nil && detail.BundleProfileLang != nil && len(detail.BundleProfileLang) > 0 {
		bundleProfile.Uuid = detail.UUID
		bundleProfile.Name = detail.Name
		bundleProfile.Content = detail.Content
		bundleProfile.Price = detail.Price
		bundleProfile.PriceType = detail.PriceType
		bundleProfile.BgImg1 = detail.BgImg1
		bundleProfile.BgImg2 = detail.BgImg2
		bundleProfile.Sort = detail.Sort
		bundleProfile.ShelfStatus = detail.ShelfStatus
		bundleProfile.CreatedAt = detail.CreatedAt.Format("2006-01-02 15:04:05")
		bundleProfile.UpdatedAt = detail.UpdatedAt.Format("2006-01-02 15:04:05")
		bundleProfile.Contract = detail.Contract
		if detail.BundleToValueAddService != nil && len(detail.BundleToValueAddService) > 0 {
			for _, valueAddService := range detail.BundleToValueAddService {
				selectValueAddService := &bundle.SelectValueAddService{
					ValueAddUuid: valueAddService.ValueUid,
					IsDisplay:    valueAddService.IsDisplay,
				}
				selectValueAddServices = append(selectValueAddServices, selectValueAddService)
			}
		}
		for _, lang := range detail.BundleProfileLang {
			bundleProfileLang := &bundle.BundleProfileLang{
				Uuid:      lang.UUID,
				Name:      lang.Name,
				Price:     lang.Price,
				PriceType: lang.PriceType,
				Content:   lang.Content,
				Language:  lang.Language,
				CreatedAt: time.Unix(lang.CreatedAt, 0).Format("2006-01-02 15:04:05"),
				UpdatedAt: time.Unix(int64(lang.UpdatedAt), 0).Format("2006-01-02 15:04:05"),
			}
			// 通过中间表拼接增值服务数据
			// if detail.BundleToValueAddService != nil && len(detail.BundleToValueAddService) > 0 {
			// 	for _, valueAddService := range detail.BundleToValueAddService {
			// 		valueAddDeatilData, err := dao.ValueAddServiceDetailByUuidAndLanguage(valueAddService.ValueUid, bundleProfileLang.Language)
			// 		if err != nil {
			// 			return res, err
			// 		}
			//if valueAddService.IsDisplay{}
			// ValueAddServiceLang := &bundle.ValueAddServiceLang{
			// 	Uuid:          valueAddDeatilData.UUID,
			// 	ServiceName:   valueAddDeatilData.ServiceName,
			// 	ServiceType:   int32(valueAddDeatilData.ServiceType),
			// 	PriceMode:     int32(valueAddDeatilData.PriceMode),
			// 	PriceType:     int64(valueAddDeatilData.PriceType),
			// 	OriginalPrice: fmt.Sprintf("%.2f", float32(valueAddDeatilData.OriginalPrice)),
			// 	Unit:          string(valueAddDeatilData.Unit),
			// 	Language:      valueAddDeatilData.Language,
			// 	CreatedAt:     time.Unix(valueAddDeatilData.CreatedAt, 0).Format("2006-01-02 15:04:05"),
			// 	UpdatedAt:     time.Unix(valueAddDeatilData.UpdatedAt, 0).Format("2006-01-02 15:04:05"),
			// }
			//bundleProfileLang.ValueAddServiceLang = append(bundleProfileLang.ValueAddServiceLang, ValueAddServiceLang)
			// 		selectValueAddService = append(selectValueAddService, &bundle.SelectValueAddService{
			// 			ValueAddUuid: valueAddService.ValueUid,
			// 			ServiceName:  valueAddDeatilData.ServiceName,
			// 			IsDisplay:    valueAddService.IsDisplay,
			// 		})
			// 	}
			// }
			bundleProfileLangs = append(bundleProfileLangs, bundleProfileLang)
		}
	}

	if selectValueAddServices != nil && len(selectValueAddServices) > 0 {
		bundleProfile.SelectValueAddService = selectValueAddServices
	}
	bundleProfile.BundleProfileLang = bundleProfileLangs
	res.Bundle = bundleProfile
	return
}
func HandleShelf(req *bundle.HandShelfRequest) (res *bundle.CommonResponse, err error) {
	res = new(bundle.CommonResponse)
	if req.Uuid == "" {
		return res, errors.New("uuid不能为空")
	}
	if req.ShelfStatus != 1 && req.ShelfStatus != 2 {
		return res, errors.New("Invalid shelf status")
	}

	res, err = dao.HandShelf(req.Uuid, req.ShelfStatus)
	if err != nil {
		res.Msg = err.Error()
		return res, err
	}

	res.Msg = "Operation success"
	return res, nil
}

// 差异更新套餐与增值服务中间表
func diffUpdateBundleToValueAddService(tx *gorm.DB, bundleUuid string, selectService []*model.BundleToValueAddService) error {
	oldUuids, err := dao.GetValueAddServiceUuidsByBundleUuid(bundleUuid)
	if err != nil {
		return errors.New("查询旧套餐与增值服务关联失败: " + err.Error())
	}
	newUuids := make(map[string]*model.BundleToValueAddService)
	for _, s := range selectService {
		newUuids[s.ValueUid] = s
	}
	oldSet := make(map[string]struct{})
	for _, uid := range oldUuids {
		oldSet[uid] = struct{}{}
	}
	// 需要新增的
	toAdd := make([]*model.BundleToValueAddService, 0)
	for uid, s := range newUuids {
		if _, exist := oldSet[uid]; !exist {
			s.BundleUuid = bundleUuid
			toAdd = append(toAdd, s)
		}
	}
	// 需要删除的
	toDel := make([]string, 0)
	for _, uid := range oldUuids {
		if _, exist := newUuids[uid]; !exist {
			toDel = append(toDel, uid)
		}
	}
	if len(toDel) > 0 {
		if err = tx.Where("bundle_uuid = ? AND value_uid IN ?", bundleUuid, toDel).Delete(&model.BundleToValueAddService{}).Error; err != nil {
			return errors.New("删除套餐与增值服务关联失败: " + err.Error())
		}
	}
	if len(toAdd) > 0 {
		if err = dao.CreateBundleToValueAddService(tx, toAdd); err != nil {
			return errors.New("保存套餐与增值服务关联失败: " + err.Error())
		}
	}
	return nil
}
func saveBundleHistory(tx *gorm.DB, bundleUuid string, operator string, operatorId uint64) error {
	// 保存历史记录
	data, err := dao.GetBundleDetailByUuid(bundleUuid)
	if err != nil {
		return errors.New("查询套餐详情失败: " + err.Error())
	}
	j, err := json.MarshalIndent(data, "", " ")
	if err != nil {
		return errors.New("json转换失败: " + err.Error())
	}
	history := &model.BundleProfileHistory{
		Uuid:          bundleUuid,
		BundleProfile: datatypes.JSON(j),
		Operator:      operator,
		OperatorId:    operatorId,
	}
	if err := tx.Create(history).Error; err != nil {
		return errors.New("保存套餐历史记录失败: " + err.Error())
	}
	return nil
}