package logic

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

	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils"
	"github.com/shopspring/decimal"
	"gorm.io/datatypes"
	"gorm.io/gorm"
)

// 增值套餐创建
func CreateValueAddBundle(req *bundle.CreateValueAddBundleRequest) (res *bundle.CreateValueAddBundleResponse, err error) {
	res = &bundle.CreateValueAddBundleResponse{}

	savedAmount := float32(req.Num * (msg.OriginalPrice - msg.DiscountPrice))
	totalPrice := float32(req.Num * msg.DiscountPrice)

	valueAddBundleProfile := &model.ValueAddBundleProfile{
		UUID:          utils.GetUUID(),
		Num:           req.Num,
		OriginalPrice: msg.OriginalPrice,
		DiscountPrice: msg.DiscountPrice,
		SavedAmount:   savedAmount,
		TotalPrice:    totalPrice,
		//Type:          msg.Custom,
	}

	err = dao.CreateValueAddBundle(valueAddBundleProfile)
	if err != nil {
		res.Msg = msg.ErrorCreateValueAddBundleInfo
		return res, err
	}

	res.Uuid = valueAddBundleProfile.UUID
	res.TotalPrice = totalPrice
	res.SavedAmount = savedAmount
	res.Msg = msg.SuccessCreateValueAddBundleInfo

	return
}

// 增值套餐列表
func ValueAddBundleList(req *bundle.ValueAddBundleListRequest) (res *bundle.ValueAddBundleListResponse, err error) {
	res = &bundle.ValueAddBundleListResponse{}
	var bundleCommonUid string
	var bundleProfile *model.BundleProfile
	bundleProfile, err = dao.BundleProfileDetail(req.BundleUuid)
	if err != nil {
		return
	} else {
		var bundleOrderRecord *model.BundleOrderRecords
		bundleOrderRecord, err = dao.GetBundleOrderRecordsByCommonUidAndUserId(bundleProfile.BundleCommonUid, req.UserId)
		if err != nil {
			err = nil
		} else {
			bundleCommonUid = bundleOrderRecord.BundleCommonUid
			res.OrderNo = true
			res.Price = bundleOrderRecord.ValueAddBundleAmount
			res.Num = bundleOrderRecord.Num

			if bundleOrderRecord.ValueAddBundleUUID != "" {
				res.Status = true
			}
		}
	}

	valueAddBundleProfile, err := dao.ValueAddBundleList(req.PriceType)
	if err != nil {
		res.Msg = msg.ErrorGetValueAddBundleList
		return res, err
	}

	for _, valueAddBundle := range valueAddBundleProfile {
		valueAddBundleProfileInfo := &bundle.ValueAddBundleProfile{
			Uuid:                valueAddBundle.UUID,
			Num:                 valueAddBundle.Num,
			OriginalPrice:       valueAddBundle.OriginalPrice,
			DiscountPrice:       valueAddBundle.DiscountPrice,
			TotalPrice:          valueAddBundle.TotalPrice,
			SavedAmount:         valueAddBundle.SavedAmount,
			DiscountPriceStatus: valueAddBundle.DiscountPriceStatus,
			Choose:              valueAddBundle.Choose,
		}

		if bundleCommonUid == valueAddBundle.AddBundleCommonUid {
			valueAddBundleProfileInfo.Status = true
		}

		res.Data = append(res.Data, valueAddBundleProfileInfo)
	}

	res.OriginalPrice = msg.OriginalPrice
	res.Total = int32(len(valueAddBundleProfile))
	res.Msg = "SUCCESS"

	return
}

