package logic

import (
	"encoding/json"
	"errors"
	"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",
		ImgOption:   int8(req.ImgOption),
		BgImg1:      req.BgImg1,
		BgImg2:      req.BgImg2,
		ShelfStatus: 2, //默认初始状态为2-下架
		FontColor:   req.FontColor,
	}
	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, errors.New("查询增值服务失败")
	// 	}
	// 	if valueService != nil && len(valueService) > 0 {
	// 		for _, v := range valueService {
	// 			existValueService[v] = v
	// 		}
	// 	}
	// }
	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("增值服务不存在")
				} else {
					return res, errors.New("查询增值服务失败")
				}
			}
			if _, exists := selectValueAddServiceCount[int(detail.ServiceType)]; exists {
				return res, errors.New("每种增值服务类型只可选择一个")
			}
			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.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, errors.New("获取套餐信息失败")
					}
				}
			}
			if req.Language == msg.ZH_CN {
				bundleProfile.UUID = utils.GetUUID()
				if err = dao.TxCreateBundle(tx, bundleProfile); err != nil {
					return res, errors.New("创建套餐信息失败")
				}
				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("保存套餐与增值服务关联失败")
					}
				}
				if err = dao.TxCreateBundleLang(tx, bundleLang); err != nil {
					return res, errors.New("创建套餐信息失败")
				}
			}
			langList := []string{msg.ZH_TW, msg.EN, msg.DE_DE, msg.JA_JP}
			for _, lang := range langList {
				otherLang := &model.BundleProfileLang{
					UUID:      bundleLang.UUID,
					Name:      bundleLang.Name,
					Content:   bundleLang.Content,
					Price:     bundleLang.Price,
					PriceType: bundleLang.PriceType,
				}
				otherLang.Language = lang
				if err = dao.TxCreateBundleLang(tx, otherLang); err != nil {
					return res, errors.New("创建套餐信息失败")
				}
			}
			res.Msg = "创建套餐信息成功"
			return
		} else {
			return
		}
	} else { // 已存在,进行更新

		// 更新前保存历史记录
		if saveErr := saveBundleHistory(tx, req.Uuid, "", 0); saveErr != nil {
			return res, saveErr
		}
		if req.Language == msg.ZH_CN {
			updateBundle := map[string]interface{}{
				"name":       req.Name,
				"sort":       req.Sort,
				"content":    req.Content,
				"price":      req.Price,
				"price_type": req.PriceType,
				"img_option": req.ImgOption,
				"bg_img1":    req.BgImg1,
				"bg_img2":    req.BgImg2,
				"font_color": req.FontColor,
			}
			if err = dao.TxUpdateBundle(tx, req.Uuid, updateBundle); err != nil {
				return res, errors.New("更新套餐信息失败")
			}
			//更新中间表函数
			if err = diffUpdateBundleToValueAddService(tx, req.Uuid, selectService); err != nil {
				tx.Rollback()
				return res, errors.New("更新套餐与增值服务关联失败")
			}
		}
		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, errors.New("更新套餐信息失败")
		}
		res.Uuid = req.Uuid
		res.Msg = "保存成功"
	}
	return res, nil
}

