package db

import (
	"context"
	"fmt"
	"github.com/issue9/conv"
	"log"
	"strconv"
	"time"
	"youngee_b_api/model/gorm_model"
	"youngee_b_api/model/http_model"
	"youngee_b_api/util"

	"gorm.io/gorm"
)

func CreateEnterprise(ctx context.Context, newEnterprise gorm_model.Enterprise) (*string, error) {
	db := GetReadDB(ctx)
	err := db.Create(&newEnterprise).Error
	if err != nil {
		return nil, err
	}
	return &newEnterprise.EnterpriseID, nil
}

// GetEnterpriseByUID 用户ID查找
func GetEnterpriseByUID(ctx context.Context, userID int64) (*gorm_model.Enterprise, error) {
	db := GetReadDB(ctx)
	enterprise := gorm_model.Enterprise{}
	err := db.Where("user_id = ?", userID).First(&enterprise).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		} else {
			return nil, err
		}
	}
	return &enterprise, nil
}

// GetEnterpriseByEnterpriseID 企业ID查找
func GetEnterpriseByEnterpriseID(ctx context.Context, EnterpriseID string) (*gorm_model.Enterprise, error) {
	db := GetReadDB(ctx)
	enterprise := gorm_model.Enterprise{}
	err := db.Where("enterprise_id = ?", EnterpriseID).First(&enterprise).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		} else {
			return nil, err
		}
	}
	return &enterprise, nil
}

// GetEnterpriseBalance 获取企业可用余额等信息
func GetEnterpriseBalance(ctx context.Context, EnterpriseID string) (*http_model.EnterpriseBalanceData, error) {
	db := GetReadDB(ctx)
	enterprise := gorm_model.Enterprise{}
	err := db.Where("enterprise_id = ?", EnterpriseID).First(&enterprise).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		} else {
			return nil, err
		}
	}
	var Invoicing float64
	var BillableAmount float64
	db1 := GetReadDB(ctx)
	db1.Model(gorm_model.YounggeeInvoiceRecord{}).Select("sum(invoice_amount) as Invoicing").
		Where("enterprise_id = ? AND status = 1", EnterpriseID).Find(&Invoicing)
	Invoicing, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", Invoicing), 64)
	db2 := GetReadDB(ctx)
	db2.Model(gorm_model.YounggeeRechargeRecord{}).Select("sum(recharge_amount) as BillableAmount").
		Where("enterprise_id = ? AND status = 2 AND invoice_status = 2", EnterpriseID).Find(&BillableAmount)
	BillableAmount, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", BillableAmount), 64)
	db3 := GetReadDB(ctx)
	var Recharging float64
	db3.Model(gorm_model.YounggeeRechargeRecord{}).Select("sum(recharge_amount) as Recharging").
		Where("enterprise_id = ? AND status = 1 AND invoice_status = 1", EnterpriseID).Find(&Recharging)
	Recharging, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", Recharging), 64)
	res := &http_model.EnterpriseBalanceData{
		Balance:          enterprise.Balance,
		FrozenBalance:    enterprise.FrozenBalance,
		AvailableBalance: enterprise.AvailableBalance,
		Recharging:       Recharging,
		BillableAmount:   BillableAmount,
		Invoicing:        Invoicing,
	}
	return res, nil
}

// 支付-修改企业账户余额
func UpdateEnterpriseBalance(ctx context.Context, EnterpriseID string, balance float64, availableBalance float64, frozenBalance float64) (*float64, error) {
	db := GetReadDB(ctx)
	err := db.Model(gorm_model.Enterprise{}).Where("enterprise_id", EnterpriseID).
		Updates(map[string]interface{}{"balance": gorm.Expr("balance + ?", balance), "available_balance": gorm.Expr("available_balance + ?", availableBalance), "frozen_balance": gorm.Expr("frozen_balance + ?", frozenBalance)}).Error
	if err != nil {
		return nil, err
	}
	enterprise := gorm_model.Enterprise{}
	err = db.Model(gorm_model.Enterprise{}).Where("enterprise_id", EnterpriseID).Scan(&enterprise).Error
	if err != nil {
		return nil, err
	}

	return &enterprise.Balance, nil
}