// 增值套餐详情
func ValueAddBundleDetail(req *bundle.ValueAddBundleDetailRequest) (res *bundle.ValueAddBundleDetailResponse, err error) {
	res = &bundle.ValueAddBundleDetailResponse{}

	valueAddBundleProfile := &model.ValueAddBundleProfile{}
	valueAddBundleProfile, err = dao.ValueAddBundleDetail(req.Uuid)
	if err != nil {
		res.Msg = msg.ErrorGetValueAddBundleInfo
		return res, err
	}

	res.Data = &bundle.ValueAddBundleProfile{
		Uuid:                valueAddBundleProfile.UUID,
		Num:                 valueAddBundleProfile.Num,
		OriginalPrice:       valueAddBundleProfile.OriginalPrice,
		DiscountPrice:       valueAddBundleProfile.DiscountPrice,
		TotalPrice:          valueAddBundleProfile.TotalPrice,
		SavedAmount:         valueAddBundleProfile.SavedAmount,
		DiscountPriceStatus: valueAddBundleProfile.DiscountPriceStatus,
		Choose:              valueAddBundleProfile.Choose,
		AddBundleCommonUid:  valueAddBundleProfile.AddBundleCommonUid,
	}

	bundleOrderRecords := &model.BundleOrderRecords{}
	bundleOrderRecords, err = dao.BundleOrderRecordsDetailByAddUid(req.Uuid)
	if err != nil {
		err = nil
	} else {
		res.PayTime = bundleOrderRecords.PayTime
	}

	res.Msg = "SUCCESS"
	return
}

//*******************************************************************新增值服务***********************

