package dao

import (
	"errors"
	"micro-bundle/internal/model"
	"micro-bundle/pb/bundle"
	"micro-bundle/pkg/app"
	"micro-bundle/pkg/utils"
	"strconv"
	"time"

	"dubbo.apache.org/dubbo-go/v3/common/logger"
	"github.com/duke-git/lancet/v2/datetime"

	"gorm.io/gorm"
)

func AddBundleExtendRecord(data model.BundleExtensionRecords) error {
	return app.ModuleClients.BundleDB.Transaction(func(tx *gorm.DB) error {
		if err := tx.Create(&data).Error; err != nil {
			return err
		}
		if data.AvailableDurationAdditional != 0 && data.TimeUnit != 0 {
			record := model.BundleOrderRecords{}
			if err := tx.Model(&model.BundleOrderRecords{}).Where(&model.BundleOrderRecords{CustomerID: strconv.Itoa(data.UserId)}).First(&record).Error; err != nil {
				return err
			}
			var expireTime time.Time
			if record.ExpirationTime != "" {
				et, _ := time.Parse(time.DateOnly, record.ExpirationTime)
				expireTime = et
			} else {
				expireTime = time.Now()
				logger.Infof("过期时间为空,使用默认过期时间" + expireTime.Format(time.DateTime))
			}

			switch data.TimeUnit {
			case 1:
				expireTime = datetime.AddDay(expireTime, int64(data.AvailableDurationAdditional))
			case 2:
				expireTime = datetime.AddMonth(expireTime, int64(data.AvailableDurationAdditional))
			case 3:
				expireTime = datetime.AddYear(expireTime, int64(data.AvailableDurationAdditional))
			default:
				return errors.New("时间单位有误")
			}
			record.ExpirationTime = expireTime.Format(time.DateOnly)
			return tx.Model(&model.BundleOrderRecords{}).Where(&model.BundleOrderRecords{UUID: record.UUID}).Updates(&record).Error
		}
		return nil
	})
}

func GetBundleExtendRecordList(req *bundle.BundleExtendRecordsListRequest) (data []model.BundleExtendRecordItemPo, total int64, err error) {
	session := app.ModuleClients.BundleDB.Table("fiee_bundle.bundle_extension_records AS ber").
		Select(`
			ber.*,
			u.nickname as user_name,
			u.tel_num as user_phone_number
	`).Joins("LEFT JOIN `micro-account`.`user` u on u.id = user_id")
	if req.User != "" {
		if utils.IsPhoneNumber(req.User) {
			session = session.Where("u.tel_num = ?", req.User)
		} else {
			session = session.Where("u.nickname like ?", req.User)
		}
	}
	if req.Operator != "" {
		if utils.IsPhoneNumber(req.Operator) {
			session = session.Where("ber.operator_phone_number = ?", req.Operator)
		} else {
			session = session.Where("ber.operator_name like ?", req.Operator)
		}
	}
	if req.Type != 0 {
		session = session.Where("ber.`type` = ?", req.Type)
	}
	if req.AssociatedOrderNumber != "" {
		session = session.Where("ber.associated_order_number like ?", "%"+req.AssociatedOrderNumber+"%")
	}
	if err = session.Count(&total).Error; err != nil {
		return
	}

	if req.Page != 0 && req.PageSize != 0 {
		session = session.Limit(int(req.PageSize)).Offset(int(req.Page-1) * int(req.PageSize))
	}
	err = session.Find(&data).Error
	return
}