func BundleListV2(req *bundle.BundleListRequest) (res *bundle.BundleListResponse, err error) {
	res = new(bundle.BundleListResponse)
	res, err = dao.BundleListV2(req)
	if err != nil {
		return res, errors.New("获取套餐列表失败")
	}
	return res, nil
}
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")
	}
	detail, err := dao.BundleDetailV2(req)
	if err != nil {
		return res, errors.New("获取套餐信息失败")
	}
	if detail != nil {
		bundleProfile.Uuid = detail.UUID
		bundleProfile.Name = detail.Name
		bundleProfile.Content = detail.Content
		bundleProfile.Price = detail.Price
		bundleProfile.PriceType = detail.PriceType
		bundleProfile.ImgOption = int32(detail.ImgOption)
		bundleProfile.BgImg1 = detail.BgImg1
		bundleProfile.BgImg2 = detail.BgImg2
		bundleProfile.FontColor = detail.FontColor
		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 {
				valueAddDetail, err := dao.ValueAddServiceDetailByUuidAndLanguage(valueAddService.ValueUid, req.Language)
				if err != nil {
					return res, errors.New("查询增值服务失败")
				}
				selectValueAddService := &bundle.SelectValueAddService{
					ValueAddUuid: valueAddService.ValueUid,
					IsDisplay:    valueAddService.IsDisplay,
					ServiceName:  valueAddDetail.ServiceName,
				}
				selectValueAddServices = append(selectValueAddServices, selectValueAddService)
			}
		}
		if detail.BundleProfileLang != nil && len(detail.BundleProfileLang) > 0 {
			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"),
				}
				bundleProfileLangs = append(bundleProfileLangs, bundleProfileLang)
			}
		}
	}

	if selectValueAddServices != nil && len(selectValueAddServices) > 0 {
		bundleProfile.SelectValueAddService = selectValueAddServices
	}
	bundleProfile.BundleProfileLang = bundleProfileLangs
	res.Bundle = bundleProfile
	return
}
func BundleLangDetailV2(req *bundle.BundleDetailRequest) (res *bundle.BundleProfileLang, err error) {
	res = new(bundle.BundleProfileLang)
	if req.Uuid == "" {
		return res, errors.New("缺少套餐UUID")
	}
	if req.Language == "" {
		return res, errors.New("language不能为空")
	}
	detail, err := dao.BundleDetailV2(req)
	if err != nil {
		return res, errors.New("获取套餐信息失败")
	}
	lang, err := dao.BundleDetailByUuidAndLanguage(req.Uuid, req.Language)
	if err != nil {
		return res, errors.New("获取套餐信息失败")
	}
	if detail != nil {
		res.Uuid = detail.UUID
		res.ImgOption = int32(detail.ImgOption)
		res.BgImg1 = detail.BgImg1
		res.BgImg2 = detail.BgImg2
		res.FontColor = detail.FontColor
		res.Sort = detail.Sort
		res.ShelfStatus = detail.ShelfStatus
		res.Contract = detail.Contract
	}
	if lang != nil {
		res.Name = lang.Name
		res.Price = lang.Price
		res.PriceType = lang.PriceType
		res.Content = lang.Content
		res.Language = lang.Language
		res.CreatedAt = time.Unix(lang.CreatedAt, 0).Format("2006-01-02 15:04:05")
		res.UpdatedAt = time.Unix(int64(lang.UpdatedAt), 0).Format("2006-01-02 15:04:05")
	}
	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("状态值无效")
	}
	detail, err := dao.GetBundleDetailByUuid(req.Uuid)
	if err != nil {
		return res, errors.New("获取套餐信息失败")
	}
	if detail.ShelfStatus == req.ShelfStatus {
		if detail.ShelfStatus == 1 {
			return res, errors.New("套餐已上架,请勿重复操作")
		}
		if detail.ShelfStatus == 2 {
			return res, errors.New("套餐已下架,请勿重复操作")
		}
	}
	bundleDetailLangs, err := dao.GetBundleLangsByUuid(req.Uuid)
	if err != nil {
		return res, errors.New("获取套餐信息失败")
	}
	var langToPriceType = make(map[string]int64)
	for _, bundleLang := range bundleDetailLangs {
		langToPriceType[bundleLang.Language] = bundleLang.PriceType
	}
	tx := app.ModuleClients.BundleDB.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	if req.ShelfStatus == 1 {
		valueAddUuids, err := dao.GetValueAddServiceUuidsByBundleUuid(req.Uuid)
		if err != nil {
			return res, errors.New("查询增值服务失败")
		}
		//判断时长类型是否存在
		isExist := false
		for _, valueUid := range valueAddUuids {
			detail, err := dao.ValueAddServiceDetail(valueUid)
			if err != nil {
				return res, errors.New("查询增值服务失败")
			}
			if detail.ServiceType == 5 {
				isExist = true
				break
			}
		}
		if !isExist {
			return res, errors.New("缺失可用时长服务类型")
		}
		//校验币种
		valueAddServices, err := dao.BatchValueAddServiceDetailTx(tx, valueAddUuids)
		if err != nil {
			return res, errors.New("查询增值服务详情失败")
		}
		for _, valueAddService := range valueAddServices {
			if valueAddService.ValueAddServiceLang != nil && len(valueAddService.ValueAddServiceLang) > 0 {
				for _, lang := range valueAddService.ValueAddServiceLang {
					if langToPriceType[lang.Language] != lang.PriceType {
						return res, errors.New("所选增值服务币种与套餐币种不一致")
					}
				}
			}
		}
	}

	res, err = dao.HandShelf(req.Uuid, req.ShelfStatus)
	if err != nil {
		return res, errors.New("更新套餐状态失败")
	}
	res.Msg = "更新成功"
	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("查询套餐与增值服务关联失败")
	}
	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)
	toDel := make([]string, 0)
	toUpdate := make([]*model.BundleToValueAddService, 0)
	for uid, s := range newUuids {
		if _, exist := oldSet[uid]; !exist {
			s.BundleUuid = bundleUuid
			toAdd = append(toAdd, s)
		} else {
			s.BundleUuid = bundleUuid
			toUpdate = append(toUpdate, s)
		}
	}
	// 需要删除的
	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("删除套餐与增值服务关联失败")
		}
	}
	if len(toAdd) > 0 {
		if err = dao.CreateBundleToValueAddService(tx, toAdd); err != nil {
			return errors.New("保存套餐与增值服务关联失败")
		}
	}
	if len(toUpdate) > 0 {
		updates := make(map[string]interface{})
		var uids []string
		for _, record := range toUpdate {
			uids = append(uids, record.ValueUid)
			updates["is_display"] = record.IsDisplay
		}
		if err = dao.UpdateBundleToValueAddService(tx, toUpdate); err != nil {
			return errors.New("保存套餐与增值服务关联失败")
		}
	}
	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("获取套餐信息失败")
	}
	bundleToValueAddService := data.BundleToValueAddService
	data.BundleToValueAddService = nil
	var valueUuid []string
	if bundleToValueAddService != nil && len(bundleToValueAddService) > 0 {
		for _, v := range bundleToValueAddService {
			valueUuid = append(valueUuid, v.ValueUid)
		}
	}
	valueData, err := dao.BatchValueAddServiceDetailTx(tx, valueUuid)
	if err != nil {
		return errors.New("查询增值服务详情失败")
	}
	j, err := json.Marshal(data)
	if err != nil {
		return errors.New("序列化转换失败")
	}
	vJ, err := json.Marshal(valueData)
	if err != nil {
		return errors.New("序列化转换失败")
	}
	history := &model.BundleProfileHistory{
		Uuid:            bundleUuid,
		BundleProfile:   datatypes.JSON(j),
		ValueAddService: datatypes.JSON(vJ),
		Operator:        operator,
		OperatorId:      operatorId,
	}
	if err := tx.Create(history).Error; err != nil {
		return errors.New("保存套餐历史记录失败")
	}
	return nil
}

// 增加h5套餐列表
func BundleListH5V2(req *bundle.BundleListRequest) (res *bundle.BundleListResponse, err error) {
	res = new(bundle.BundleListResponse)
	res, err = dao.BundleListH5V2(req)
	if err != nil {
		return res, errors.New("获取套餐列表失败")
	}
	return res, nil
}