// 增值套餐保存(无则新增,有则更新)
func SaveValueAddService(in *bundle.ValueAddServiceLang) (res *bundle.SaveResponse, err error) {
	res = &bundle.SaveResponse{}
	if in.Language == "" {
		return res, errors.New("语言参数不能为空")
	}
	var options model.PriceOptions
	if in.OriginalPrice == "" {
		return res, errors.New("原价参数不能为空")
	}
	originalPrice, parseErr := strconv.ParseFloat(in.OriginalPrice, 32)
	if parseErr != nil {
		return res, parseErr
	}
	index := 1
	for _, option := range in.Options {
		price, parseErr := strconv.ParseFloat(option.Price, 32)
		if parseErr != nil {
			return res, parseErr
		}
		if option.Num < 0 || option.Num > 99 {
			return res, errors.New("数量参数需为0-99")
		}
		if price > originalPrice {
			return res, errors.New("优惠单价需小于等于原价")
		}
		options = append(options, &model.PriceOption{
			Id:     int32(index),
			Num:    option.Num,
			Symbol: option.Symbol,
			Price:  float32(price),
		})
		index++
	}
	ok, err := model.ValidateOptions(options)
	if !ok {
		return res, err
	}
	valueAddService := &model.ValueAddService{
		ServiceName: in.ServiceName,
		ServiceType: in.ServiceType,
	}
	valueAddServiceLang := &model.ValueAddServiceLang{
		ServiceName:   in.ServiceName,
		ServiceType:   in.ServiceType,
		PriceMode:     int32(in.PriceMode),
		OriginalPrice: float32(originalPrice),
		Unit:          in.Unit,
		Language:      in.Language,
		PriceType:     in.PriceType,
		Options:       options,
	}
	if in.Uuid == "" && in.Language != msg.ZH_CN {
		return res, errors.New("请先新增简体中文套餐,再添加其他语言版本")
	}
	tx := app.ModuleClients.BundleDB.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	// 检查当前语言套餐是否存在
	_, err = dao.ValueAddServiceDetailByUuidAndLanguage(in.Uuid, in.Language)
	if err != nil {
		if err == gorm.ErrRecordNotFound { // 当前语言套餐不存在
			if in.Language != msg.ZH_CN {
				_, err = dao.ValueAddServiceDetailByUuidAndLanguage(in.Uuid, msg.ZH_CN)
				if err != nil {
					if err != gorm.ErrRecordNotFound {
						return res, errors.New("请先创建中文套餐")
					} else {
						// // 新语言补充:只要UUID存在即可直接插入新语言
						// if in.Uuid != "" {
						// 	valueAddServiceLang.UUID = in.Uuid
						// 	if err = dao.CreateValueAddServiceLang(tx, valueAddServiceLang); err != nil {
						// 		return res, errors.New("补充新语言套餐失败: " + err.Error())
						// 	}
						// 	res.Uuid = in.Uuid
						// 	res.Msg = "补充新语言套餐成功"
						// 	return
						// }
						return
					}
				}
			}
			if in.Language == msg.ZH_CN {
				valueAddService.UUID = utils.GetUUID()
				err = dao.CreateValueAddService(tx, valueAddService)
				if err != nil {
					return res, errors.New("保存中文语言套餐失败: " + err.Error())
				}
				valueAddServiceLang.UUID = valueAddService.UUID
				res.Uuid = valueAddService.UUID
				if err = dao.CreateValueAddServiceLang(tx, valueAddServiceLang); err != nil {
					return res, errors.New("保存语言套餐失败: " + err.Error())
				}
			}
			langList := []string{msg.ZH_TW, msg.EN, msg.DE_DE, msg.JS_JP}
			for _, lang := range langList {
				otherLang := model.ValueAddServiceLang{
					UUID:          valueAddServiceLang.UUID,
					ServiceName:   valueAddServiceLang.ServiceName,
					ServiceType:   valueAddServiceLang.ServiceType,
					PriceMode:     valueAddServiceLang.PriceMode,
					OriginalPrice: valueAddServiceLang.OriginalPrice,
					TotalPrice:    valueAddServiceLang.TotalPrice,
					Unit:          valueAddServiceLang.Unit,
					Language:      lang,
					PriceType:     valueAddServiceLang.PriceType,
					Options:       valueAddServiceLang.Options,
				}
				otherLang.Language = lang
				if err = dao.CreateValueAddServiceLang(tx, &otherLang); err != nil {
					return res, errors.New(fmt.Sprintf("保存%s语言套餐失败: ", lang) + err.Error())
				}
			}
			res.Msg = "保存成功"
			return
		} else {
			return
		}
	} else {
		// 已存在,进行更新
		if err := saveValueAddServiceHistory(tx, in.Uuid); err != nil {
			return res, err
		}
		//中文状态下,更新主表和语言表
		if in.Language == msg.ZH_CN {
			updateService := map[string]interface{}{
				"uuid":         in.Uuid,
				"service_name": in.ServiceName,
				"service_type": in.ServiceType,
			}
			if err = dao.UpdateValueAddService(tx, updateService); err != nil {
				return res, err
			}
		}
		// 查找所有与该增值服务关联的套餐,若币种不一致则取消关联并统计
		var cancelNum int64 = 0
		bundleToValueAddList, _ := dao.GetBundleToValueAddServiceByValueUid(in.Uuid)
		for _, rel := range bundleToValueAddList {
			bundleProfile, _ := dao.BundleDetailByUuidAndLanguage(rel.BundleUuid, in.Language)
			if bundleProfile != nil && bundleProfile.PriceType != in.PriceType {
				dao.DeleteBundleToValueAddService(tx, rel.BundleUuid, in.Uuid)
				cancelNum++
			}
		}
		//更新语言表
		updateLangService := map[string]interface{}{
			"uuid":           in.Uuid,
			"service_name":   in.ServiceName,
			"service_type":   in.ServiceType,
			"price_mode":     in.PriceMode,
			"original_price": in.OriginalPrice,
			"unit":           in.Unit,
			"price_type":     in.PriceType,
			"options":        options,
			"language":       in.Language,
		}
		if err := dao.UpdateValueAddServiceLang(tx, updateLangService); err != nil {
			return res, err
		}
		res.Uuid = in.Uuid
		res.Msg = "保存成功"
		res.CancelNum = cancelNum
	}
	return
}