func GetBundleBalanceList(req *bundle.GetBundleBalanceListReq) (data []model.BundleBalancePo, total int64, err error) {
	session := app.ModuleClients.BundleDB.Table("fiee_bundle.bundle_balance AS bb").
		Select(`
		bb .*,
		bor.expiration_time as expired_time,
		bor.bundle_name,
		bor.status,
		bor.uuid as order_uuid,
		u.nickname as user_name,
		u.tel_num as user_phone_number
	`).
		Joins("LEFT JOIN bundle_order_records bor on bor.customer_id = bb .user_id").
		Joins("LEFT JOIN `micro-account`.`user` u on u.id = bb.user_id")
	if req.UserName != "" {
		session = session.Where("u.nickname like ?", "%"+req.UserName+"%")
	}
	if req.Status != 0 {
		session = session.Where("bor.status = ?", req.Status)
	}
	if req.ExpiredTimeEnd != 0 {
		session = session.Where("bor.expiration_time <= ?", time.UnixMilli(req.ExpiredTimeEnd))
	}
	if req.ExpiredTimeStart != 0 {
		session = session.Where("bor.expiration_time >= ?", time.UnixMilli(req.ExpiredTimeStart))
	}
	err = session.Count(&total).Error
	if err != nil {
		return
	}
	if req.Page != 0 && req.PageSize != 0 {
		session = session.Limit(int(req.PageSize)).Offset(int(req.Page-1) * int(req.PageSize))
	}
	err = session.Find(&data).Error
	return
}

func GetBundleBalanceByUserId(req *bundle.GetBundleBalanceByUserIdReq) (data model.UserBundleBalancePo, err error) {
	err = app.ModuleClients.BundleDB.Table("fiee_bundle.bundle_balance AS bb").
		Select("bb .*,bor.uuid AS order_uuid, bor.bundle_name AS bundle_name, bor.status AS bundle_status, bor.pay_time AS pay_time, bor.expiration_time AS expired_time,bor.amount AS payment_amount").
		Joins("LEFT JOIN bundle_order_records bor ON bor.customer_id = bb.user_id").
		Joins("LEFT JOIN `micro-account`.`user` u ON u.id = bb.user_id").
		Where("bor.deleted_at IS NULL").
		Where("bb.user_id = ?", req.UserId).
		Where("bor.expiration_time > ?", time.Now()).
		First(&data).Error
	if err != nil {
		return
	}
	var additionalInfo model.UserBundleBalancePo
	err = app.ModuleClients.BundleDB.Model(&model.BundleExtensionRecords{}).
		Select("user_id, SUM(account_additional) as account_additional, SUM(images_additional) as images_additional, SUM(video_additional) as video_additional, SUM(data_additional) as data_additional").
		Where("type = 1"). // 手动扩展
		Where("user_id = ?", req.UserId).
		Where("created_at > ?", data.PayTime). // 判断扩展是否生效
		First(&additionalInfo).Error
	if err != nil {
		return
	}
	data.AccountAdditional = additionalInfo.AccountAdditional
	data.VideoAdditional = additionalInfo.VideoAdditional
	data.ImageAdditional = additionalInfo.ImageAdditional
	data.DataAnalysisAdditional = additionalInfo.DataAnalysisAdditional
	return
}

func AddBundleBalanceByUserId(data model.BundleBalance) error {
	return app.ModuleClients.BundleDB.Transaction(func(tx *gorm.DB) error {
		oldData := model.BundleBalance{}
		if err := tx.Model(&model.BundleBalance{}).Where("user_id = ?", data.UserId).Order("created_at desc").First(&oldData).Error; err != nil {
			return errors.New("用户还没有套餐信息")
		}
		newData := model.BundleBalance{
			Model: gorm.Model{
				ID: data.Model.ID,
			},
			UserId:                        oldData.UserId,
			OrderUUID:                     oldData.OrderUUID,
			AccountNumber:                 oldData.AccountNumber + data.AccountNumber,
			AccountConsumptionNumber:      oldData.AccountConsumptionNumber + data.AccountConsumptionNumber,
			VideoNumber:                   oldData.VideoNumber + data.VideoNumber,
			VideoConsumptionNumber:        oldData.VideoConsumptionNumber + data.VideoConsumptionNumber,
			ImageNumber:                   oldData.ImageNumber + data.ImageNumber,
			ImageConsumptionNumber:        oldData.ImageConsumptionNumber + data.ImageConsumptionNumber,
			DataAnalysisNumber:            oldData.DataAnalysisNumber + data.DataAnalysisNumber,
			DataAnalysisConsumptionNumber: oldData.DataAnalysisConsumptionNumber + data.DataAnalysisConsumptionNumber,
			ExpansionPacksNumber:          oldData.ExpansionPacksNumber + data.ExpansionPacksNumber,
		}

		if newData.AccountConsumptionNumber > newData.AccountNumber ||
			newData.VideoConsumptionNumber > newData.VideoNumber ||
			newData.ImageConsumptionNumber > newData.ImageNumber ||
			newData.DataAnalysisConsumptionNumber > newData.DataAnalysisNumber {
			return errors.New("套餐余量不足")
		}
		return tx.Model(&model.BundleBalance{}).Where("id = ?", oldData.ID).Updates(&newData).Error
	})
}