func MakeRechargeId(ctx context.Context, EnterpriseID string) string {
	db := GetReadDB(ctx)
	// 1、年月日
	year := time.Now().Year()
	month := time.Now().Month()
	day := time.Now().Day()
	yearData, _ := util.GetDayNum("year", year)
	monthData, _ := util.GetDayNum("month", int(month))
	dayData, _ := util.GetDayNum("day", day)
	sum := 0
	sum += dayData + monthData
	leap := 0
	if (yearData%400 == 0) || ((yearData%4 == 0) && (yearData%100 != 0)) {
		leap = 1
	}
	if (leap == 1) && (monthData > 2) {
		sum += 1
	}
	last := ""
	rechargeIdPrefix := "8" + EnterpriseID[len(EnterpriseID)-2:] + conv.MustString(sum)
	var rechargeIdLast string
	err := db.Model(gorm_model.YounggeeRechargeRecord{}).Select("recharge_id").Where("recharge_id like ?", rechargeIdPrefix+"%").
		Last(&rechargeIdLast).Error
	if err != nil {
		last = "0"
	} else {
		last = rechargeIdLast[len(rechargeIdLast)-2:]
	}
	var lastInt int
	lastInt = conv.MustInt(last)
	if lastInt+1 < 10 {
		last = "0" + conv.MustString(conv.MustInt(last)+1)
	} else {
		last = conv.MustString(conv.MustInt(last) + 1)
	}
	return rechargeIdPrefix + last
}

func RechargeAmount(ctx context.Context, EnterpriseID string, Amount float64, phone string) error {
	db := GetReadDB(ctx)
	err := db.Model(gorm_model.Enterprise{}).Where("enterprise_id", EnterpriseID).
		Updates(map[string]interface{}{"balance": gorm.Expr("balance + ?", Amount), "available_balance": gorm.Expr("available_balance + ?", Amount)}).Error
	if err != nil {
		return err
	}
	//enterprise := gorm_model.Enterprise{}
	//err = db.Model(gorm_model.Enterprise{}).Where("enterprise_id", EnterpriseID).Scan(&enterprise).Error
	//if err != nil {
	//	return err
	//}
	rechargeId := MakeRechargeId(ctx, EnterpriseID)
	err = db.Model(gorm_model.YounggeeRechargeRecord{}).Create(&gorm_model.YounggeeRechargeRecord{
		RechargeID:         rechargeId,
		RechargeAmount:     Amount,
		EnterpriseID:       EnterpriseID,
		Status:             2,
		InvoiceStatus:      2,
		CommitAt:           time.Now(),
		RechargeMethod:     3,
		TransferVoucherUrl: "--",
		Phone:              phone,
		ConfirmAt:          time.Now(),
	}).Error
	if err != nil {
		return err
	}
	return nil
}

func TransferToPublic(ctx context.Context, Amount float64, phone string, EnterpriseID string, transferVoucherUrl string) error {
	db := GetReadDB(ctx)
	rechargeId := MakeRechargeId(ctx, EnterpriseID)
	fmt.Println("Amount:", Amount)
	err := db.Model(gorm_model.YounggeeRechargeRecord{}).Create(&gorm_model.YounggeeRechargeRecord{
		RechargeID:         rechargeId,
		RechargeAmount:     Amount,
		EnterpriseID:       EnterpriseID,
		Status:             1,
		InvoiceStatus:      1,
		CommitAt:           time.Now(),
		Phone:              phone,
		RechargeMethod:     1,
		TransferVoucherUrl: transferVoucherUrl,
		ConfirmAt:          time.Now(),
	}).Error
	if err != nil {
		return err
	}
	db1 := GetReadDB(ctx)
	err = db1.Model(gorm_model.Enterprise{}).Where("enterprise_id = ?", EnterpriseID).Updates(
		map[string]interface{}{"recharging": gorm.Expr("recharging + ?", Amount)}).Error
	if err != nil {
		log.Println("[TransferToPublic] recharging modify failed:", err)
		return err
	}
	return nil
}

func UpdateEnterprise(ctx context.Context, EnterpriseID string, BusinessName string) error {
	db := GetReadDB(ctx)
	err := db.Model(gorm_model.Enterprise{}).Where("enterprise_id=?", EnterpriseID).Update("business_name", BusinessName).Error
	if err != nil {
		fmt.Println("Update Enterprise Failed!")
		return err
	}
	return nil
}