// 增值套餐列表
func ValueAddServiceList(req *bundle.ValueAddServiceListRequest) (res *bundle.ValueAddServiceListResponse, err error) {
	res = &bundle.ValueAddServiceListResponse{}
	list, total, err := dao.ValueAddServiceList(req)
	if err != nil {
		res.Msg = msg.ErrorValueAddServiceList
		return res, err
	}
	for _, valueAddService := range list {
		serviceInfo := &bundle.ValueAddService{
			Uuid:        valueAddService.UUID,
			ServiceName: valueAddService.ServiceName,
			ServiceType: valueAddService.ServiceType,
		}
		for _, serviceLang := range valueAddService.ValueAddServiceLang {
			serviceLangInfo := &bundle.ValueAddServiceLang{
				Uuid:          valueAddService.UUID,
				ServiceName:   serviceLang.ServiceName,
				ServiceType:   serviceLang.ServiceType,
				PriceMode:     serviceLang.PriceMode,
				OriginalPrice: fmt.Sprintf("%.2f", serviceLang.OriginalPrice),
				Unit:          serviceLang.Unit,
				PriceType:     int64(serviceLang.PriceType),
				Language:      serviceLang.Language,
				CreatedAt:     time.Unix(serviceLang.CreatedAt, 0).Format("2006-01-02 15:04:05"),
				UpdatedAt:     time.Unix(serviceLang.UpdatedAt, 0).Format("2006-01-02 15:04:05"),
			}
			if serviceLang.Options != nil && len(serviceLang.Options) > 0 {
				var options []*bundle.ValueAddPriceOptions
				for _, option := range serviceLang.Options {
					var saveAmount decimal.Decimal
					if serviceLang.PriceMode == 1 {
						original := decimal.NewFromFloat(float64(serviceLang.OriginalPrice))
						price := decimal.NewFromFloat(float64(option.Price))
						num := decimal.NewFromInt(int64(option.Num))
						saveAmount = original.Sub(price).Mul(num)
					} else if serviceLang.PriceMode == 2 {
						original := decimal.NewFromFloat(float64(serviceLang.OriginalPrice))
						price := decimal.NewFromFloat(float64(option.Price))
						saveAmount = original.Sub(price)
					}
					options = append(options, &bundle.ValueAddPriceOptions{
						Id:         int64(option.Id),
						Num:        option.Num,
						Symbol:     option.Symbol,
						Price:      fmt.Sprintf("%.2f", option.Price),
						SaveAmount: saveAmount.StringFixed(2),
					})
				}
				serviceLangInfo.Options = options
			}
			serviceInfo.ServiceLang = append(serviceInfo.ServiceLang, serviceLangInfo)
		}
		res.ValueAddServiceList = append(res.ValueAddServiceList, serviceInfo)
	}
	res.Total = int32(total)
	res.Msg = msg.SuccessValueAddServiceList
	return

}

// 增值套餐详情
func ValueAddServiceDetail(req *bundle.ValueAddServiceDetailRequest) (res *bundle.ValueAddServiceDetailResponse, err error) {
	res = &bundle.ValueAddServiceDetailResponse{}
	valueAddService := &bundle.ValueAddService{}
	serviceLangs := []*bundle.ValueAddServiceLang{}
	if req.Uuid == "" {
		res.Msg = msg.ErrorValueAddServiceInfo
		return res, errors.New("uuid不能为空")
	}
	// if req.Language == "" {
	// 	res.Msg = msg.ErrorValueAddServiceInfo
	// 	return res, errors.New("语言选项不能为空")
	// }
	detail, err := dao.ValueAddServiceDetail(req.Uuid)
	if err != nil {
		res.Msg = msg.ErrorValueAddServiceInfo
		return res, err
	}
	if detail != nil && len(detail.ValueAddServiceLang) > 0 {
		valueAddService.Uuid = detail.UUID
		valueAddService.ServiceName = detail.ServiceName
		valueAddService.ServiceType = detail.ServiceType
		for _, serviceLang := range detail.ValueAddServiceLang {
			langOptions := []*bundle.ValueAddPriceOptions{}
			if serviceLang.Options != nil && len(serviceLang.Options) > 0 {
				for _, opt := range serviceLang.Options {
					var saveAmount decimal.Decimal
					if serviceLang.PriceMode == 1 {
						original := decimal.NewFromFloat(float64(serviceLang.OriginalPrice))
						price := decimal.NewFromFloat(float64(opt.Price))
						num := decimal.NewFromInt(int64(opt.Num))
						saveAmount = original.Sub(price).Mul(num)
					} else if serviceLang.PriceMode == 2 {
						original := decimal.NewFromFloat(float64(serviceLang.OriginalPrice))
						price := decimal.NewFromFloat(float64(opt.Price))
						saveAmount = original.Sub(price)
					}
					langOptions = append(langOptions, &bundle.ValueAddPriceOptions{
						Id:         int64(opt.Id),
						Num:        opt.Num,
						Symbol:     opt.Symbol,
						Price:      fmt.Sprintf("%.2f", opt.Price),
						SaveAmount: saveAmount.StringFixed(2),
					})
				}
			}
			serviceLangInfo := &bundle.ValueAddServiceLang{
				Uuid:          serviceLang.UUID,
				ServiceName:   serviceLang.ServiceName,
				ServiceType:   serviceLang.ServiceType,
				Language:      serviceLang.Language,
				PriceMode:     serviceLang.PriceMode,
				OriginalPrice: fmt.Sprintf("%.2f", serviceLang.OriginalPrice),
				Unit:          serviceLang.Unit,
				PriceType:     int64(serviceLang.PriceType),
				Options:       langOptions,
				CreatedAt:     time.Unix(serviceLang.CreatedAt, 0).Format("2006-01-02 15:04:05"),
				UpdatedAt:     time.Unix(serviceLang.UpdatedAt, 0).Format("2006-01-02 15:04:05"),
			}
			serviceLangs = append(serviceLangs, serviceLangInfo)
		}
	}
	valueAddService.ServiceLang = serviceLangs

	res.ValueAddService = valueAddService
	res.Msg = msg.SuccessValueAddServiceInfo
	return
}