func CreateBundleBalance(data model.BundleBalance) error {
	return app.ModuleClients.BundleDB.Create(&data).Error
}

func GetUsedRecord(req *bundle.GetUsedRecordListReq) (data []model.CostLog, total int64, err error) {
	session := app.ModuleClients.BundleDB.Model(&model.CostLog{})
	if req.Title != "" {
		session = session.Where("title = ?", req.Title)
	}
	if req.Platform != 0 {
		session = session.Where("JSON_CONTAINS(platform_ids,?)", req.Platform)
	}
	if req.Account != 0 {
		session = session.Where("JSON_CONTAINS(media_names,?)", req.Account)
	}
	if req.SubmitTimeEnd != 0 {
		session = session.Where("submit_time <= ?", time.UnixMilli(req.SubmitTimeEnd))
	}
	if req.SubmitTimeStart != 0 {
		session = session.Where("submit_time >= ?", time.UnixMilli(req.SubmitTimeStart))
	}
	if req.User != "" {
		if utils.IsPhoneNumber(req.User) {
			session = session.Where("artist_phone = ?", req.User)
		} else {
			session = session.Where("artist_name like ?", "%"+req.User+"%")
		}
	}
	if req.Operator != "" {
		if utils.IsPhoneNumber(req.Operator) {
			session = session.Where("operator_phone = ?", req.Operator)
		} else {
			session = session.Where("operator_name like ?", "%"+req.Operator+"%")
		}
	}
	if req.Type != 0 {
		session = session.Where("work_category = ?", req.Type)
	}
	if err = session.Count(&total).Error; err != nil {
		return
	}
	if req.Page != 0 && req.PageSize != 0 {
		session = session.Offset(int(req.Page-1) * int(req.PageSize)).Limit(int(req.PageSize))
	}
	err = session.Find(&data).Error
	return
}

func GetImageWorkDetail(req *bundle.GetImageWorkDetailReq) (data model.CastWorkImage, err error) {
	err = app.ModuleClients.BundleDB.Where(&model.CastWorkImage{WorkUuid: req.WorkId}).First(&data).Error
	return
}

func GetVedioWorkDetail(req *bundle.GetVedioWorkDetailReq) (data model.CastWorkVideo, err error) {
	err = app.ModuleClients.BundleDB.Where(&model.CastWorkVideo{WorkUuid: req.WorkId}).First(&data).Error
	return
}

func ToBeComfirmedWorks(req *bundle.ToBeComfirmedWorksReq) (data []model.CastWorkLog, total int64, err error) {
	session := app.ModuleClients.BundleDB.Model(&model.CastWorkLog{}).Where(&model.CastWorkLog{
		ArtistUuid: req.ArtistUuid,
	})
	err = session.Count(&total).Error
	if err != nil {
		return
	}
	if req.Page != 0 && req.PageSize != 0 {
		session.Limit(int(req.PageSize)).Offset(int(req.Page-1) * int(req.PageSize))
	}

	err = session.Find(&data).Error
	return
}