func saveValueAddServiceHistory(tx *gorm.DB, uuid string) (err error) {
	// 保存历史记录
	data, err := dao.GetValueAddServiceDetailByUuid(tx, uuid)
	if err != nil {
		return errors.New("查询增值服务详情失败: " + err.Error())
	}
	j, err := json.Marshal(data)
	if err != nil {
		return errors.New("json转换失败: " + err.Error())
	}
	history := &model.ValueAddServiceHistory{
		Uuid:            uuid,
		ValueAddService: datatypes.JSON(j),
		//Operator:      operator,
		//OperatorId:    operatorId,
	}
	if err := tx.Create(history).Error; err != nil {
		return errors.New("保存增值服务历史记录失败: " + err.Error())
	}
	return nil
}
func ValueAddServiceDetailByUuidAndLanguage(req *bundle.ValueAddServiceDetailRequest) (res *bundle.ValueAddServiceLang, err error) {
	res = &bundle.ValueAddServiceLang{}
	if req.Uuid == "" {
		return res, errors.New("uuid不能为空")
	}
	if req.Language == "" {
		return res, errors.New("语言选项不能为空")
	}
	detail, err := dao.ValueAddServiceDetailByUuidAndLanguage(req.Uuid, req.Language)
	if err != nil {
		return res, err
	}
	if detail == nil {
		return res, errors.New("增值服务不存在")
	}
	langOptions := []*bundle.ValueAddPriceOptions{}
	if detail.Options != nil && len(detail.Options) > 0 {
		for _, opt := range detail.Options {
			var saveAmount decimal.Decimal
			if detail.PriceMode == 1 {
				original := decimal.NewFromFloat(float64(detail.OriginalPrice))
				price := decimal.NewFromFloat(float64(opt.Price))
				num := decimal.NewFromInt(int64(opt.Num))
				saveAmount = original.Sub(price).Mul(num)
			} else if detail.PriceMode == 2 {
				original := decimal.NewFromFloat(float64(detail.OriginalPrice))
				price := decimal.NewFromFloat(float64(opt.Price))
				saveAmount = original.Sub(price)
			}
			langOptions = append(langOptions, &bundle.ValueAddPriceOptions{
				Id:         int64(opt.Id),
				Num:        opt.Num,
				Symbol:     opt.Symbol,
				Price:      fmt.Sprintf("%.2f", opt.Price),
				SaveAmount: saveAmount.StringFixed(2),
			})
		}
	}
	res = &bundle.ValueAddServiceLang{
		Uuid:          detail.UUID,
		ServiceName:   detail.ServiceName,
		ServiceType:   detail.ServiceType,
		Language:      detail.Language,
		PriceMode:     detail.PriceMode,
		OriginalPrice: fmt.Sprintf("%.2f", detail.OriginalPrice),
		Unit:          detail.Unit,
		PriceType:     int64(detail.PriceType),
		Options:       langOptions,
		CreatedAt:     time.Unix(detail.CreatedAt, 0).Format("2006-01-02 15:04:05"),
		UpdatedAt:     time.Unix(detail.UpdatedAt, 0).Format("2006-01-02 15:04:05"),
	}
	return
}
func CalculatePrice(req *bundle.CalculatePriceRequest) (res *bundle.CalculatePriceResponse, err error) {
	res = &bundle.CalculatePriceResponse{}
	if req.Uuid == "" {
		return res, errors.New("uuid不能为空")
	}
	if req.Language == "" {
		return res, errors.New("语言选项不能为空")
	}
	detail, err := dao.ValueAddServiceDetailByUuidAndLanguage(req.Uuid, req.Language)
	if err != nil {
		return res, err
	}
	if detail == nil {
		return res, errors.New("增值服务不存在")
	}
	// langOptions := []*bundle.ValueAddPriceOptions{}
	// if detail.Options != nil && len(detail.Options) > 0 {
	// 	for _, opt := range detail.Options {
	// 		langOptions = append(langOptions, &bundle.ValueAddPriceOptions{
	// 			Id:     int64(opt.Id),
	// 			Num:    opt.Num,
	// 			Symbol: opt.Symbol,
	// 			Price:  fmt.Sprintf("%.2f", opt.Price),
	// 		})
	// 	}
	// }
	price, err := detail.Options.CalculatePrice(detail.PriceMode, req.Num)
	if err != nil {
		return res, err
	}
	res.Price = price
	return
}
func BatchGetValueAddServiceLang(req *bundle.BatchGetValueAddServiceLangRequest) (res *bundle.BatchGetValueAddServiceLangResponse, err error) {
	res = &bundle.BatchGetValueAddServiceLangResponse{}
	if req.Uuids == nil || len(req.Uuids) == 0 {
		return res, errors.New("uuid不能为空")
	}
	if req.Language == "" {
		return res, errors.New("语言选项不能为空")
	}
	detail, err := dao.BatchGetValueAddServiceLang(req.Uuids, req.Language)
	if err != nil {
		return res, err
	}
	for _, v := range detail {
		langOptions := []*bundle.ValueAddPriceOptions{}
		if v.Options != nil && len(v.Options) > 0 {
			for _, opt := range v.Options {
				var saveAmount decimal.Decimal
				if v.PriceMode == 1 {
					original := decimal.NewFromFloat(float64(v.OriginalPrice))
					price := decimal.NewFromFloat(float64(opt.Price))
					num := decimal.NewFromInt(int64(opt.Num))
					saveAmount = original.Sub(price).Mul(num)
				} else if v.PriceMode == 2 {
					original := decimal.NewFromFloat(float64(v.OriginalPrice))
					price := decimal.NewFromFloat(float64(opt.Price))
					saveAmount = original.Sub(price)
				}
				langOptions = append(langOptions, &bundle.ValueAddPriceOptions{
					Id:         int64(opt.Id),
					Num:        opt.Num,
					Symbol:     opt.Symbol,
					Price:      fmt.Sprintf("%.2f", opt.Price),
					SaveAmount: saveAmount.StringFixed(2),
				})
			}
		}
		res.ValueAddServiceLangList = append(res.ValueAddServiceLangList, &bundle.ValueAddServiceLang{
			Uuid:          v.UUID,
			ServiceName:   v.ServiceName,
			ServiceType:   v.ServiceType,
			Language:      v.Language,
			PriceMode:     v.PriceMode,
			OriginalPrice: fmt.Sprintf("%.2f", v.OriginalPrice),
			Unit:          v.Unit,
			PriceType:     int64(v.PriceType),
			Options:       langOptions,
		})
	}
	return
}